mirror of https://github.com/snes9xgit/snes9x.git
Add threaded APU option.
This commit is contained in:
parent
5285ec4e9d
commit
045f68bb26
187
apu/apu.cpp
187
apu/apu.cpp
|
@ -210,49 +210,122 @@
|
|||
namespace SNES
|
||||
{
|
||||
#include "bapu/dsp/blargg_endian.h"
|
||||
|
||||
CPU cpu;
|
||||
CPU cpu;
|
||||
}
|
||||
|
||||
namespace spc
|
||||
{
|
||||
static apu_callback sa_callback = NULL;
|
||||
static void *extra_data = NULL;
|
||||
static apu_callback sa_callback = NULL;
|
||||
static void *extra_data = NULL;
|
||||
|
||||
static bool8 sound_in_sync = TRUE;
|
||||
static bool8 sound_enabled = FALSE;
|
||||
static bool8 sound_in_sync = TRUE;
|
||||
static bool8 sound_enabled = FALSE;
|
||||
|
||||
static int buffer_size;
|
||||
static int lag_master = 0;
|
||||
static int lag = 0;
|
||||
static int buffer_size;
|
||||
static int lag_master = 0;
|
||||
static int lag = 0;
|
||||
|
||||
static uint8 *landing_buffer = NULL;
|
||||
static uint8 *shrink_buffer = NULL;
|
||||
static uint8 *landing_buffer = NULL;
|
||||
static uint8 *shrink_buffer = NULL;
|
||||
|
||||
static Resampler *resampler = NULL;
|
||||
static Resampler *resampler = NULL;
|
||||
|
||||
static int32 reference_time;
|
||||
static uint32 remainder;
|
||||
static int32 reference_time;
|
||||
static uint32 remainder;
|
||||
|
||||
static const int timing_hack_numerator = 256;
|
||||
static int timing_hack_denominator = 256;
|
||||
/* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup
|
||||
static const int timing_hack_numerator = 256;
|
||||
static int timing_hack_denominator = 256;
|
||||
/* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup
|
||||
if necessary on game load. */
|
||||
static uint32 ratio_numerator = APU_NUMERATOR_NTSC;
|
||||
static uint32 ratio_denominator = APU_DENOMINATOR_NTSC;
|
||||
static uint32 ratio_numerator = APU_NUMERATOR_NTSC;
|
||||
static uint32 ratio_denominator = APU_DENOMINATOR_NTSC;
|
||||
|
||||
static double dynamic_rate_multiplier = 1.0;
|
||||
static double dynamic_rate_multiplier = 1.0;
|
||||
static bool8 using_threads = FALSE;
|
||||
}
|
||||
|
||||
namespace msu
|
||||
{
|
||||
static int buffer_size;
|
||||
static uint8 *landing_buffer = NULL;
|
||||
static Resampler *resampler = NULL;
|
||||
static int resample_buffer_size = -1;
|
||||
static uint8 *resample_buffer = NULL;
|
||||
static int buffer_size;
|
||||
static uint8 *landing_buffer = NULL;
|
||||
static Resampler *resampler = NULL;
|
||||
static int resample_buffer_size = -1;
|
||||
static uint8 *resample_buffer = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_THREADS
|
||||
#include <pthread.h>
|
||||
static pthread_t worker_thread;
|
||||
|
||||
static pthread_mutex_t thread_running_mutex;
|
||||
static pthread_cond_t thread_running_cond;
|
||||
static bool8 thread_running = FALSE;
|
||||
static bool8 thread_exit = FALSE;
|
||||
|
||||
static void *S9xAPUWorkerThread(void *arg)
|
||||
{
|
||||
while (!thread_exit)
|
||||
{
|
||||
pthread_mutex_lock(&thread_running_mutex);
|
||||
|
||||
while (!thread_running)
|
||||
{
|
||||
pthread_cond_wait(&thread_running_cond, &thread_running_mutex);
|
||||
if (thread_exit)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&thread_running_mutex);
|
||||
|
||||
S9xAPUExecute();
|
||||
SNES::dsp.synchronize();
|
||||
|
||||
pthread_mutex_lock(&thread_running_mutex);
|
||||
thread_running = FALSE;
|
||||
pthread_cond_broadcast(&thread_running_cond);
|
||||
pthread_mutex_unlock(&thread_running_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void S9xAPUThreadWait(void)
|
||||
{
|
||||
pthread_mutex_lock(&thread_running_mutex);
|
||||
while (thread_running)
|
||||
{
|
||||
pthread_cond_wait(&thread_running_cond, &thread_running_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&thread_running_mutex);
|
||||
}
|
||||
|
||||
static void S9xAPUThreadRun(void)
|
||||
{
|
||||
pthread_mutex_lock(&thread_running_mutex);
|
||||
thread_running++;
|
||||
pthread_cond_broadcast(&thread_running_cond);
|
||||
pthread_mutex_unlock(&thread_running_mutex);
|
||||
}
|
||||
|
||||
static void S9xAPUThreadInit(void)
|
||||
{
|
||||
pthread_cond_init(&thread_running_cond, NULL);
|
||||
pthread_mutex_init(&thread_running_mutex, NULL);
|
||||
thread_running = TRUE;
|
||||
pthread_create(&worker_thread, NULL, S9xAPUWorkerThread, NULL);
|
||||
}
|
||||
|
||||
static void S9xAPUThreadDeinit(void)
|
||||
{
|
||||
S9xAPUThreadWait();
|
||||
thread_exit = TRUE;
|
||||
S9xAPUThreadRun();
|
||||
pthread_join(worker_thread, NULL);
|
||||
pthread_cond_destroy(&thread_running_cond);
|
||||
pthread_mutex_destroy(&thread_running_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void EightBitize (uint8 *, int);
|
||||
static void DeStereo (uint8 *, int);
|
||||
static void ReverseStereo (uint8 *, int);
|
||||
|
@ -481,7 +554,7 @@ void S9xUpdateDynamicRate (int avail, int buffer_size)
|
|||
UpdatePlaybackRate();
|
||||
}
|
||||
|
||||
static void UpdatePlaybackRate (void)
|
||||
static inline void UpdatePlaybackRate (void)
|
||||
{
|
||||
if (Settings.SoundInputRate == 0)
|
||||
Settings.SoundInputRate = APU_DEFAULT_INPUT_RATE;
|
||||
|
@ -568,6 +641,21 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
|
|||
|
||||
spc::sound_enabled = S9xOpenSoundDevice();
|
||||
|
||||
#ifdef USE_THREADS
|
||||
if (spc::using_threads)
|
||||
{
|
||||
S9xAPUThreadDeinit();
|
||||
}
|
||||
|
||||
spc::using_threads = Settings.ThreadedAPU & spc::sound_enabled;
|
||||
|
||||
if (spc::using_threads)
|
||||
{
|
||||
printf ("Using threaded APU.\n");
|
||||
S9xAPUThreadInit();
|
||||
}
|
||||
#endif
|
||||
|
||||
return (spc::sound_enabled);
|
||||
}
|
||||
|
||||
|
@ -607,6 +695,11 @@ bool8 S9xInitAPU (void)
|
|||
|
||||
void S9xDeinitAPU (void)
|
||||
{
|
||||
if (spc::using_threads)
|
||||
{
|
||||
S9xAPUThreadDeinit();
|
||||
}
|
||||
|
||||
if (spc::resampler)
|
||||
{
|
||||
delete spc::resampler;
|
||||
|
@ -658,14 +751,35 @@ static inline int S9xAPUGetClockRemainder (int32 cpucycles)
|
|||
spc::ratio_denominator;
|
||||
}
|
||||
|
||||
static inline void S9xAPUUpdateClock (void)
|
||||
{
|
||||
SNES::smp.clock -= S9xAPUGetClock (CPU.Cycles);
|
||||
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
|
||||
S9xAPUSetReferenceTime(CPU.Cycles);
|
||||
}
|
||||
|
||||
uint8 S9xAPUReadPort (int port)
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
if (spc::using_threads)
|
||||
{
|
||||
S9xAPUThreadWait();
|
||||
}
|
||||
#endif
|
||||
S9xAPUUpdateClock();
|
||||
S9xAPUExecute ();
|
||||
return ((uint8) SNES::smp.port_read (port & 3));
|
||||
}
|
||||
|
||||
void S9xAPUWritePort (int port, uint8 byte)
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
if (spc::using_threads)
|
||||
{
|
||||
S9xAPUThreadWait();
|
||||
}
|
||||
#endif
|
||||
S9xAPUUpdateClock();
|
||||
S9xAPUExecute ();
|
||||
SNES::cpu.port_write (port & 3, byte);
|
||||
}
|
||||
|
@ -677,16 +791,27 @@ void S9xAPUSetReferenceTime (int32 cpucycles)
|
|||
|
||||
void S9xAPUExecute (void)
|
||||
{
|
||||
SNES::smp.clock -= S9xAPUGetClock (CPU.Cycles);
|
||||
SNES::smp.enter ();
|
||||
|
||||
spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles);
|
||||
|
||||
S9xAPUSetReferenceTime(CPU.Cycles);
|
||||
}
|
||||
|
||||
void S9xAPUEndScanline (void)
|
||||
{
|
||||
#ifdef USE_THREADS
|
||||
if (spc::using_threads)
|
||||
{
|
||||
S9xAPUThreadWait();
|
||||
|
||||
if (SNES::dsp.spc_dsp.sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync)
|
||||
S9xLandSamples();
|
||||
|
||||
S9xAPUUpdateClock();
|
||||
S9xAPUThreadRun();
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
S9xAPUUpdateClock();
|
||||
S9xAPUExecute();
|
||||
SNES::dsp.synchronize();
|
||||
|
||||
|
|
|
@ -66,6 +66,12 @@ AC_ARG_WITH(xrandr,
|
|||
[],
|
||||
[with_xrandr=yes])
|
||||
|
||||
AC_ARG_WITH(pthreads,
|
||||
[AS_HELP_STRING([--with(out)-pthreads],
|
||||
[Enable POSIX Threads (default: with)])],
|
||||
[],
|
||||
[with_pthreads=yes])
|
||||
|
||||
AC_ARG_WITH(portaudio,
|
||||
[AS_HELP_STRING([--with(out)-portaudio],
|
||||
[Enable PortAudio sound driver support (default: with)])],
|
||||
|
@ -268,6 +274,17 @@ if test yes = "$with_oss" ; then
|
|||
])
|
||||
fi
|
||||
|
||||
THREADS=0
|
||||
if test yes = "$with_pthreads" ; then
|
||||
AC_CHECK_HEADER(pthread.h, [
|
||||
CFLAGS="$CFLAGS -DUSE_THREADS"
|
||||
LIBS="$LIBS -lpthread"
|
||||
THREADS=1
|
||||
],[
|
||||
echo "Cannot find pthreads. Disabling threading."
|
||||
])
|
||||
fi
|
||||
|
||||
ALSA=0
|
||||
ALSA_CFLAGS=""
|
||||
ALSA_LIBS=""
|
||||
|
|
|
@ -255,6 +255,7 @@ Snes9xConfig::load_defaults (void)
|
|||
Settings.SoundSync = 1;
|
||||
Settings.DynamicRateControl = 1;
|
||||
Settings.DynamicRateLimit = 5;
|
||||
Settings.ThreadedAPU = FALSE;
|
||||
Settings.HDMATimingHack = 100;
|
||||
Settings.ApplyCheats = 1;
|
||||
|
||||
|
@ -406,6 +407,7 @@ Snes9xConfig::save_config_file (void)
|
|||
xml_out_int (xml, "sound_sync", Settings.SoundSync);
|
||||
xml_out_int (xml, "dynamic_rate_control", Settings.DynamicRateControl);
|
||||
xml_out_int (xml, "dynamic_rate_limit", Settings.DynamicRateLimit);
|
||||
xml_out_int (xml, "threaded_apu", Settings.ThreadedAPU);
|
||||
|
||||
/* Snes9X core-stored variables */
|
||||
xml_out_int (xml, "transparency", Settings.Transparency);
|
||||
|
@ -677,6 +679,10 @@ Snes9xConfig::set_option (const char *name, const char *value)
|
|||
Settings.DynamicRateLimit = atoi (value);
|
||||
Settings.DynamicRateLimit = CLAMP (Settings.DynamicRateLimit, 1, 1000);
|
||||
}
|
||||
else if (!strcasecmp (name, "threaded_apu"))
|
||||
{
|
||||
Settings.ThreadedAPU = atoi (value);
|
||||
}
|
||||
else if (!strcasecmp (name, "gaussian_interpolation"))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -678,6 +678,7 @@ Snes9xPreferences::move_settings_to_dialog (void)
|
|||
set_check ("sync_sound", Settings.SoundSync);
|
||||
set_check ("dynamic_rate_control", Settings.DynamicRateControl);
|
||||
set_spin ("dynamic_rate_limit", Settings.DynamicRateLimit / 1000.0);
|
||||
set_check ("threaded_apu", Settings.ThreadedAPU);
|
||||
set_spin ("rewind_buffer_size", config->rewind_buffer_size);
|
||||
set_spin ("rewind_granularity", config->rewind_granularity);
|
||||
|
||||
|
@ -770,7 +771,8 @@ Snes9xPreferences::get_settings_from_dialog (void)
|
|||
(7 - (get_combo ("playback_combo")))) ||
|
||||
(config->sound_input_rate != get_slider ("sound_input_rate")) ||
|
||||
(Settings.SoundSync != get_check ("sync_sound")) ||
|
||||
(Settings.DynamicRateControl != get_check ("dynamic_rate_control"))
|
||||
(Settings.DynamicRateControl != get_check ("dynamic_rate_control")) ||
|
||||
(Settings.ThreadedAPU != get_check ("threaded_apu"))
|
||||
)
|
||||
{
|
||||
sound_needs_restart = 1;
|
||||
|
@ -836,6 +838,7 @@ Snes9xPreferences::get_settings_from_dialog (void)
|
|||
config->mute_sound_turbo = get_check ("mute_sound_turbo_check");
|
||||
Settings.DynamicRateControl = get_check ("dynamic_rate_control");
|
||||
Settings.DynamicRateLimit = (uint32) (get_spin ("dynamic_rate_limit") * 1000);
|
||||
Settings.ThreadedAPU = get_check ("threaded_apu");
|
||||
|
||||
store_ntsc_settings ();
|
||||
config->ntsc_scanline_intensity = get_combo ("ntsc_scanline_intensity");
|
||||
|
|
|
@ -4016,7 +4016,21 @@
|
|||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="threaded_apu">
|
||||
<property name="label" translatable="yes">Threaded sound processors</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Tries to run the S-SMP and S-DSP on a separate thread</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="dynamic_rate_control">
|
||||
<property name="label" translatable="yes">Dynamic rate control</property>
|
||||
|
@ -4029,7 +4043,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">2</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
|
@ -4046,7 +4060,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">3</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -4062,7 +4076,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">4</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -4078,7 +4092,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">5</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -4298,7 +4312,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
@ -424,6 +424,7 @@ void S9xLoadConfigFiles (char **argv, int argc)
|
|||
Settings.Mute = conf.GetBool("Sound::Mute", false);
|
||||
Settings.DynamicRateControl = conf.GetBool("Sound::DynamicRateControl", false);
|
||||
Settings.DynamicRateLimit = conf.GetInt ("Sound::DynamicRateLimit", 5);
|
||||
Settings.ThreadedAPU = conf.GetBool("Sound::ThreadedAPU", false);
|
||||
|
||||
// Display
|
||||
|
||||
|
|
Loading…
Reference in New Issue