summaryrefslogtreecommitdiff
path: root/opl
diff options
context:
space:
mode:
Diffstat (limited to 'opl')
-rw-r--r--opl/opl.c8
-rw-r--r--opl/opl.h5
-rw-r--r--opl/opl_internal.h2
-rw-r--r--opl/opl_linux.c3
-rw-r--r--opl/opl_obsd.c3
-rw-r--r--opl/opl_queue.c13
-rw-r--r--opl/opl_queue.h2
-rw-r--r--opl/opl_sdl.c10
-rw-r--r--opl/opl_timer.c7
-rw-r--r--opl/opl_timer.h1
-rw-r--r--opl/opl_win32.c3
11 files changed, 53 insertions, 4 deletions
diff --git a/opl/opl.c b/opl/opl.c
index 0666476d..cc5b861d 100644
--- a/opl/opl.c
+++ b/opl/opl.c
@@ -452,3 +452,11 @@ void OPL_SetPaused(int paused)
}
}
+void OPL_AdjustCallbacks(float value)
+{
+ if (driver != NULL)
+ {
+ driver->adjust_callbacks_func(value);
+ }
+}
+
diff --git a/opl/opl.h b/opl/opl.h
index f0879b4d..d6a295b0 100644
--- a/opl/opl.h
+++ b/opl/opl.h
@@ -104,6 +104,11 @@ void OPL_InitRegisters(void);
void OPL_SetCallback(unsigned int ms, opl_callback_t callback, void *data);
+// Adjust callback times by the specified factor. For example, a value of
+// 0.5 will halve all remaining times.
+
+void OPL_AdjustCallbacks(float factor);
+
// Clear all OPL callbacks that have been set.
void OPL_ClearCallbacks(void);
diff --git a/opl/opl_internal.h b/opl/opl_internal.h
index 91a275d5..24e79644 100644
--- a/opl/opl_internal.h
+++ b/opl/opl_internal.h
@@ -32,6 +32,7 @@ typedef void (*opl_clear_callbacks_func)(void);
typedef void (*opl_lock_func)(void);
typedef void (*opl_unlock_func)(void);
typedef void (*opl_set_paused_func)(int paused);
+typedef void (*opl_adjust_callbacks_func)(float value);
typedef struct
{
@@ -46,6 +47,7 @@ typedef struct
opl_lock_func lock_func;
opl_unlock_func unlock_func;
opl_set_paused_func set_paused_func;
+ opl_adjust_callbacks_func adjust_callbacks_func;
} opl_driver_t;
// Sample rate to use when doing software emulation.
diff --git a/opl/opl_linux.c b/opl/opl_linux.c
index 12d21075..5df5d468 100644
--- a/opl/opl_linux.c
+++ b/opl/opl_linux.c
@@ -95,7 +95,8 @@ opl_driver_t opl_linux_driver =
OPL_Timer_ClearCallbacks,
OPL_Timer_Lock,
OPL_Timer_Unlock,
- OPL_Timer_SetPaused
+ OPL_Timer_SetPaused,
+ OPL_Timer_AdjustCallbacks,
};
#endif /* #ifdef HAVE_IOPERM */
diff --git a/opl/opl_obsd.c b/opl/opl_obsd.c
index 3313c1b2..39e0c156 100644
--- a/opl/opl_obsd.c
+++ b/opl/opl_obsd.c
@@ -110,7 +110,8 @@ opl_driver_t opl_openbsd_driver =
OPL_Timer_ClearCallbacks,
OPL_Timer_Lock,
OPL_Timer_Unlock,
- OPL_Timer_SetPaused
+ OPL_Timer_SetPaused,
+ OPL_Timer_AdjustCallbacks,
};
#endif /* #ifndef NO_OBSD_DRIVER */
diff --git a/opl/opl_queue.c b/opl/opl_queue.c
index d05cc6a1..ee87a19b 100644
--- a/opl/opl_queue.c
+++ b/opl/opl_queue.c
@@ -201,6 +201,19 @@ unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue)
}
}
+void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
+ unsigned int time, float factor)
+{
+ int offset;
+ int i;
+
+ for (i = 0; i < queue->num_entries; ++i)
+ {
+ offset = queue->entries[i].time - time;
+ queue->entries[i].time = time + (int) (offset * factor);
+ }
+}
+
#ifdef TEST
#include <assert.h>
diff --git a/opl/opl_queue.h b/opl/opl_queue.h
index b0f479f4..20ddeda9 100644
--- a/opl/opl_queue.h
+++ b/opl/opl_queue.h
@@ -32,6 +32,8 @@ void OPL_Queue_Push(opl_callback_queue_t *queue,
int OPL_Queue_Pop(opl_callback_queue_t *queue,
opl_callback_t *callback, void **data);
unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue);
+void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
+ unsigned int time, float factor);
#endif /* #ifndef OPL_QUEUE_H */
diff --git a/opl/opl_sdl.c b/opl/opl_sdl.c
index 4cd3dc7b..3ed7f784 100644
--- a/opl/opl_sdl.c
+++ b/opl/opl_sdl.c
@@ -486,6 +486,13 @@ static void OPL_SDL_SetPaused(int paused)
opl_sdl_paused = paused;
}
+static void OPL_SDL_AdjustCallbacks(float factor)
+{
+ SDL_LockMutex(callback_queue_mutex);
+ OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
+ SDL_UnlockMutex(callback_queue_mutex);
+}
+
opl_driver_t opl_sdl_driver =
{
"SDL",
@@ -497,6 +504,7 @@ opl_driver_t opl_sdl_driver =
OPL_SDL_ClearCallbacks,
OPL_SDL_Lock,
OPL_SDL_Unlock,
- OPL_SDL_SetPaused
+ OPL_SDL_SetPaused,
+ OPL_SDL_AdjustCallbacks,
};
diff --git a/opl/opl_timer.c b/opl/opl_timer.c
index 97e5ea8b..bab15687 100644
--- a/opl/opl_timer.c
+++ b/opl/opl_timer.c
@@ -224,6 +224,13 @@ void OPL_Timer_ClearCallbacks(void)
SDL_UnlockMutex(callback_queue_mutex);
}
+void OPL_Timer_AdjustCallbacks(float factor)
+{
+ SDL_LockMutex(callback_queue_mutex);
+ OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
+ SDL_UnlockMutex(callback_queue_mutex);
+}
+
void OPL_Timer_Lock(void)
{
SDL_LockMutex(timer_mutex);
diff --git a/opl/opl_timer.h b/opl/opl_timer.h
index 1febcac9..73544013 100644
--- a/opl/opl_timer.h
+++ b/opl/opl_timer.h
@@ -29,6 +29,7 @@ void OPL_Timer_ClearCallbacks(void);
void OPL_Timer_Lock(void);
void OPL_Timer_Unlock(void);
void OPL_Timer_SetPaused(int paused);
+void OPL_Timer_AdjustCallbacks(float factor);
#endif /* #ifndef OPL_TIMER_H */
diff --git a/opl/opl_win32.c b/opl/opl_win32.c
index c6c37803..ea7b9eeb 100644
--- a/opl/opl_win32.c
+++ b/opl/opl_win32.c
@@ -184,7 +184,8 @@ opl_driver_t opl_win32_driver =
OPL_Timer_ClearCallbacks,
OPL_Timer_Lock,
OPL_Timer_Unlock,
- OPL_Timer_SetPaused
+ OPL_Timer_SetPaused,
+ OPL_Timer_AdjustCallbacks,
};
#endif /* #ifdef _WIN32 */