cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_joystick.c (21148B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../SDL_internal.h"
     22
     23/* This is the joystick API for Simple DirectMedia Layer */
     24
     25#include "SDL.h"
     26#include "SDL_events.h"
     27#include "SDL_sysjoystick.h"
     28#include "SDL_assert.h"
     29#include "SDL_hints.h"
     30
     31#if !SDL_EVENTS_DISABLED
     32#include "../events/SDL_events_c.h"
     33#endif
     34
     35static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
     36static SDL_Joystick *SDL_joysticks = NULL;
     37static SDL_Joystick *SDL_updating_joystick = NULL;
     38
     39static void
     40SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
     41{
     42    if (hint && *hint == '1') {
     43        SDL_joystick_allows_background_events = SDL_TRUE;
     44    } else {
     45        SDL_joystick_allows_background_events = SDL_FALSE;
     46    }
     47}
     48
     49int
     50SDL_JoystickInit(void)
     51{
     52    int status;
     53
     54    /* See if we should allow joystick events while in the background */
     55    SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
     56                        SDL_JoystickAllowBackgroundEventsChanged, NULL);
     57
     58#if !SDL_EVENTS_DISABLED
     59    if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
     60        return -1;
     61    }
     62#endif /* !SDL_EVENTS_DISABLED */
     63
     64    status = SDL_SYS_JoystickInit();
     65    if (status >= 0) {
     66        status = 0;
     67    }
     68    return (status);
     69}
     70
     71/*
     72 * Count the number of joysticks attached to the system
     73 */
     74int
     75SDL_NumJoysticks(void)
     76{
     77    return SDL_SYS_NumJoysticks();
     78}
     79
     80/*
     81 * Get the implementation dependent name of a joystick
     82 */
     83const char *
     84SDL_JoystickNameForIndex(int device_index)
     85{
     86    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
     87        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
     88        return (NULL);
     89    }
     90    return (SDL_SYS_JoystickNameForDeviceIndex(device_index));
     91}
     92
     93/*
     94 * Open a joystick for use - the index passed as an argument refers to
     95 * the N'th joystick on the system.  This index is the value which will
     96 * identify this joystick in future joystick events.
     97 *
     98 * This function returns a joystick identifier, or NULL if an error occurred.
     99 */
    100SDL_Joystick *
    101SDL_JoystickOpen(int device_index)
    102{
    103    SDL_Joystick *joystick;
    104    SDL_Joystick *joysticklist;
    105    const char *joystickname = NULL;
    106
    107    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
    108        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
    109        return (NULL);
    110    }
    111
    112    joysticklist = SDL_joysticks;
    113    /* If the joystick is already open, return it
    114    * it is important that we have a single joystick * for each instance id
    115    */
    116    while (joysticklist) {
    117        if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id) {
    118                joystick = joysticklist;
    119                ++joystick->ref_count;
    120                return (joystick);
    121        }
    122        joysticklist = joysticklist->next;
    123    }
    124
    125    /* Create and initialize the joystick */
    126    joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
    127    if (joystick == NULL) {
    128        SDL_OutOfMemory();
    129        return NULL;
    130    }
    131
    132    SDL_memset(joystick, 0, (sizeof *joystick));
    133    if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) {
    134        SDL_free(joystick);
    135        return NULL;
    136    }
    137
    138    joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index);
    139    if (joystickname)
    140        joystick->name = SDL_strdup(joystickname);
    141    else
    142        joystick->name = NULL;
    143
    144    if (joystick->naxes > 0) {
    145        joystick->axes = (Sint16 *) SDL_malloc
    146            (joystick->naxes * sizeof(Sint16));
    147    }
    148    if (joystick->nhats > 0) {
    149        joystick->hats = (Uint8 *) SDL_malloc
    150            (joystick->nhats * sizeof(Uint8));
    151    }
    152    if (joystick->nballs > 0) {
    153        joystick->balls = (struct balldelta *) SDL_malloc
    154            (joystick->nballs * sizeof(*joystick->balls));
    155    }
    156    if (joystick->nbuttons > 0) {
    157        joystick->buttons = (Uint8 *) SDL_malloc
    158            (joystick->nbuttons * sizeof(Uint8));
    159    }
    160    if (((joystick->naxes > 0) && !joystick->axes)
    161        || ((joystick->nhats > 0) && !joystick->hats)
    162        || ((joystick->nballs > 0) && !joystick->balls)
    163        || ((joystick->nbuttons > 0) && !joystick->buttons)) {
    164        SDL_OutOfMemory();
    165        SDL_JoystickClose(joystick);
    166        return NULL;
    167    }
    168    if (joystick->axes) {
    169        SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
    170    }
    171    if (joystick->hats) {
    172        SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
    173    }
    174    if (joystick->balls) {
    175        SDL_memset(joystick->balls, 0,
    176            joystick->nballs * sizeof(*joystick->balls));
    177    }
    178    if (joystick->buttons) {
    179        SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
    180    }
    181
    182    /* Add joystick to list */
    183    ++joystick->ref_count;
    184    /* Link the joystick in the list */
    185    joystick->next = SDL_joysticks;
    186    SDL_joysticks = joystick;
    187
    188    SDL_SYS_JoystickUpdate(joystick);
    189
    190    return (joystick);
    191}
    192
    193
    194/*
    195 * Checks to make sure the joystick is valid.
    196 */
    197int
    198SDL_PrivateJoystickValid(SDL_Joystick * joystick)
    199{
    200    int valid;
    201
    202    if (joystick == NULL) {
    203        SDL_SetError("Joystick hasn't been opened yet");
    204        valid = 0;
    205    } else {
    206        valid = 1;
    207    }
    208
    209    if (joystick && joystick->closed) {
    210        valid = 0;
    211    }
    212
    213    return valid;
    214}
    215
    216/*
    217 * Get the number of multi-dimensional axis controls on a joystick
    218 */
    219int
    220SDL_JoystickNumAxes(SDL_Joystick * joystick)
    221{
    222    if (!SDL_PrivateJoystickValid(joystick)) {
    223        return (-1);
    224    }
    225    return (joystick->naxes);
    226}
    227
    228/*
    229 * Get the number of hats on a joystick
    230 */
    231int
    232SDL_JoystickNumHats(SDL_Joystick * joystick)
    233{
    234    if (!SDL_PrivateJoystickValid(joystick)) {
    235        return (-1);
    236    }
    237    return (joystick->nhats);
    238}
    239
    240/*
    241 * Get the number of trackballs on a joystick
    242 */
    243int
    244SDL_JoystickNumBalls(SDL_Joystick * joystick)
    245{
    246    if (!SDL_PrivateJoystickValid(joystick)) {
    247        return (-1);
    248    }
    249    return (joystick->nballs);
    250}
    251
    252/*
    253 * Get the number of buttons on a joystick
    254 */
    255int
    256SDL_JoystickNumButtons(SDL_Joystick * joystick)
    257{
    258    if (!SDL_PrivateJoystickValid(joystick)) {
    259        return (-1);
    260    }
    261    return (joystick->nbuttons);
    262}
    263
    264/*
    265 * Get the current state of an axis control on a joystick
    266 */
    267Sint16
    268SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
    269{
    270    Sint16 state;
    271
    272    if (!SDL_PrivateJoystickValid(joystick)) {
    273        return (0);
    274    }
    275    if (axis < joystick->naxes) {
    276        state = joystick->axes[axis];
    277    } else {
    278        SDL_SetError("Joystick only has %d axes", joystick->naxes);
    279        state = 0;
    280    }
    281    return (state);
    282}
    283
    284/*
    285 * Get the current state of a hat on a joystick
    286 */
    287Uint8
    288SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
    289{
    290    Uint8 state;
    291
    292    if (!SDL_PrivateJoystickValid(joystick)) {
    293        return (0);
    294    }
    295    if (hat < joystick->nhats) {
    296        state = joystick->hats[hat];
    297    } else {
    298        SDL_SetError("Joystick only has %d hats", joystick->nhats);
    299        state = 0;
    300    }
    301    return (state);
    302}
    303
    304/*
    305 * Get the ball axis change since the last poll
    306 */
    307int
    308SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
    309{
    310    int retval;
    311
    312    if (!SDL_PrivateJoystickValid(joystick)) {
    313        return (-1);
    314    }
    315
    316    retval = 0;
    317    if (ball < joystick->nballs) {
    318        if (dx) {
    319            *dx = joystick->balls[ball].dx;
    320        }
    321        if (dy) {
    322            *dy = joystick->balls[ball].dy;
    323        }
    324        joystick->balls[ball].dx = 0;
    325        joystick->balls[ball].dy = 0;
    326    } else {
    327        return SDL_SetError("Joystick only has %d balls", joystick->nballs);
    328    }
    329    return (retval);
    330}
    331
    332/*
    333 * Get the current state of a button on a joystick
    334 */
    335Uint8
    336SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
    337{
    338    Uint8 state;
    339
    340    if (!SDL_PrivateJoystickValid(joystick)) {
    341        return (0);
    342    }
    343    if (button < joystick->nbuttons) {
    344        state = joystick->buttons[button];
    345    } else {
    346        SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
    347        state = 0;
    348    }
    349    return (state);
    350}
    351
    352/*
    353 * Return if the joystick in question is currently attached to the system,
    354 *  \return SDL_FALSE if not plugged in, SDL_TRUE if still present.
    355 */
    356SDL_bool
    357SDL_JoystickGetAttached(SDL_Joystick * joystick)
    358{
    359    if (!SDL_PrivateJoystickValid(joystick)) {
    360        return SDL_FALSE;
    361    }
    362
    363    return SDL_SYS_JoystickAttached(joystick);
    364}
    365
    366/*
    367 * Get the instance id for this opened joystick
    368 */
    369SDL_JoystickID
    370SDL_JoystickInstanceID(SDL_Joystick * joystick)
    371{
    372    if (!SDL_PrivateJoystickValid(joystick)) {
    373        return (-1);
    374    }
    375
    376    return (joystick->instance_id);
    377}
    378
    379/*
    380 * Get the friendly name of this joystick
    381 */
    382const char *
    383SDL_JoystickName(SDL_Joystick * joystick)
    384{
    385    if (!SDL_PrivateJoystickValid(joystick)) {
    386        return (NULL);
    387    }
    388
    389    return (joystick->name);
    390}
    391
    392/*
    393 * Close a joystick previously opened with SDL_JoystickOpen()
    394 */
    395void
    396SDL_JoystickClose(SDL_Joystick * joystick)
    397{
    398    SDL_Joystick *joysticklist;
    399    SDL_Joystick *joysticklistprev;
    400
    401    if (!joystick) {
    402        return;
    403    }
    404
    405    /* First decrement ref count */
    406    if (--joystick->ref_count > 0) {
    407        return;
    408    }
    409
    410    if (joystick == SDL_updating_joystick) {
    411        return;
    412    }
    413
    414    SDL_SYS_JoystickClose(joystick);
    415
    416    joysticklist = SDL_joysticks;
    417    joysticklistprev = NULL;
    418    while (joysticklist) {
    419        if (joystick == joysticklist) {
    420            if (joysticklistprev) {
    421                /* unlink this entry */
    422                joysticklistprev->next = joysticklist->next;
    423            } else {
    424                SDL_joysticks = joystick->next;
    425            }
    426            break;
    427        }
    428        joysticklistprev = joysticklist;
    429        joysticklist = joysticklist->next;
    430    }
    431
    432    SDL_free(joystick->name);
    433
    434    /* Free the data associated with this joystick */
    435    SDL_free(joystick->axes);
    436    SDL_free(joystick->hats);
    437    SDL_free(joystick->balls);
    438    SDL_free(joystick->buttons);
    439    SDL_free(joystick);
    440}
    441
    442void
    443SDL_JoystickQuit(void)
    444{
    445    /* Make sure we're not getting called in the middle of updating joysticks */
    446    SDL_assert(!SDL_updating_joystick);
    447
    448    /* Stop the event polling */
    449    while (SDL_joysticks) {
    450        SDL_joysticks->ref_count = 1;
    451        SDL_JoystickClose(SDL_joysticks);
    452    }
    453
    454    /* Quit the joystick setup */
    455    SDL_SYS_JoystickQuit();
    456
    457#if !SDL_EVENTS_DISABLED
    458    SDL_QuitSubSystem(SDL_INIT_EVENTS);
    459#endif
    460}
    461
    462
    463static SDL_bool
    464SDL_PrivateJoystickShouldIgnoreEvent()
    465{
    466    if (SDL_joystick_allows_background_events) {
    467        return SDL_FALSE;
    468    }
    469
    470    if (SDL_WasInit(SDL_INIT_VIDEO)) {
    471        if (SDL_GetKeyboardFocus() == NULL) {
    472            /* Video is initialized and we don't have focus, ignore the event. */
    473            return SDL_TRUE;
    474        } else {
    475            return SDL_FALSE;
    476        }
    477    }
    478
    479    /* Video subsystem wasn't initialized, always allow the event */
    480    return SDL_FALSE;
    481}
    482
    483/* These are global for SDL_sysjoystick.c and SDL_events.c */
    484
    485int
    486SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
    487{
    488    int posted;
    489
    490    /* Make sure we're not getting garbage or duplicate events */
    491    if (axis >= joystick->naxes) {
    492        return 0;
    493    }
    494    if (value == joystick->axes[axis]) {
    495        return 0;
    496    }
    497
    498    /* We ignore events if we don't have keyboard focus, except for centering
    499     * events.
    500     */
    501    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
    502        if ((value > 0 && value >= joystick->axes[axis]) ||
    503            (value < 0 && value <= joystick->axes[axis])) {
    504            return 0;
    505        }
    506    }
    507
    508    /* Update internal joystick state */
    509    joystick->axes[axis] = value;
    510
    511    /* Post the event, if desired */
    512    posted = 0;
    513#if !SDL_EVENTS_DISABLED
    514    if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
    515        SDL_Event event;
    516        event.type = SDL_JOYAXISMOTION;
    517        event.jaxis.which = joystick->instance_id;
    518        event.jaxis.axis = axis;
    519        event.jaxis.value = value;
    520        posted = SDL_PushEvent(&event) == 1;
    521    }
    522#endif /* !SDL_EVENTS_DISABLED */
    523    return (posted);
    524}
    525
    526int
    527SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
    528{
    529    int posted;
    530
    531    /* Make sure we're not getting garbage or duplicate events */
    532    if (hat >= joystick->nhats) {
    533        return 0;
    534    }
    535    if (value == joystick->hats[hat]) {
    536        return 0;
    537    }
    538
    539    /* We ignore events if we don't have keyboard focus, except for centering
    540     * events.
    541     */
    542    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
    543        if (value != SDL_HAT_CENTERED) {
    544            return 0;
    545        }
    546    }
    547
    548    /* Update internal joystick state */
    549    joystick->hats[hat] = value;
    550
    551    /* Post the event, if desired */
    552    posted = 0;
    553#if !SDL_EVENTS_DISABLED
    554    if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
    555        SDL_Event event;
    556        event.jhat.type = SDL_JOYHATMOTION;
    557        event.jhat.which = joystick->instance_id;
    558        event.jhat.hat = hat;
    559        event.jhat.value = value;
    560        posted = SDL_PushEvent(&event) == 1;
    561    }
    562#endif /* !SDL_EVENTS_DISABLED */
    563    return (posted);
    564}
    565
    566int
    567SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
    568                        Sint16 xrel, Sint16 yrel)
    569{
    570    int posted;
    571
    572    /* Make sure we're not getting garbage events */
    573    if (ball >= joystick->nballs) {
    574        return 0;
    575    }
    576
    577    /* We ignore events if we don't have keyboard focus. */
    578    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
    579        return 0;
    580    }
    581
    582    /* Update internal mouse state */
    583    joystick->balls[ball].dx += xrel;
    584    joystick->balls[ball].dy += yrel;
    585
    586    /* Post the event, if desired */
    587    posted = 0;
    588#if !SDL_EVENTS_DISABLED
    589    if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
    590        SDL_Event event;
    591        event.jball.type = SDL_JOYBALLMOTION;
    592        event.jball.which = joystick->instance_id;
    593        event.jball.ball = ball;
    594        event.jball.xrel = xrel;
    595        event.jball.yrel = yrel;
    596        posted = SDL_PushEvent(&event) == 1;
    597    }
    598#endif /* !SDL_EVENTS_DISABLED */
    599    return (posted);
    600}
    601
    602int
    603SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
    604{
    605    int posted;
    606#if !SDL_EVENTS_DISABLED
    607    SDL_Event event;
    608
    609    switch (state) {
    610    case SDL_PRESSED:
    611        event.type = SDL_JOYBUTTONDOWN;
    612        break;
    613    case SDL_RELEASED:
    614        event.type = SDL_JOYBUTTONUP;
    615        break;
    616    default:
    617        /* Invalid state -- bail */
    618        return (0);
    619    }
    620#endif /* !SDL_EVENTS_DISABLED */
    621
    622    /* Make sure we're not getting garbage or duplicate events */
    623    if (button >= joystick->nbuttons) {
    624        return 0;
    625	}
    626	if (state == joystick->buttons[button]) {
    627		return 0;
    628	}
    629
    630    /* We ignore events if we don't have keyboard focus, except for button
    631     * release. */
    632    if (SDL_PrivateJoystickShouldIgnoreEvent()) {
    633        if (state == SDL_PRESSED) {
    634            return 0;
    635        }
    636    }
    637
    638    /* Update internal joystick state */
    639    joystick->buttons[button] = state;
    640
    641    /* Post the event, if desired */
    642    posted = 0;
    643#if !SDL_EVENTS_DISABLED
    644    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
    645        event.jbutton.which = joystick->instance_id;
    646        event.jbutton.button = button;
    647        event.jbutton.state = state;
    648        posted = SDL_PushEvent(&event) == 1;
    649    }
    650#endif /* !SDL_EVENTS_DISABLED */
    651    return (posted);
    652}
    653
    654void
    655SDL_JoystickUpdate(void)
    656{
    657    SDL_Joystick *joystick;
    658
    659    joystick = SDL_joysticks;
    660    while (joystick) {
    661        SDL_Joystick *joysticknext;
    662        /* save off the next pointer, the Update call may cause a joystick removed event
    663         * and cause our joystick pointer to be freed
    664         */
    665        joysticknext = joystick->next;
    666
    667        SDL_updating_joystick = joystick;
    668
    669        SDL_SYS_JoystickUpdate(joystick);
    670
    671        if (joystick->closed && joystick->uncentered) {
    672            int i;
    673
    674            /* Tell the app that everything is centered/unpressed...  */
    675            for (i = 0; i < joystick->naxes; i++)
    676                SDL_PrivateJoystickAxis(joystick, i, 0);
    677
    678            for (i = 0; i < joystick->nbuttons; i++)
    679                SDL_PrivateJoystickButton(joystick, i, 0);
    680
    681            for (i = 0; i < joystick->nhats; i++)
    682                SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
    683
    684            joystick->uncentered = SDL_FALSE;
    685        }
    686
    687        SDL_updating_joystick = NULL;
    688
    689        /* If the joystick was closed while updating, free it here */
    690        if (joystick->ref_count <= 0) {
    691            SDL_JoystickClose(joystick);
    692        }
    693
    694        joystick = joysticknext;
    695    }
    696
    697    /* this needs to happen AFTER walking the joystick list above, so that any
    698       dangling hardware data from removed devices can be free'd
    699     */
    700    SDL_SYS_JoystickDetect();
    701}
    702
    703int
    704SDL_JoystickEventState(int state)
    705{
    706#if SDL_EVENTS_DISABLED
    707    return SDL_DISABLE;
    708#else
    709    const Uint32 event_list[] = {
    710        SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
    711        SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED
    712    };
    713    unsigned int i;
    714
    715    switch (state) {
    716    case SDL_QUERY:
    717        state = SDL_DISABLE;
    718        for (i = 0; i < SDL_arraysize(event_list); ++i) {
    719            state = SDL_EventState(event_list[i], SDL_QUERY);
    720            if (state == SDL_ENABLE) {
    721                break;
    722            }
    723        }
    724        break;
    725    default:
    726        for (i = 0; i < SDL_arraysize(event_list); ++i) {
    727            SDL_EventState(event_list[i], state);
    728        }
    729        break;
    730    }
    731    return (state);
    732#endif /* SDL_EVENTS_DISABLED */
    733}
    734
    735/* return the guid for this index */
    736SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index)
    737{
    738    if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) {
    739        SDL_JoystickGUID emptyGUID;
    740        SDL_SetError("There are %d joysticks available", SDL_NumJoysticks());
    741        SDL_zero(emptyGUID);
    742        return emptyGUID;
    743    }
    744    return SDL_SYS_JoystickGetDeviceGUID(device_index);
    745}
    746
    747/* return the guid for this opened device */
    748SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick)
    749{
    750    if (!SDL_PrivateJoystickValid(joystick)) {
    751        SDL_JoystickGUID emptyGUID;
    752        SDL_zero(emptyGUID);
    753        return emptyGUID;
    754    }
    755    return SDL_SYS_JoystickGetGUID(joystick);
    756}
    757
    758/* convert the guid to a printable string */
    759void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID)
    760{
    761    static const char k_rgchHexToASCII[] = "0123456789abcdef";
    762    int i;
    763
    764    if ((pszGUID == NULL) || (cbGUID <= 0)) {
    765        return;
    766    }
    767
    768    for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) {
    769        /* each input byte writes 2 ascii chars, and might write a null byte. */
    770        /* If we don't have room for next input byte, stop */
    771        unsigned char c = guid.data[i];
    772
    773        *pszGUID++ = k_rgchHexToASCII[c >> 4];
    774        *pszGUID++ = k_rgchHexToASCII[c & 0x0F];
    775    }
    776    *pszGUID = '\0';
    777}
    778
    779
    780/*-----------------------------------------------------------------------------
    781 * Purpose: Returns the 4 bit nibble for a hex character
    782 * Input  : c -
    783 * Output : unsigned char
    784 *-----------------------------------------------------------------------------*/
    785static unsigned char nibble(char c)
    786{
    787    if ((c >= '0') && (c <= '9')) {
    788        return (unsigned char)(c - '0');
    789    }
    790
    791    if ((c >= 'A') && (c <= 'F')) {
    792        return (unsigned char)(c - 'A' + 0x0a);
    793    }
    794
    795    if ((c >= 'a') && (c <= 'f')) {
    796        return (unsigned char)(c - 'a' + 0x0a);
    797    }
    798
    799    /* received an invalid character, and no real way to return an error */
    800    /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */
    801    return 0;
    802}
    803
    804
    805/* convert the string version of a joystick guid to the struct */
    806SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID)
    807{
    808    SDL_JoystickGUID guid;
    809    int maxoutputbytes= sizeof(guid);
    810    size_t len = SDL_strlen(pchGUID);
    811    Uint8 *p;
    812    size_t i;
    813
    814    /* Make sure it's even */
    815    len = (len) & ~0x1;
    816
    817    SDL_memset(&guid, 0x00, sizeof(guid));
    818
    819    p = (Uint8 *)&guid;
    820    for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) {
    821        *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]);
    822    }
    823
    824    return guid;
    825}
    826
    827
    828/* vi: set ts=4 sw=4 expandtab: */