mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v035 release.
Changelog: - Added video synchronization support at long last [blargg, byuu]. - Added audio panel to control volume, latency, frequency and SNES input frequency settings. - Added driver panel to select APIs to use for video, audio and input. - Added crash handler for driver initialization. - Xv and SDL video drivers now work with compositing enabled on Linux/Xorg. - Improved ALSA audio driver for Linux. - Now using a fixed output frequency, along with a 4-tap hermite resampler. - Improved header detection; fixes Batman: Revenge of The Joker and a few fan translations. - Frameskip will now randomly choose a frame in each set to display; helps with animations. - Locales now support meta-data, which allows for unique translations of the same English input.
This commit is contained in:
parent
e2cc164f70
commit
8c591ce44a
|
@ -1,5 +1,5 @@
|
||||||
bsnes
|
bsnes
|
||||||
Version: 0.034
|
Version: 0.035
|
||||||
Author: byuu
|
Author: byuu
|
||||||
|
|
||||||
========
|
========
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#define BSNES_VERSION "0.034.06"
|
#define BSNES_VERSION "0.035"
|
||||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||||
|
|
||||||
#define BUSCORE sBus
|
#define BUSCORE sBus
|
||||||
|
|
|
@ -9,16 +9,27 @@ namespace nall {
|
||||||
|
|
||||||
class dictionary : noncopyable {
|
class dictionary : noncopyable {
|
||||||
public:
|
public:
|
||||||
const char* operator[](const char *input) const {
|
string operator[](const char *input) {
|
||||||
for(unsigned i = 0; i < index_input.size(); i++) {
|
for(unsigned i = 0; i < index_input.size(); i++) {
|
||||||
if(!strcmp(input, index_input[i])) return index_output[i];
|
if(index_input[i] == input) return index_output[i];
|
||||||
}
|
}
|
||||||
return input; //no match, return input rather than null string
|
|
||||||
|
//no match, use input; remove input identifier, if one exists
|
||||||
|
if(strbegin(input, "{{")) {
|
||||||
|
int pos = strpos(input, "}}");
|
||||||
|
if(pos >= 0) {
|
||||||
|
string temp = substr(input, pos + 2);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool import(const char *filename) {
|
bool import(const char *filename) {
|
||||||
string data;
|
string data;
|
||||||
if(fread(data, filename) == false) return false;
|
if(fread(data, filename) == false) return false;
|
||||||
|
ltrim_once(data, "\xef\xbb\xbf"); //remove UTF-8 marker, if it exists
|
||||||
replace(data, "\r", "");
|
replace(data, "\r", "");
|
||||||
|
|
||||||
lstring line;
|
lstring line;
|
||||||
|
@ -38,16 +49,12 @@ public:
|
||||||
trim_once(part[1], "\"");
|
trim_once(part[1], "\"");
|
||||||
|
|
||||||
unsigned n = index_input.size();
|
unsigned n = index_input.size();
|
||||||
index_input[n] = strdup(part[0]);
|
index_input[n] = part[0];
|
||||||
index_output[n] = strdup(part[1]);
|
index_output[n] = part[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
for(unsigned i = 0; i < index_input.size(); i++) {
|
|
||||||
free(index_input[i]);
|
|
||||||
free(index_output[i]);
|
|
||||||
}
|
|
||||||
index_input.reset();
|
index_input.reset();
|
||||||
index_output.reset();
|
index_output.reset();
|
||||||
}
|
}
|
||||||
|
@ -56,9 +63,9 @@ public:
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
array<char*> index_input;
|
lstring index_input;
|
||||||
array<char*> index_output;
|
lstring index_output;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace nall
|
} //namespace nall
|
||||||
|
|
|
@ -165,12 +165,12 @@ void AudioInterface::driver(const char *driver) {
|
||||||
const char* AudioInterface::default_driver() {
|
const char* AudioInterface::default_driver() {
|
||||||
#if defined(AUDIO_DIRECTSOUND)
|
#if defined(AUDIO_DIRECTSOUND)
|
||||||
return "DirectSound";
|
return "DirectSound";
|
||||||
#elif defined(AUDIO_AO)
|
|
||||||
return "libao";
|
|
||||||
#elif defined(AUDIO_ALSA)
|
#elif defined(AUDIO_ALSA)
|
||||||
return "ALSA";
|
return "ALSA";
|
||||||
#elif defined(AUDIO_OPENAL)
|
#elif defined(AUDIO_OPENAL)
|
||||||
return "OpenAL";
|
return "OpenAL";
|
||||||
|
#elif defined(AUDIO_AO)
|
||||||
|
return "libao";
|
||||||
#elif defined(AUDIO_OSS)
|
#elif defined(AUDIO_OSS)
|
||||||
return "OSS";
|
return "OSS";
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -80,20 +80,23 @@ double AudioInterface::hermite(double mu1, double a, double b, double c, double
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioInterface::sample(uint16_t left, uint16_t right) {
|
void AudioInterface::sample(uint16_t left, uint16_t right) {
|
||||||
|
int s_left = (int16_t)left;
|
||||||
|
int s_right = (int16_t)right;
|
||||||
|
|
||||||
if(volume != 100) {
|
if(volume != 100) {
|
||||||
left = sclamp<16>((double)left * (double)volume / 100.0);
|
s_left = sclamp<16>((double)s_left * (double)volume / 100.0);
|
||||||
right = sclamp<16>((double)right * (double)volume / 100.0);
|
s_right = sclamp<16>((double)s_right * (double)volume / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
r_left [0] = r_left [1];
|
r_left [0] = r_left [1];
|
||||||
r_left [1] = r_left [2];
|
r_left [1] = r_left [2];
|
||||||
r_left [2] = r_left [3];
|
r_left [2] = r_left [3];
|
||||||
r_left [3] = (int16_t)left;
|
r_left [3] = s_left;
|
||||||
|
|
||||||
r_right[0] = r_right[1];
|
r_right[0] = r_right[1];
|
||||||
r_right[1] = r_right[2];
|
r_right[1] = r_right[2];
|
||||||
r_right[2] = r_right[3];
|
r_right[2] = r_right[3];
|
||||||
r_right[3] = (int16_t)right;
|
r_right[3] = s_right;
|
||||||
|
|
||||||
if(resample_enabled == false) {
|
if(resample_enabled == false) {
|
||||||
if(p) p->sample(left, right);
|
if(p) p->sample(left, right);
|
||||||
|
|
|
@ -221,7 +221,7 @@ void MainWindow::setup() {
|
||||||
menu_settings_videofilter.attach(menu_settings_videofilter_swscanline.create(group, translate["Scanline"]));
|
menu_settings_videofilter.attach(menu_settings_videofilter_swscanline.create(group, translate["Scanline"]));
|
||||||
menu_settings_videofilter.attach(menu_settings_videofilter_swscale2x.create(group, translate["Scale2x"]));
|
menu_settings_videofilter.attach(menu_settings_videofilter_swscale2x.create(group, translate["Scale2x"]));
|
||||||
menu_settings_videofilter.attach(menu_settings_videofilter_swhq2x.create(group, translate["HQ2x"]));
|
menu_settings_videofilter.attach(menu_settings_videofilter_swhq2x.create(group, translate["HQ2x"]));
|
||||||
menu_settings_videofilter.attach(menu_settings_videofilter_swntsc.create(group, translate["NTSC"]));
|
menu_settings_videofilter.attach(menu_settings_videofilter_swntsc.create(group, translate["{{filter}}NTSC"]));
|
||||||
group.reset();
|
group.reset();
|
||||||
|
|
||||||
menu_settings.attach(menu_settings_videoframeskip.create(translate["Video Frameskip"]));
|
menu_settings.attach(menu_settings_videoframeskip.create(translate["Video Frameskip"]));
|
||||||
|
@ -264,8 +264,8 @@ void MainWindow::setup() {
|
||||||
menu_settings_emuspeed_fastest.create(group, translate["200%"]);
|
menu_settings_emuspeed_fastest.create(group, translate["200%"]);
|
||||||
group.reset();
|
group.reset();
|
||||||
menu_settings_emuspeed_sep1.create();
|
menu_settings_emuspeed_sep1.create();
|
||||||
menu_settings_emuspeed_videosync.create(translate["Sync to Video"]);
|
menu_settings_emuspeed_videosync.create(translate["Sync Video"]);
|
||||||
menu_settings_emuspeed_audiosync.create(translate["Sync to Audio"]);
|
menu_settings_emuspeed_audiosync.create(translate["Sync Audio"]);
|
||||||
|
|
||||||
if(audio.cap(Audio::Frequency)) {
|
if(audio.cap(Audio::Frequency)) {
|
||||||
//only audio can sync to specific frequency rates; video syncs only to monitor refresh rate
|
//only audio can sync to specific frequency rates; video syncs only to monitor refresh rate
|
||||||
|
|
|
@ -109,9 +109,9 @@ struct Audio {
|
||||||
static integral_setting synchronize;
|
static integral_setting synchronize;
|
||||||
} audio;
|
} audio;
|
||||||
integral_setting Audio::output_frequency(config(), "audio.output_frequency", "Sound card audio output frequency", integral_setting::decimal, 48000);
|
integral_setting Audio::output_frequency(config(), "audio.output_frequency", "Sound card audio output frequency", integral_setting::decimal, 48000);
|
||||||
integral_setting Audio::input_frequency(config(), "audio.input_frequency", "Emulator audio input frequency", integral_setting::decimal, 31950);
|
integral_setting Audio::input_frequency(config(), "audio.input_frequency", "Emulator audio input frequency", integral_setting::decimal, 31960);
|
||||||
integral_setting Audio::latency(config(), "audio.latency", "Sound card latency (in ms)", integral_setting::decimal, 100);
|
integral_setting Audio::latency(config(), "audio.latency", "Sound card latency (in ms)", integral_setting::decimal, 100);
|
||||||
integral_setting Audio::volume(config(), "audio.volume", "Audio volume (0 - 100)", integral_setting::decimal, 100);
|
integral_setting Audio::volume(config(), "audio.volume", "Audio volume (10 - 100)", integral_setting::decimal, 100);
|
||||||
integral_setting Audio::mute(config(), "audio.mute", "Mute audio playback", integral_setting::boolean, false);
|
integral_setting Audio::mute(config(), "audio.mute", "Mute audio playback", integral_setting::boolean, false);
|
||||||
integral_setting Audio::synchronize(config(), "audio.synchronize", "Synchronize to audio sample rate", integral_setting::boolean, true);
|
integral_setting Audio::synchronize(config(), "audio.synchronize", "Synchronize to audio sample rate", integral_setting::boolean, true);
|
||||||
|
|
||||||
|
|
|
@ -118,19 +118,15 @@ void update_frameskip(int speed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_emulation_speed(int speed) {
|
void update_emulation_speed(int speed) {
|
||||||
config::system.emulation_speed = max(0, min(4, speed));
|
config::system.emulation_speed = speed = max(0, min(4, speed));
|
||||||
|
|
||||||
double scale;
|
double scale[] = { 0.50, 0.75, 1.00, 1.50, 2.00 };
|
||||||
switch(config::system.emulation_speed) {
|
unsigned outfreq = config::audio.output_frequency;
|
||||||
case 0: scale = 0.50; break; //slowest
|
unsigned infreq = config::audio.input_frequency * scale[speed] + 0.5;
|
||||||
case 1: scale = 0.75; break; //slow
|
|
||||||
case 2: scale = 1.00; break; //normal
|
|
||||||
case 3: scale = 1.50; break; //fast
|
|
||||||
case 4: scale = 2.00; break; //fastest
|
|
||||||
}
|
|
||||||
|
|
||||||
audio.set(Audio::ResampleOutputFrequency, config::audio.output_frequency);
|
audio.set(Audio::Resample, outfreq != infreq); //only resample when necessary
|
||||||
audio.set(Audio::ResampleInputFrequency, config::audio.input_frequency * scale + 0.5);
|
audio.set(Audio::ResampleOutputFrequency, outfreq);
|
||||||
|
audio.set(Audio::ResampleInputFrequency, infreq);
|
||||||
|
|
||||||
window_main.sync();
|
window_main.sync();
|
||||||
}
|
}
|
||||||
|
@ -178,9 +174,11 @@ void update_video_settings() {
|
||||||
width *= multiplier;
|
width *= multiplier;
|
||||||
height *= multiplier;
|
height *= multiplier;
|
||||||
if(video_settings.aspect_correction == true) {
|
if(video_settings.aspect_correction == true) {
|
||||||
if(video_settings.region == 0) { //NTSC
|
if(video_settings.region == 0) {
|
||||||
|
//NTSC
|
||||||
width = uint( double(width) * double(config::video.aspect_ntsc_x) / double(config::video.aspect_ntsc_y) );
|
width = uint( double(width) * double(config::video.aspect_ntsc_x) / double(config::video.aspect_ntsc_y) );
|
||||||
} else { //PAL
|
} else {
|
||||||
|
//PAL
|
||||||
width = uint( double(width) * double(config::video.aspect_pal_x) / double(config::video.aspect_pal_y) );
|
width = uint( double(width) * double(config::video.aspect_pal_x) / double(config::video.aspect_pal_y) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,7 +413,7 @@ void reset() {
|
||||||
if(cartridge.loaded() == true) {
|
if(cartridge.loaded() == true) {
|
||||||
snes.reset();
|
snes.reset();
|
||||||
status.flush();
|
status.flush();
|
||||||
status.enqueue(translate["Reset"]);
|
status.enqueue(translate["System was reset."]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +421,7 @@ void power() {
|
||||||
if(cartridge.loaded() == true) {
|
if(cartridge.loaded() == true) {
|
||||||
snes.power();
|
snes.power();
|
||||||
status.flush();
|
status.flush();
|
||||||
status.enqueue(translate["Power cycle"]);
|
status.enqueue(translate["System power was cycled."]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ uintptr_t AdvancedWindow::list_change(event_t) {
|
||||||
string default_;
|
string default_;
|
||||||
config::config().list[i]->get_default(default_);
|
config::config().list[i]->get_default(default_);
|
||||||
desc.set_text(string()
|
desc.set_text(string()
|
||||||
<< "(" << translate["Default"] << " = " << default_ << ")\n"
|
<< "(" << translate["{{advanced}}Default"] << " = " << default_ << ")\n"
|
||||||
<< config::config().list[i]->description);
|
<< config::config().list[i]->description);
|
||||||
string value_;
|
string value_;
|
||||||
config::config().list[i]->get(value_);
|
config::config().list[i]->get(value_);
|
||||||
|
@ -90,8 +90,8 @@ void AdvancedWindow::setup() {
|
||||||
string() << translate["Name"] << "\t" << translate["Type"] << "\t" << translate["Value"]);
|
string() << translate["Name"] << "\t" << translate["Type"] << "\t" << translate["Value"]);
|
||||||
desc.create(Editbox::Multiline | Editbox::VerticalScrollAlways | Editbox::Readonly, 475, 80, translate["<description>"]);
|
desc.create(Editbox::Multiline | Editbox::VerticalScrollAlways | Editbox::Readonly, 475, 80, translate["<description>"]);
|
||||||
edit_val.create(0, 265, 25, translate["<current value>"]);
|
edit_val.create(0, 265, 25, translate["<current value>"]);
|
||||||
set_val.create (0, 100, 25, translate["Set"]);
|
set_val.create (0, 100, 25, translate["{{advanced}}Set"]);
|
||||||
set_def.create (0, 100, 25, translate["Default"]);
|
set_def.create (0, 100, 25, translate["{{advanced}}Default"]);
|
||||||
|
|
||||||
unsigned y = 0;
|
unsigned y = 0;
|
||||||
attach(list, 0, y); y += 240 + 5;
|
attach(list, 0, y); y += 240 + 5;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
uintptr_t AudioSettingsWindow::volume_change(event_t) {
|
uintptr_t AudioSettingsWindow::volume_change(event_t) {
|
||||||
config::audio.volume = 10 + volume.get_position();
|
config::audio.volume = 10 + svolume.get_position();
|
||||||
audio.set(Audio::Volume, config::audio.volume);
|
audio.set(Audio::Volume, config::audio.volume);
|
||||||
|
|
||||||
sync_ui();
|
sync_ui();
|
||||||
|
@ -7,19 +7,18 @@ uintptr_t AudioSettingsWindow::volume_change(event_t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t AudioSettingsWindow::latency_change(event_t) {
|
uintptr_t AudioSettingsWindow::latency_change(event_t) {
|
||||||
config::audio.latency = 25 + latency.get_position() * 5;
|
config::audio.latency = 25 + slatency.get_position() * 5;
|
||||||
audio.set(Audio::Latency, config::audio.latency);
|
audio.set(Audio::Latency, config::audio.latency);
|
||||||
|
|
||||||
sync_ui();
|
sync_ui();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t AudioSettingsWindow::outputfrequency_change(event_t) {
|
uintptr_t AudioSettingsWindow::output_change(event_t) {
|
||||||
switch(outputfrequency.get_position()) { default:
|
switch(soutput.get_position()) {
|
||||||
case 0: config::audio.output_frequency = 32000; break;
|
case 0: config::audio.output_frequency = 32000; break;
|
||||||
case 1: config::audio.output_frequency = 44100; break;
|
case 1: config::audio.output_frequency = 44100; break; default:
|
||||||
case 2: config::audio.output_frequency = 48000; break;
|
case 2: config::audio.output_frequency = 48000; break;
|
||||||
case 3: config::audio.output_frequency = 96000; break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
audio.set(Audio::Frequency, config::audio.output_frequency);
|
audio.set(Audio::Frequency, config::audio.output_frequency);
|
||||||
|
@ -29,8 +28,49 @@ uintptr_t AudioSettingsWindow::outputfrequency_change(event_t) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t AudioSettingsWindow::inputfrequency_change(event_t) {
|
uintptr_t AudioSettingsWindow::input_change(event_t) {
|
||||||
config::audio.input_frequency = inputfrequency.get_position() + 32000 - 200;
|
config::audio.input_frequency = sinput.get_position() + 32000 - 200;
|
||||||
|
event::update_emulation_speed(config::system.emulation_speed);
|
||||||
|
|
||||||
|
sync_ui();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t AudioSettingsWindow::volume_tick(event_t) {
|
||||||
|
char t[256];
|
||||||
|
evolume.get_text(t, sizeof t);
|
||||||
|
config::audio.volume = strdec(t);
|
||||||
|
audio.set(Audio::Volume, config::audio.volume);
|
||||||
|
|
||||||
|
sync_ui();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t AudioSettingsWindow::latency_tick(event_t) {
|
||||||
|
char t[256];
|
||||||
|
elatency.get_text(t, sizeof t);
|
||||||
|
config::audio.latency = strdec(t);
|
||||||
|
audio.set(Audio::Latency, config::audio.latency);
|
||||||
|
|
||||||
|
sync_ui();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t AudioSettingsWindow::output_tick(event_t) {
|
||||||
|
char t[256];
|
||||||
|
eoutput.get_text(t, sizeof t);
|
||||||
|
config::audio.output_frequency = strdec(t);
|
||||||
|
audio.set(Audio::Frequency, config::audio.output_frequency);
|
||||||
|
event::update_emulation_speed(config::system.emulation_speed);
|
||||||
|
|
||||||
|
sync_ui();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t AudioSettingsWindow::input_tick(event_t) {
|
||||||
|
char t[256];
|
||||||
|
einput.get_text(t, sizeof t);
|
||||||
|
config::audio.input_frequency = strdec(t);
|
||||||
event::update_emulation_speed(config::system.emulation_speed);
|
event::update_emulation_speed(config::system.emulation_speed);
|
||||||
|
|
||||||
sync_ui();
|
sync_ui();
|
||||||
|
@ -42,75 +82,121 @@ void AudioSettingsWindow::sync_ui() {
|
||||||
<< translate["Volume:"] << " "
|
<< translate["Volume:"] << " "
|
||||||
<< (int)config::audio.volume << "%"
|
<< (int)config::audio.volume << "%"
|
||||||
);
|
);
|
||||||
volume.set_position(config::audio.volume - 10);
|
|
||||||
|
|
||||||
llatency.set_text(string()
|
llatency.set_text(string()
|
||||||
<< translate["Latency:"] << " "
|
<< translate["Latency:"] << " "
|
||||||
<< (int)config::audio.latency << "ms"
|
<< (int)config::audio.latency << "ms"
|
||||||
);
|
);
|
||||||
latency.set_position((config::audio.latency - 25) / 5);
|
|
||||||
|
|
||||||
loutputfrequency.set_text(string()
|
loutput.set_text(string()
|
||||||
<< translate["PC output frequency:"] << " "
|
<< translate["Frequency:"] << " "
|
||||||
<< (int)config::audio.output_frequency << "hz"
|
<< (int)config::audio.output_frequency << "hz"
|
||||||
);
|
);
|
||||||
unsigned position;
|
|
||||||
if(config::audio.output_frequency <= 32000) position = 0;
|
|
||||||
else if(config::audio.output_frequency <= 44100) position = 1;
|
|
||||||
else if(config::audio.output_frequency <= 48000) position = 2;
|
|
||||||
else position = 3;
|
|
||||||
outputfrequency.set_position(position);
|
|
||||||
|
|
||||||
int input_freq = config::audio.input_frequency - 32000;
|
if(config::advanced.enable == false) {
|
||||||
string adjust;
|
int input_freq = config::audio.input_frequency - 32000;
|
||||||
if(input_freq > 0) adjust << "+";
|
string adjust;
|
||||||
adjust << input_freq;
|
if(input_freq > 0) adjust << "+";
|
||||||
if(config::advanced.enable == true) {
|
adjust << input_freq << "hz";
|
||||||
adjust << " (" << (int)config::audio.input_frequency << "hz)";
|
linput.set_text(string()
|
||||||
|
<< translate["Frequency adjust:"] << " "
|
||||||
|
<< adjust
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
linput.set_text(string() << translate["Frequency adjust:"] << " " << (int)config::audio.input_frequency << "hz");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(config::advanced.enable == false) {
|
||||||
|
svolume.set_position(config::audio.volume - 10);
|
||||||
|
slatency.set_position((config::audio.latency - 25) / 5);
|
||||||
|
unsigned position;
|
||||||
|
if(config::audio.output_frequency <= 32000) position = 0;
|
||||||
|
else if(config::audio.output_frequency <= 44100) position = 1;
|
||||||
|
else position = 2;
|
||||||
|
soutput.set_position(position);
|
||||||
|
sinput.set_position(config::audio.input_frequency - 32000 + 200);
|
||||||
|
} else {
|
||||||
|
evolume.set_text(string() << (int)config::audio.volume);
|
||||||
|
elatency.set_text(string() << (int)config::audio.latency);
|
||||||
|
eoutput.set_text(string() << (int)config::audio.output_frequency);
|
||||||
|
einput.set_text(string() << (int)config::audio.input_frequency);
|
||||||
}
|
}
|
||||||
linputfrequency.set_text(string()
|
|
||||||
<< translate["SNES input frequency adjust:"] << " "
|
|
||||||
<< adjust
|
|
||||||
);
|
|
||||||
inputfrequency.set_position(input_freq + 200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSettingsWindow::setup() {
|
void AudioSettingsWindow::setup() {
|
||||||
create(0, 475, 355);
|
create(0, 475, 355);
|
||||||
|
|
||||||
lvolume.create(0, 475, 18);
|
lvolume.create(0, 235, 18);
|
||||||
//if advanced UI mode is disabled, volume range is 10% - 100%
|
svolume.create(0, 475, 30, 91);
|
||||||
//if enabled, volume range is 10% - 200%
|
evolume.create(0, 130, 25);
|
||||||
//101%+ is hidden by default, as it can cause audio quality degradation due to clamping
|
bvolume.create(0, 100, 25, translate["{{audio}}Set"]);
|
||||||
volume.create(0, 475, 30, (config::advanced.enable == false ? 91 : 191));
|
|
||||||
|
|
||||||
llatency.create(0, 475, 18);
|
llatency.create(0, 235, 18);
|
||||||
latency.create(0, 475, 30, 31);
|
slatency.create(0, 475, 30, 26);
|
||||||
|
elatency.create(0, 130, 25);
|
||||||
|
blatency.create(0, 100, 25, translate["{{audio}}Set"]);
|
||||||
|
|
||||||
loutputfrequency.create(0, 475, 18);
|
loutput.create(0, 235, 18);
|
||||||
outputfrequency.create(0, 475, 30, 4);
|
soutput.create(0, 475, 30, 3);
|
||||||
|
eoutput.create(0, 130, 25);
|
||||||
|
boutput.create(0, 100, 25, translate["{{audio}}Set"]);
|
||||||
|
|
||||||
linputfrequency.create(0, 475, 18);
|
linput.create(0, 235, 18);
|
||||||
inputfrequency.create(0, 475, 30, 401);
|
sinput.create(0, 475, 30, 401);
|
||||||
|
einput.create(0, 130, 25);
|
||||||
|
binput.create(0, 100, 25, translate["{{audio}}Set"]);
|
||||||
|
|
||||||
unsigned y = 0;
|
unsigned y = 0;
|
||||||
attach(lvolume, 0, y); y += 18;
|
if(config::advanced.enable == false) {
|
||||||
attach(volume, 0, y); y += 30;
|
attach(lvolume, 0, y); y += 18;
|
||||||
if(audio.cap(Audio::Latency) == true) {
|
attach(svolume, 0, y); y += 30;
|
||||||
attach(llatency, 0, y); y += 18;
|
if(audio.cap(Audio::Latency) == true) {
|
||||||
attach(latency, 0, y); y += 30;
|
attach(llatency, 0, y); y += 18;
|
||||||
}
|
attach(slatency, 0, y); y += 30;
|
||||||
if(audio.cap(Audio::Frequency) == true) {
|
}
|
||||||
attach(loutputfrequency, 0, y); y += 18;
|
if(audio.cap(Audio::Frequency) == true) {
|
||||||
attach(outputfrequency, 0, y); y += 30;
|
attach(loutput, 0, y); y += 18;
|
||||||
}
|
attach(soutput, 0, y); y += 30;
|
||||||
attach(linputfrequency, 0, y); y += 18;
|
}
|
||||||
attach(inputfrequency, 0, y); y += 30;
|
attach(linput, 0, y); y += 18;
|
||||||
|
attach(sinput, 0, y); y += 30;
|
||||||
|
} else {
|
||||||
|
attach(lvolume, 0, y);
|
||||||
|
attach(llatency, 240, y); y += 18;
|
||||||
|
|
||||||
volume.on_change = bind(&AudioSettingsWindow::volume_change, this);
|
attach(evolume, 0, y);
|
||||||
latency.on_change = bind(&AudioSettingsWindow::latency_change, this);
|
attach(bvolume, 135, y);
|
||||||
outputfrequency.on_change = bind(&AudioSettingsWindow::outputfrequency_change, this);
|
attach(elatency, 240, y);
|
||||||
inputfrequency.on_change = bind(&AudioSettingsWindow::inputfrequency_change, this);
|
attach(blatency, 375, y); y += 25 + 5;
|
||||||
|
|
||||||
|
attach(loutput, 0, y);
|
||||||
|
attach(linput, 240, y); y += 18;
|
||||||
|
|
||||||
|
attach(eoutput, 0, y);
|
||||||
|
attach(boutput, 135, y);
|
||||||
|
attach(einput, 240, y);
|
||||||
|
attach(binput, 375, y); y += 25 + 5;
|
||||||
|
|
||||||
|
if(audio.cap(Audio::Latency) == false) {
|
||||||
|
elatency.disable();
|
||||||
|
blatency.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audio.cap(Audio::Frequency) == false) {
|
||||||
|
eoutput.disable();
|
||||||
|
boutput.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svolume.on_change = bind(&AudioSettingsWindow::volume_change, this);
|
||||||
|
slatency.on_change = bind(&AudioSettingsWindow::latency_change, this);
|
||||||
|
soutput.on_change = bind(&AudioSettingsWindow::output_change, this);
|
||||||
|
sinput.on_change = bind(&AudioSettingsWindow::input_change, this);
|
||||||
|
|
||||||
|
bvolume.on_tick = bind(&AudioSettingsWindow::volume_tick, this);
|
||||||
|
blatency.on_tick = bind(&AudioSettingsWindow::latency_tick, this);
|
||||||
|
boutput.on_tick = bind(&AudioSettingsWindow::output_tick, this);
|
||||||
|
binput.on_tick = bind(&AudioSettingsWindow::input_tick, this);
|
||||||
|
|
||||||
sync_ui();
|
sync_ui();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,34 @@
|
||||||
class AudioSettingsWindow : public Window {
|
class AudioSettingsWindow : public Window {
|
||||||
public:
|
public:
|
||||||
Label lvolume;
|
Label lvolume;
|
||||||
Slider volume;
|
Slider svolume;
|
||||||
|
Editbox evolume;
|
||||||
|
Button bvolume;
|
||||||
|
|
||||||
Label llatency;
|
Label llatency;
|
||||||
Slider latency;
|
Slider slatency;
|
||||||
|
Editbox elatency;
|
||||||
|
Button blatency;
|
||||||
|
|
||||||
Label loutputfrequency;
|
Label loutput;
|
||||||
Slider outputfrequency;
|
Slider soutput;
|
||||||
|
Editbox eoutput;
|
||||||
|
Button boutput;
|
||||||
|
|
||||||
Label linputfrequency;
|
Label linput;
|
||||||
Slider inputfrequency;
|
Slider sinput;
|
||||||
|
Editbox einput;
|
||||||
|
Button binput;
|
||||||
|
|
||||||
uintptr_t volume_change(event_t);
|
uintptr_t volume_change(event_t);
|
||||||
uintptr_t latency_change(event_t);
|
uintptr_t latency_change(event_t);
|
||||||
uintptr_t outputfrequency_change(event_t);
|
uintptr_t output_change(event_t);
|
||||||
uintptr_t inputfrequency_change(event_t);
|
uintptr_t input_change(event_t);
|
||||||
|
|
||||||
|
uintptr_t volume_tick(event_t);
|
||||||
|
uintptr_t latency_tick(event_t);
|
||||||
|
uintptr_t output_tick(event_t);
|
||||||
|
uintptr_t input_tick(event_t);
|
||||||
|
|
||||||
void sync_ui();
|
void sync_ui();
|
||||||
void setup();
|
void setup();
|
||||||
|
|
|
@ -30,7 +30,7 @@ void DriverSelectWindow::setup() {
|
||||||
|
|
||||||
lstring part;
|
lstring part;
|
||||||
|
|
||||||
lvideo.create(0, 155, 18, translate["Video Driver:"]);
|
lvideo.create(0, 155, 18, translate["Video driver:"]);
|
||||||
cvideo.create(0, 155, 25);
|
cvideo.create(0, 155, 25);
|
||||||
|
|
||||||
split(part, ";", video.driver_list());
|
split(part, ";", video.driver_list());
|
||||||
|
@ -39,7 +39,7 @@ void DriverSelectWindow::setup() {
|
||||||
if(part[i] == config::system.video) cvideo.set_selection(i);
|
if(part[i] == config::system.video) cvideo.set_selection(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
laudio.create(0, 155, 18, translate["Audio Driver:"]);
|
laudio.create(0, 155, 18, translate["Audio driver:"]);
|
||||||
caudio.create(0, 155, 25);
|
caudio.create(0, 155, 25);
|
||||||
|
|
||||||
split(part, ";", audio.driver_list());
|
split(part, ";", audio.driver_list());
|
||||||
|
@ -48,7 +48,7 @@ void DriverSelectWindow::setup() {
|
||||||
if(part[i] == config::system.audio) caudio.set_selection(i);
|
if(part[i] == config::system.audio) caudio.set_selection(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
linput.create(0, 155, 18, translate["Input Driver:"]);
|
linput.create(0, 155, 18, translate["Input driver:"]);
|
||||||
cinput.create(0, 155, 25);
|
cinput.create(0, 155, 25);
|
||||||
|
|
||||||
split(part, ";", input.driver_list());
|
split(part, ";", input.driver_list());
|
||||||
|
@ -59,31 +59,29 @@ void DriverSelectWindow::setup() {
|
||||||
|
|
||||||
video_caps.create(0, 475, 18);
|
video_caps.create(0, 475, 18);
|
||||||
|
|
||||||
video_sync.create(0, 155, 18, translate["Synchronize"]);
|
video_sync.create(0, 155, 18, translate["{{video}}Synchronize"]);
|
||||||
video_sync.disable();
|
video_sync.disable();
|
||||||
video_filter.create(0, 155, 18, translate["Hardware Filtering"]);
|
video_filter.create(0, 155, 18, translate["Hardware filtering"]);
|
||||||
video_filter.disable();
|
video_filter.disable();
|
||||||
|
|
||||||
audio_caps.create(0, 475, 18);
|
audio_caps.create(0, 475, 18);
|
||||||
|
|
||||||
audio_sync.create(0, 155, 18, translate["Synchronize"]);
|
audio_sync.create(0, 155, 18, translate["{{audio}}Synchronize"]);
|
||||||
audio_sync.disable();
|
audio_sync.disable();
|
||||||
audio_freq.create(0, 155, 18, translate["Frequency Control"]);
|
audio_freq.create(0, 155, 18, translate["Frequency control"]);
|
||||||
audio_freq.disable();
|
audio_freq.disable();
|
||||||
audio_latency.create(0, 155, 18, translate["Latency Control"]);
|
audio_latency.create(0, 155, 18, translate["Latency control"]);
|
||||||
audio_latency.disable();
|
audio_latency.disable();
|
||||||
|
|
||||||
input_caps.create(0, 475, 18);
|
input_caps.create(0, 475, 18);
|
||||||
|
|
||||||
input_keyboard.create(0, 155, 18, translate["Keyboard Support"]);
|
input_keyboard.create(0, 155, 18, translate["Keyboard support"]);
|
||||||
input_keyboard.disable();
|
input_keyboard.disable();
|
||||||
input_joypad.create(0, 155, 18, translate["Joypad Support"]);
|
input_joypad.create(0, 155, 18, translate["Joypad support"]);
|
||||||
input_joypad.disable();
|
input_joypad.disable();
|
||||||
|
|
||||||
restart_message.create(0, 475, 36, string()
|
restart_message.create(0, 475, 36,
|
||||||
<< translate["Note: bsnes must be restarted for changes to take effect."] << "\n"
|
translate["Note: bsnes must be restarted for changes to take effect."]);
|
||||||
<< translate["If bsnes then crashes on startup, restart it again to adjust driver settings."]
|
|
||||||
);
|
|
||||||
|
|
||||||
bool crashed = config::system.invoke_crash_handler;
|
bool crashed = config::system.invoke_crash_handler;
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,15 @@ void InputConfigWindow::setup() {
|
||||||
capture_pause.create (group, 0, 155, 18, translate["Pause emulation"]);
|
capture_pause.create (group, 0, 155, 18, translate["Pause emulation"]);
|
||||||
|
|
||||||
config_type.create(0, 235, 25);
|
config_type.create(0, 235, 25);
|
||||||
config_type.add_item(translate["Controller Port 1"]);
|
config_type.add_item(translate["{{input}}Controller Port 1"]);
|
||||||
config_type.add_item(translate["Controller Port 2"]);
|
config_type.add_item(translate["{{input}}Controller Port 2"]);
|
||||||
config_type.add_item(translate["User Interface"]);
|
config_type.add_item(translate["{{input}}User Interface"]);
|
||||||
config_type.set_selection(0);
|
config_type.set_selection(0);
|
||||||
|
|
||||||
config_subtype.create(0, 235, 25);
|
config_subtype.create(0, 235, 25);
|
||||||
refresh_subtype();
|
refresh_subtype();
|
||||||
|
|
||||||
list.create(Listbox::Header | Listbox::VerticalScrollAlways, 475, 254, string() << translate["Name"] << "\t" << translate["Value"]);
|
list.create(Listbox::Header | Listbox::VerticalScrollAlways, 475, 254, string() << translate["{{input}}Name"] << "\t" << translate["{{input}}Value"]);
|
||||||
setkey.create(0, 235, 25, translate["Assign Key"]);
|
setkey.create(0, 235, 25, translate["Assign Key"]);
|
||||||
setkey.disable();
|
setkey.disable();
|
||||||
clrkey.create(0, 235, 25, translate["Unassign Key"]);
|
clrkey.create(0, 235, 25, translate["Unassign Key"]);
|
||||||
|
@ -117,7 +117,7 @@ void InputConfigWindow::refresh_list() {
|
||||||
unsigned length;
|
unsigned length;
|
||||||
get_input_type(length);
|
get_input_type(length);
|
||||||
for(unsigned i = 0; i < length; i++) {
|
for(unsigned i = 0; i < length; i++) {
|
||||||
const char *name;
|
string name;
|
||||||
acquire(i, name);
|
acquire(i, name);
|
||||||
list.add_item(string() << name << "\t" << input_find(get_value(i)));
|
list.add_item(string() << name << "\t" << input_find(get_value(i)));
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ uintptr_t InputConfigWindow::set_tick(event_t) {
|
||||||
if(pos < 0) return true;
|
if(pos < 0) return true;
|
||||||
window_input_capture.index = pos;
|
window_input_capture.index = pos;
|
||||||
string message = translate["Press a key to assign to $ ..."];
|
string message = translate["Press a key to assign to $ ..."];
|
||||||
const char *name;
|
string name;
|
||||||
acquire(pos, name);
|
acquire(pos, name);
|
||||||
replace(message, "$", name);
|
replace(message, "$", name);
|
||||||
window_input_capture.label.set_text(message);
|
window_input_capture.label.set_text(message);
|
||||||
|
@ -211,7 +211,7 @@ InputCaptureWindow::InputCaptureWindow() {
|
||||||
|
|
||||||
/* Misc */
|
/* Misc */
|
||||||
|
|
||||||
string_setting& InputConfigWindow::acquire(unsigned index, const char *&name) {
|
string_setting& InputConfigWindow::acquire(unsigned index, string &name) {
|
||||||
#define map(n, lname) \
|
#define map(n, lname) \
|
||||||
case n: { \
|
case n: { \
|
||||||
switch(index) { \
|
switch(index) { \
|
||||||
|
@ -270,12 +270,12 @@ string_setting& InputConfigWindow::acquire(unsigned index, const char *&name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint InputConfigWindow::get_value(uint index) {
|
uint InputConfigWindow::get_value(uint index) {
|
||||||
const char *name;
|
string name;
|
||||||
return input_find(acquire(index, name));
|
return input_find(acquire(index, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputConfigWindow::set_value(uint index, uint16 value) {
|
void InputConfigWindow::set_value(uint index, uint16 value) {
|
||||||
const char *name;
|
string name;
|
||||||
acquire(index, name) = input_find(value);
|
acquire(index, name) = input_find(value);
|
||||||
input_manager.bind();
|
input_manager.bind();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public:
|
||||||
uintptr_t set_tick(event_t);
|
uintptr_t set_tick(event_t);
|
||||||
uintptr_t clr_tick(event_t);
|
uintptr_t clr_tick(event_t);
|
||||||
|
|
||||||
string_setting& acquire(unsigned index, const char *&name);
|
string_setting& acquire(unsigned index, string &name);
|
||||||
uint get_value(uint index);
|
uint get_value(uint index);
|
||||||
void set_value(uint index, uint16 value);
|
void set_value(uint index, uint16 value);
|
||||||
} window_input_config;
|
} window_input_config;
|
||||||
|
|
|
@ -79,23 +79,23 @@ void PathSettingsWindow::setup() {
|
||||||
|
|
||||||
lrompath.create(0, 475, 18, translate["Default game ROM path:"]);
|
lrompath.create(0, 475, 18, translate["Default game ROM path:"]);
|
||||||
rompath.create(Editbox::Readonly, 265, 25);
|
rompath.create(Editbox::Readonly, 265, 25);
|
||||||
romselect.create(0, 100, 25, translate["Select"]);
|
romselect.create(0, 100, 25, translate["{{path}}Select"]);
|
||||||
romdefault.create(0, 100, 25, translate["Default"]);
|
romdefault.create(0, 100, 25, translate["{{path}}Default"]);
|
||||||
|
|
||||||
lpatchpath.create(0, 475, 18, translate["Default UPS patch path:"]);
|
lpatchpath.create(0, 475, 18, translate["Default UPS patch path:"]);
|
||||||
patchpath.create(Editbox::Readonly, 265, 25);
|
patchpath.create(Editbox::Readonly, 265, 25);
|
||||||
patchselect.create(0, 100, 25, translate["Select"]);
|
patchselect.create(0, 100, 25, translate["{{path}}Select"]);
|
||||||
patchdefault.create(0, 100, 25, translate["Default"]);
|
patchdefault.create(0, 100, 25, translate["{{path}}Default"]);
|
||||||
|
|
||||||
lsavepath.create(0, 475, 18, translate["Default save RAM path:"]);
|
lsavepath.create(0, 475, 18, translate["Default save RAM path:"]);
|
||||||
savepath.create(Editbox::Readonly, 265, 25);
|
savepath.create(Editbox::Readonly, 265, 25);
|
||||||
saveselect.create(0, 100, 25, translate["Select"]);
|
saveselect.create(0, 100, 25, translate["{{path}}Select"]);
|
||||||
savedefault.create(0, 100, 25, translate["Default"]);
|
savedefault.create(0, 100, 25, translate["{{path}}Default"]);
|
||||||
|
|
||||||
lcheatpath.create(0, 475, 18, translate["Default cheat file path:"]);
|
lcheatpath.create(0, 475, 18, translate["Default cheat file path:"]);
|
||||||
cheatpath.create(Editbox::Readonly, 265, 25);
|
cheatpath.create(Editbox::Readonly, 265, 25);
|
||||||
cheatselect.create(0, 100, 25, translate["Select"]);
|
cheatselect.create(0, 100, 25, translate["{{path}}Select"]);
|
||||||
cheatdefault.create(0, 100, 25, translate["Default"]);
|
cheatdefault.create(0, 100, 25, translate["{{path}}Default"]);
|
||||||
|
|
||||||
unsigned y = 0;
|
unsigned y = 0;
|
||||||
attach(lrompath, 0, y); y += 18;
|
attach(lrompath, 0, y); y += 18;
|
||||||
|
|
|
@ -18,7 +18,7 @@ void Status::update() {
|
||||||
} else if(!cartridge.loaded()) {
|
} else if(!cartridge.loaded()) {
|
||||||
output = "";
|
output = "";
|
||||||
} else if(app.pause || app.autopause) {
|
} else if(app.pause || app.autopause) {
|
||||||
output = translate["Paused"];
|
output = translate["Paused."];
|
||||||
} else if(ppu.status.frames_updated) {
|
} else if(ppu.status.frames_updated) {
|
||||||
ppu.status.frames_updated = false;
|
ppu.status.frames_updated = false;
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ void ui_init() {
|
||||||
|
|
||||||
video.set(Video::Handle, window_main.view.handle());
|
video.set(Video::Handle, window_main.view.handle());
|
||||||
video.set(Video::Synchronize, config::video.windowed.synchronize);
|
video.set(Video::Synchronize, config::video.windowed.synchronize);
|
||||||
audio.set(Audio::Resample, true);
|
|
||||||
audio.set(Audio::Handle, window_main.handle());
|
audio.set(Audio::Handle, window_main.handle());
|
||||||
audio.set(Audio::Synchronize, config::audio.synchronize);
|
audio.set(Audio::Synchronize, config::audio.synchronize);
|
||||||
audio.set(Audio::Volume, config::audio.volume);
|
audio.set(Audio::Volume, config::audio.volume);
|
||||||
|
@ -79,7 +78,7 @@ void ui_init() {
|
||||||
input.set(Input::Handle, window_main.handle());
|
input.set(Input::Handle, window_main.handle());
|
||||||
input.set(Input::AnalogAxisResistance, config::input.analog_axis_resistance);
|
input.set(Input::AnalogAxisResistance, config::input.analog_axis_resistance);
|
||||||
|
|
||||||
//sets Audio::ResampleOutputFrequency and Audio::ResampleInputFrequency
|
//sets Audio::Resample, Audio::ResampleOutputFrequency and Audio::ResampleInputFrequency
|
||||||
event::update_emulation_speed(config::system.emulation_speed);
|
event::update_emulation_speed(config::system.emulation_speed);
|
||||||
|
|
||||||
video.init();
|
video.init();
|
||||||
|
|
Loading…
Reference in New Issue