Update to v094r22 release.

byuu says:

I fixed the hiro layout enable bug, so when you go to assign joypad
input, the window disables itself so your input doesn't mess with the
controls.

I added "reset" to the hotkeys, in case you feel like clearing all of
them at once.

I added device selection support and the ability to disable audio
synchronization (run > 60fps) to the ruby/OSS driver. This is exposed in
tomoko's configuration file.

I added checks to stringify so that assigning null char* strings to
nall::string won't cause crashes anymore (technically the crash was in
strlen(), which doesn't check for null strings, but whatever ... I'll do
the check myself.)

I hooked up BrowserDialog::folderSelect() to loading slotted media for
now. Tested it by loading a Game Boy game successfully through the Super
Game Boy. Definitely want to write a custom window for this though, that
looks more like the library dialog.

Remaining issues:
- finish slotted cart loader (SGB, BSX, ST)
- add DIP switch selection window (NSS) [I may end up punting this one
  to v096]
- add more configuration panels (video, audio, timing)
This commit is contained in:
Tim Allen
2015-05-25 22:23:49 +10:00
parent 99b2b4b57c
commit 7bf4cff946
21 changed files with 280 additions and 250 deletions

View File

@@ -1,9 +1,3 @@
/*
audio.openal (2007-12-26)
author: Nach
contributors: byuu, wertigon, _willow_
*/
#if defined(PLATFORM_MACOSX)
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
@@ -14,15 +8,14 @@
namespace ruby {
class pAudioOpenAL {
public:
struct pAudioOpenAL {
struct {
ALCdevice* handle;
ALCcontext* context;
ALuint source;
ALenum format;
unsigned latency;
unsigned queue_length;
unsigned queueLength;
} device;
struct {
@@ -37,21 +30,21 @@ public:
unsigned latency;
} settings;
bool cap(const string& name) {
auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
if(name == Audio::Latency) return true;
return false;
}
any get(const string& name) {
auto get(const string& name) -> any {
if(name == Audio::Synchronize) return settings.synchronize;
if(name == Audio::Frequency) return settings.frequency;
if(name == Audio::Latency) return settings.latency;
return false;
}
bool set(const string& name, const any& value) {
auto set(const string& name, const any& value) -> bool {
if(name == Audio::Synchronize) {
settings.synchronize = any_cast<bool>(value);
return true;
@@ -65,7 +58,7 @@ public:
if(name == Audio::Latency) {
if(settings.latency != any_cast<unsigned>(value)) {
settings.latency = any_cast<unsigned>(value);
update_latency();
updateLatency();
}
return true;
}
@@ -73,7 +66,7 @@ public:
return false;
}
void sample(uint16_t sl, uint16_t sr) {
auto sample(uint16_t sl, uint16_t sr) -> void {
buffer.data[buffer.length++] = sl + (sr << 16);
if(buffer.length < buffer.size) return;
@@ -84,17 +77,17 @@ public:
while(processed--) {
alSourceUnqueueBuffers(device.source, 1, &albuffer);
alDeleteBuffers(1, &albuffer);
device.queue_length--;
device.queueLength--;
}
//wait for buffer playback to catch up to sample generation if not synchronizing
if(settings.synchronize == false || device.queue_length < 3) break;
if(settings.synchronize == false || device.queueLength < 3) break;
}
if(device.queue_length < 3) {
if(device.queueLength < 3) {
alGenBuffers(1, &albuffer);
alBufferData(albuffer, device.format, buffer.data, buffer.size * 4, settings.frequency);
alSourceQueueBuffers(device.source, 1, &albuffer);
device.queue_length++;
device.queueLength++;
}
ALint playing;
@@ -103,32 +96,26 @@ public:
buffer.length = 0;
}
void clear() {
auto clear() -> void {
}
void update_latency() {
if(buffer.data) delete[] buffer.data;
buffer.size = settings.frequency * settings.latency / 1000.0 + 0.5;
buffer.data = new uint32_t[buffer.size];
}
bool init() {
update_latency();
device.queue_length = 0;
auto init() -> bool {
updateLatency();
device.queueLength = 0;
bool success = false;
if(device.handle = alcOpenDevice(NULL)) {
if(device.context = alcCreateContext(device.handle, NULL)) {
if(device.handle = alcOpenDevice(nullptr)) {
if(device.context = alcCreateContext(device.handle, nullptr)) {
alcMakeContextCurrent(device.context);
alGenSources(1, &device.source);
//alSourcef (device.source, AL_PITCH, 1.0);
//alSourcef (device.source, AL_GAIN, 1.0);
//alSource3f(device.source, AL_POSITION, 0.0, 0.0, 0.0);
//alSource3f(device.source, AL_VELOCITY, 0.0, 0.0, 0.0);
//alSource3f(device.source, AL_DIRECTION, 0.0, 0.0, 0.0);
//alSourcef (device.source, AL_ROLLOFF_FACTOR, 0.0);
//alSourcei (device.source, AL_SOURCE_RELATIVE, AL_TRUE);
//alSourcef (device.source, AL_PITCH, 1.0);
//alSourcef (device.source, AL_GAIN, 1.0);
//alSource3f(device.source, AL_POSITION, 0.0, 0.0, 0.0);
//alSource3f(device.source, AL_VELOCITY, 0.0, 0.0, 0.0);
//alSource3f(device.source, AL_DIRECTION, 0.0, 0.0, 0.0);
//alSourcef (device.source, AL_ROLLOFF_FACTOR, 0.0);
//alSourcei (device.source, AL_SOURCE_RELATIVE, AL_TRUE);
alListener3f(AL_POSITION, 0.0, 0.0, 0.0);
alListener3f(AL_VELOCITY, 0.0, 0.0, 0.0);
@@ -147,7 +134,7 @@ public:
return true;
}
void term() {
auto term() -> void {
if(alIsSource(device.source) == AL_TRUE) {
int playing = 0;
alGetSourcei(device.source, AL_SOURCE_STATE, &playing);
@@ -159,7 +146,7 @@ public:
ALuint albuffer = 0;
alSourceUnqueueBuffers(device.source, 1, &albuffer);
alDeleteBuffers(1, &albuffer);
device.queue_length--;
device.queueLength--;
}
}
@@ -168,7 +155,7 @@ public:
}
if(device.context) {
alcMakeContextCurrent(NULL);
alcMakeContextCurrent(nullptr);
alcDestroyContext(device.context);
device.context = 0;
}
@@ -189,7 +176,7 @@ public:
device.handle = 0;
device.context = 0;
device.format = AL_FORMAT_STEREO16;
device.queue_length = 0;
device.queueLength = 0;
buffer.data = 0;
buffer.length = 0;
@@ -203,6 +190,27 @@ public:
~pAudioOpenAL() {
term();
}
private:
auto queryDevices() -> lstring {
lstring result;
const char* buffer = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
if(!buffer) return result;
while(buffer[0] || buffer[1]) {
result.append(buffer);
while(buffer[0]) buffer++;
}
return result;
}
auto updateLatency() -> void {
if(buffer.data) delete[] buffer.data;
buffer.size = settings.frequency * settings.latency / 1000.0 + 0.5;
buffer.data = new uint32_t[buffer.size]();
}
};
DeclareAudio(OpenAL)

View File

@@ -1,8 +1,3 @@
/*
audio.oss (2007-12-26)
author: Nach
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
@@ -16,95 +11,112 @@
//Failing that, one can disable OSS4 ioctl calls inside init() and remove the below defines
#ifndef SNDCTL_DSP_COOKEDMODE
#define SNDCTL_DSP_COOKEDMODE _IOW('P', 30, int)
#define SNDCTL_DSP_COOKEDMODE _IOW('P', 30, signed)
#endif
#ifndef SNDCTL_DSP_POLICY
#define SNDCTL_DSP_POLICY _IOW('P', 45, int)
#define SNDCTL_DSP_POLICY _IOW('P', 45, signed)
#endif
namespace ruby {
class pAudioOSS {
public:
struct pAudioOSS {
struct {
int fd;
int format;
int channels;
const char* name;
signed fd = -1;
signed format = AFMT_S16_LE;
signed channels = 2;
} device;
struct {
unsigned frequency;
string device = "/dev/dsp";
bool synchronize = true;
unsigned frequency = 22050;
} settings;
bool cap(const string& name) {
~pAudioOSS() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Device) return true;
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
return false;
}
any get(const string& name) {
auto get(const string& name) -> any {
if(name == Audio::Device) return settings.device;
if(name == Audio::Synchronize) return settings.synchronize;
if(name == Audio::Frequency) return settings.frequency;
return false;
}
bool set(const string& name, const any& value) {
auto set(const string& name, const any& value) -> bool {
if(name == Audio::Device) {
settings.device = any_cast<string>(value);
if(!settings.device) settings.device = "/dev/dsp";
return true;
}
if(name == Audio::Synchronize) {
settings.synchronize = any_cast<bool>(value);
updateSynchronization();
return true;
}
if(name == Audio::Frequency) {
settings.frequency = any_cast<unsigned>(value);
if(device.fd > 0) init();
if(device.fd >= 0) init();
return true;
}
return false;
}
void sample(uint16_t sl, uint16_t sr) {
uint32_t sample = sl + (sr << 16);
unsigned unused = write(device.fd, &sample, 4);
auto sample(uint16_t left, uint16_t right) -> void {
uint32_t sample = left << 0 | right << 16;
auto unused = write(device.fd, &sample, 4);
}
void clear() {
auto clear() -> void {
}
bool init() {
auto init() -> bool {
term();
device.fd = open(device.name, O_WRONLY, O_NONBLOCK);
device.fd = open(settings.device, O_WRONLY, O_NONBLOCK);
if(device.fd < 0) return false;
#if 1 //SOUND_VERSION >= 0x040000
//attempt to enable OSS4-specific features regardless of version
//OSS3 ioctl calls will silently fail, but sound will still work
int cooked = 1, policy = 4; //policy should be 0 - 10, lower = less latency, more CPU usage
signed cooked = 1, policy = 4; //policy should be 0 - 10, lower = less latency, more CPU usage
ioctl(device.fd, SNDCTL_DSP_COOKEDMODE, &cooked);
ioctl(device.fd, SNDCTL_DSP_POLICY, &policy);
#endif
int freq = settings.frequency;
signed freq = settings.frequency;
ioctl(device.fd, SNDCTL_DSP_CHANNELS, &device.channels);
ioctl(device.fd, SNDCTL_DSP_SETFMT, &device.format);
ioctl(device.fd, SNDCTL_DSP_SPEED, &freq);
updateSynchronization();
return true;
}
void term() {
if(device.fd > 0) {
auto term() -> void {
if(device.fd >= 0) {
close(device.fd);
device.fd = -1;
}
}
pAudioOSS() {
device.fd = -1;
device.format = AFMT_S16_LE;
device.channels = 2;
device.name = "/dev/dsp";
settings.frequency = 22050;
}
~pAudioOSS() {
term();
private:
auto updateSynchronization() -> void {
if(device.fd < 0) return;
auto flags = fcntl(device.fd, F_GETFL);
if(flags < 0) return;
settings.synchronize ? flags &=~ O_NONBLOCK : flags |= O_NONBLOCK;
fcntl(device.fd, F_SETFL, flags);
}
};