src/SDL12_compat.c
changeset 116 911a1e7bf8b7
parent 115 ea2ce36617d5
child 117 9b264590d276
     1.1 --- a/src/SDL12_compat.c	Fri Mar 22 10:54:17 2019 -0400
     1.2 +++ b/src/SDL12_compat.c	Fri Mar 22 23:11:59 2019 -0400
     1.3 @@ -3678,10 +3678,18 @@
     1.4      return SDL20_Unsupported();
     1.5  }
     1.6  
     1.7 -static Uint32
     1.8 -SetTimerOld_Callback(Uint32 interval, void* param)
     1.9 +/* SDL 1.2 limited timers to a 10ms resolution. SDL 2.0 doesn't, so we might
    1.10 +   have to round. This is the equation 1.2 uses: */
    1.11 +static Uint32 RoundTimerTo12Resolution(const Uint32 ms)
    1.12  {
    1.13 -    return ((SDL12_TimerCallback)param)(interval);
    1.14 +    return (((ms + 10) - 1) / 10) * 10;
    1.15 +}
    1.16 +
    1.17 +
    1.18 +static Uint32 SDLCALL
    1.19 +SetTimerCallback12(Uint32 interval, void* param)
    1.20 +{
    1.21 +    return RoundTimerTo12Resolution(((SDL12_TimerCallback)param)(interval));
    1.22  }
    1.23  
    1.24  DECLSPEC int SDLCALL
    1.25 @@ -3695,7 +3703,8 @@
    1.26      }
    1.27  
    1.28      if (interval && callback) {
    1.29 -        compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
    1.30 +        interval = RoundTimerTo12Resolution(interval);
    1.31 +        compat_timer = SDL20_AddTimer(interval, SetTimerCallback12, callback);
    1.32          if (!compat_timer) {
    1.33              return -1;
    1.34          }
    1.35 @@ -3785,21 +3794,57 @@
    1.36          "This program should be fixed. No thread was actually harmed.\n");
    1.37  }
    1.38  
    1.39 +typedef struct SDL12_TimerID_Data
    1.40 +{
    1.41 +    SDL_TimerID timer_id;
    1.42 +    SDL12_NewTimerCallback callback;
    1.43 +    void *param;
    1.44 +} SDL12_TimerID_Data;
    1.45 +
    1.46  /* This changed from an opaque pointer to an int in 2.0. */
    1.47 -typedef struct _SDL12_TimerID *SDL12_TimerID;
    1.48 +typedef SDL12_TimerID_Data *SDL12_TimerID;
    1.49  SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
    1.50  
    1.51  
    1.52 +static Uint32 SDLCALL
    1.53 +AddTimerCallback12(Uint32 interval, void *param)
    1.54 +{
    1.55 +    SDL12_TimerID data = (SDL12_TimerID) param;
    1.56 +    return RoundTimerTo12Resolution(data->callback(interval, data->param));
    1.57 +}
    1.58 +
    1.59  DECLSPEC SDL12_TimerID SDLCALL
    1.60  SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
    1.61  {
    1.62 -    return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
    1.63 +    SDL12_TimerID data = (SDL12_TimerID) SDL_malloc(sizeof (SDL12_TimerID_Data));
    1.64 +    if (!data) {
    1.65 +        SDL20_OutOfMemory();
    1.66 +        return NULL;
    1.67 +    }
    1.68 +
    1.69 +    interval = RoundTimerTo12Resolution(interval);
    1.70 +    data->callback = callback;
    1.71 +    data->param = param;
    1.72 +    data->timer_id = SDL20_AddTimer(interval, AddTimerCallback12, data);
    1.73 +
    1.74 +    if (!data->timer_id) {
    1.75 +        SDL_free(data);
    1.76 +        return NULL;
    1.77 +    }
    1.78 +
    1.79 +    return data;
    1.80  }
    1.81  
    1.82  DECLSPEC SDL_bool SDLCALL
    1.83 -SDL_RemoveTimer(SDL12_TimerID id)
    1.84 +SDL_RemoveTimer(SDL12_TimerID data)
    1.85  {
    1.86 -    return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
    1.87 +    // !!! FIXME: classic 1.2 will safely return SDL_FALSE if this is a bogus
    1.88 +    // !!! FIXME:  timer. This code will dereference a bogus pointer.
    1.89 +    const SDL_bool retval = SDL20_RemoveTimer(data->timer_id);
    1.90 +    if (retval) {
    1.91 +        SDL_free(data);
    1.92 +    }
    1.93 +    return retval;
    1.94  }
    1.95  
    1.96