diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 01aa0cec..095496dc 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "104.05"; + static const string Version = "104.06"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gba/gba.hpp b/higan/gba/gba.hpp index 5b92d39d..6a96c157 100644 --- a/higan/gba/gba.hpp +++ b/higan/gba/gba.hpp @@ -36,10 +36,6 @@ namespace GameBoyAdvance { inline auto synchronize(Thread& thread) -> void { if(clock() >= thread.clock()) scheduler.resume(thread); } - - inline auto step(uint clocks) -> void { - _clock += clocks; - } }; #include diff --git a/higan/processor/m68k/effective-address.cpp b/higan/processor/m68k/effective-address.cpp index 28ad251e..512825bb 100644 --- a/higan/processor/m68k/effective-address.cpp +++ b/higan/processor/m68k/effective-address.cpp @@ -86,14 +86,16 @@ template auto M68K::read(EffectiveAddress& ea) -> uint32 { } case AddressRegisterIndirectWithPostIncrement: { + auto address = ea.address + (ea.reg == 7 && Size == Byte ? bytes() : bytes()); auto data = read(ea.address); - if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes()); + if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return data; } case AddressRegisterIndirectWithPreDecrement: { - auto data = read(ea.address - bytes()); - if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes()); + auto address = ea.address - (ea.reg == 7 && Size == Byte ? bytes() : bytes()); + auto data = read(address); + if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return data; } @@ -148,14 +150,16 @@ template auto M68K::write(EffectiveAddress& ea, uint32 dat } case AddressRegisterIndirectWithPostIncrement: { + auto address = ea.address + (ea.reg == 7 && Size == Byte ? bytes() : bytes()); write(ea.address, data); - if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes()); + if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return; } case AddressRegisterIndirectWithPreDecrement: { - write(ea.address - bytes(), data); - if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes()); + auto address = ea.address - (ea.reg == 7 && Size == Byte ? bytes() : bytes()); + write(address, data); + if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return; } diff --git a/higan/target-tomoko/program/program.cpp b/higan/target-tomoko/program/program.cpp index 0a63b366..0c2c7f7c 100644 --- a/higan/target-tomoko/program/program.cpp +++ b/higan/target-tomoko/program/program.cpp @@ -43,33 +43,9 @@ Program::Program(string_vector args) { settings["Crashed"].setValue(true); settings.save(); - if(!Video::availableDrivers().find(settings["Video/Driver"].text())) { - settings["Video/Driver"].setValue("None"); - } - video = Video::create(settings["Video/Driver"].text()); - video->setContext(presentation->viewport.handle()); - video->setBlocking(settings["Video/Synchronize"].boolean()); - if(!video->ready()) MessageDialog().setText("Failed to initialize video driver").warning(); - presentation->clearViewport(); - - if(!Audio::availableDrivers().find(settings["Audio/Driver"].text())) { - settings["Audio/Driver"].setValue("None"); - } - audio = Audio::create(settings["Audio/Driver"].text()); - audio->setExclusive(settings["Audio/Exclusive"].boolean()); - audio->setContext(presentation->viewport.handle()); - audio->setDevice(settings["Audio/Device"].text()); - audio->setBlocking(settings["Audio/Synchronize"].boolean()); - audio->setChannels(2); - if(!audio->ready()) MessageDialog().setText("Failed to initialize audio driver").warning(); - - if(!Input::availableDrivers().find(settings["Input/Driver"].text())) { - settings["Input/Driver"].setValue("None"); - } - input = Input::create(settings["Input/Driver"].text()); - input->setContext(presentation->viewport.handle()); - input->onChange({&InputManager::onChange, &inputManager()}); - if(!input->ready()) MessageDialog().setText("Failed to initialize input driver").warning(); + initializeVideoDriver(); + initializeAudioDriver(); + initializeInputDriver(); settings["Crashed"].setValue(false); settings.save(); diff --git a/higan/target-tomoko/program/program.hpp b/higan/target-tomoko/program/program.hpp index f3a17008..4ca39ad3 100644 --- a/higan/target-tomoko/program/program.hpp +++ b/higan/target-tomoko/program/program.hpp @@ -26,6 +26,10 @@ struct Program : Emulator::Platform { auto saveState(uint slot, bool managed = false) -> bool; //utility.cpp + auto initializeVideoDriver() -> void; + auto initializeAudioDriver() -> void; + auto initializeInputDriver() -> void; + auto powerCycle() -> void; auto rotateDisplay() -> void; auto connectDevices() -> void; diff --git a/higan/target-tomoko/program/utility.cpp b/higan/target-tomoko/program/utility.cpp index cb223aba..6d13b8a7 100644 --- a/higan/target-tomoko/program/utility.cpp +++ b/higan/target-tomoko/program/utility.cpp @@ -1,3 +1,69 @@ +auto Program::initializeVideoDriver() -> void { + if(!Video::availableDrivers().find(settings["Video/Driver"].text())) { + settings["Video/Driver"].setValue("None"); + } + video = Video::create(settings["Video/Driver"].text()); + video->setContext(presentation->viewport.handle()); + + video->setBlocking(settings["Video/Synchronize"].boolean()); + + if(!video->ready()) { + MessageDialog().setText("Failed to initialize video driver").warning(); + video = Video::create("None"); + } + + presentation->clearViewport(); +} + +auto Program::initializeAudioDriver() -> void { + if(!Audio::availableDrivers().find(settings["Audio/Driver"].text())) { + settings["Audio/Driver"].setValue("None"); + } + audio = Audio::create(settings["Audio/Driver"].text()); + audio->setContext(presentation->viewport.handle()); + + if(!audio->availableDevices().find(settings["Audio/Device"].text())) { + settings["Audio/Device"].setValue(audio->availableDevices()(0)); + } + audio->setDevice(settings["Audio/Device"].text()); + + if(!audio->availableFrequencies().find(settings["Audio/Frequency"].real())) { + settings["Audio/Frequency"].setValue(audio->availableFrequencies()(0)); + } + audio->setFrequency(settings["Audio/Frequency"].real()); + + if(!audio->availableLatencies().find(settings["Audio/Latency"].natural())) { + settings["Audio/Latency"].setValue(audio->availableLatencies()(0)); + } + audio->setLatency(settings["Audio/Latency"].real()); + + audio->setChannels(2); + audio->setExclusive(settings["Audio/Exclusive"].boolean()); + audio->setBlocking(settings["Audio/Synchronize"].boolean()); + + if(!audio->ready()) { + MessageDialog().setText("Failed to initialize audio driver").warning(); + audio = Audio::create("None"); + } + + Emulator::audio.setFrequency(settings["Audio/Frequency"].real()); +} + +auto Program::initializeInputDriver() -> void { + if(!Input::availableDrivers().find(settings["Input/Driver"].text())) { + settings["Input/Driver"].setValue("None"); + } + input = Input::create(settings["Input/Driver"].text()); + input->setContext(presentation->viewport.handle()); + + input->onChange({&InputManager::onChange, &inputManager()}); + + if(!input->ready()) { + MessageDialog().setText("Failed to initialize input driver").warning(); + input = Input::create("None"); + } +} + auto Program::powerCycle() -> void { if(!emulator) return; emulator->power(); @@ -78,7 +144,6 @@ auto Program::updateVideoShader() -> void { auto Program::updateAudioDriver() -> void { if(!audio) return; audio->clear(); - audio->setDevice(settings["Audio/Device"].text()); audio->setExclusive(settings["Audio/Exclusive"].boolean()); audio->setFrequency(settings["Audio/Frequency"].real()); audio->setLatency(settings["Audio/Latency"].natural()); diff --git a/higan/target-tomoko/settings/audio.cpp b/higan/target-tomoko/settings/audio.cpp index 5e122c38..eba96f0c 100644 --- a/higan/target-tomoko/settings/audio.cpp +++ b/higan/target-tomoko/settings/audio.cpp @@ -7,11 +7,13 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { driverLabel.setFont(Font().setBold()).setText("Driver"); deviceLabel.setText("Device:"); - deviceList.onChange([&] { updateDevice(); updateDriver(); }); + deviceList.onChange([&] { + settings["Audio/Device"].setValue(deviceList.selected().text()); + program->initializeAudioDriver(); + updateDevice(); + }); - //the device list never changes once a driver is activated; - //however, the available frequencies and latencies may change when the active device is changed - for(auto& device : audio->information().devices) { + for(auto& device : audio->availableDevices()) { deviceList.append(ComboButtonItem().setText(device)); if(device == settings["Audio/Device"].text()) { deviceList.item(deviceList.itemCount() - 1).setSelected(); @@ -19,13 +21,22 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { } frequencyLabel.setText("Frequency:"); - frequencyList.onChange([&] { updateDriver(); }); + frequencyList.onChange([&] { + settings["Audio/Frequency"].setValue(frequencyList.selected().text()); + program->updateAudioDriver(); + }); latencyLabel.setText("Latency:"); - latencyList.onChange([&] { updateDriver(); }); + latencyList.onChange([&] { + settings["Audio/Latency"].setValue(latencyList.selected().text()); + program->updateAudioDriver(); + }); exclusiveMode.setText("Exclusive mode"); - exclusiveMode.setChecked(settings["Audio/Exclusive"].boolean()).onToggle([&] { updateDriver(); }); + exclusiveMode.setChecked(settings["Audio/Exclusive"].boolean()).onToggle([&] { + settings["Audio/Exclusive"].setValue(exclusiveMode.checked()); + program->updateAudioDriver(); + }); effectsLabel.setFont(Font().setBold()).setText("Effects"); @@ -40,13 +51,12 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { reverbEnable.setText("Reverb").setChecked(settings["Audio/Reverb/Enable"].boolean()).onToggle([&] { updateEffects(); }); updateDevice(); - updateDriver(true); updateEffects(true); } auto AudioSettings::updateDevice() -> void { frequencyList.reset(); - for(auto& frequency : audio->information().frequencies) { + for(auto& frequency : audio->availableFrequencies()) { frequencyList.append(ComboButtonItem().setText(frequency)); if(frequency == settings["Audio/Frequency"].real()) { frequencyList.item(frequencyList.itemCount() - 1).setSelected(); @@ -54,7 +64,7 @@ auto AudioSettings::updateDevice() -> void { } latencyList.reset(); - for(auto& latency : audio->information().latencies) { + for(auto& latency : audio->availableLatencies()) { latencyList.append(ComboButtonItem().setText(latency)); if(latency == settings["Audio/Latency"].natural()) { latencyList.item(latencyList.itemCount() - 1).setSelected(); @@ -62,15 +72,6 @@ auto AudioSettings::updateDevice() -> void { } } -auto AudioSettings::updateDriver(bool initializing) -> void { - settings["Audio/Device"].setValue(deviceList.selected().text()); - settings["Audio/Frequency"].setValue(frequencyList.selected().text()); - settings["Audio/Latency"].setValue(latencyList.selected().text()); - settings["Audio/Exclusive"].setValue(exclusiveMode.checked()); - - if(!initializing) program->updateAudioDriver(); -} - auto AudioSettings::updateEffects(bool initializing) -> void { settings["Audio/Volume"].setValue(volumeSlider.position()); volumeValue.setText({volumeSlider.position(), "%"}); diff --git a/higan/target-tomoko/settings/settings.hpp b/higan/target-tomoko/settings/settings.hpp index ae9fc436..3825d291 100644 --- a/higan/target-tomoko/settings/settings.hpp +++ b/higan/target-tomoko/settings/settings.hpp @@ -64,7 +64,6 @@ struct AudioSettings : TabFrameItem { CheckLabel reverbEnable{&layout, Size{~0, 0}}; auto updateDevice() -> void; - auto updateDriver(bool initializing = false) -> void; auto updateEffects(bool initializing = false) -> void; }; diff --git a/higan/ws/cartridge/cartridge.cpp b/higan/ws/cartridge/cartridge.cpp index 73c38758..db041159 100644 --- a/higan/ws/cartridge/cartridge.cpp +++ b/higan/ws/cartridge/cartridge.cpp @@ -44,18 +44,16 @@ auto Cartridge::power() -> void { auto Cartridge::load() -> bool { information = {}; - switch(system.model()) { - case Model::WonderSwan: + if(Model::WonderSwan()) { if(auto loaded = platform->load(ID::WonderSwan, "WonderSwan", "ws")) { information.pathID = loaded.pathID(); } else return false; - break; - case Model::WonderSwanColor: - case Model::SwanCrystal: + } + + if(Model::WonderSwanColor() || Model::SwanCrystal()) { if(auto loaded = platform->load(ID::WonderSwanColor, "WonderSwan Color", "wsc")) { information.pathID = loaded.pathID(); } else return false; - break; } if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) { diff --git a/higan/ws/cpu/cpu.cpp b/higan/ws/cpu/cpu.cpp index adf62b8f..25ffdc58 100644 --- a/higan/ws/cpu/cpu.cpp +++ b/higan/ws/cpu/cpu.cpp @@ -51,7 +51,7 @@ auto CPU::power() -> void { bus.map(this, 0x00a0); bus.map(this, 0x00b0, 0x00b6); - if(system.model() != Model::WonderSwan) { + if(!Model::WonderSwan()) { bus.map(this, 0x0040, 0x0049); bus.map(this, 0x0062); } diff --git a/higan/ws/cpu/io.cpp b/higan/ws/cpu/io.cpp index ee9a199a..9e809aa8 100644 --- a/higan/ws/cpu/io.cpp +++ b/higan/ws/cpu/io.cpp @@ -43,15 +43,15 @@ auto CPU::portRead(uint16 addr) -> uint8 { //WSC_SYSTEM if(addr == 0x0062) return ( - (system.model() == Model::SwanCrystal) << 7 + Model::SwanCrystal() << 7 ); //HW_FLAGS if(addr == 0x00a0) { - bool model = system.model() != Model::WonderSwan; + bool color = !Model::WonderSwan(); return ( 1 << 0 //0 = BIOS mapped; 1 = cartridge mapped - | model << 1 //0 = WonderSwan; 1 = WonderSwan Color or SwanCrystal + | color << 1 //0 = WonderSwan; 1 = WonderSwan Color or SwanCrystal | 1 << 2 //0 = 8-bit bus width; 1 = 16-bit bus width | 1 << 7 //1 = built-in self-test passed ); @@ -59,7 +59,7 @@ auto CPU::portRead(uint16 addr) -> uint8 { //INT_BASE if(addr == 0x00b0) return ( - r.interruptBase | (system.model() == Model::WonderSwan ? 3 : 0) + r.interruptBase | (Model::WonderSwan() ? 3 : 0) ); //SER_DATA @@ -122,7 +122,7 @@ auto CPU::portWrite(uint16 addr, uint8 data) -> void { //INT_BASE if(addr == 0x00b0) { - r.interruptBase = (system.model() == Model::WonderSwan) ? data & ~7 : data & ~1; + r.interruptBase = Model::WonderSwan() ? data & ~7 : data & ~1; } //SER_DATA diff --git a/higan/ws/interface/wonderswan-color.cpp b/higan/ws/interface/wonderswan-color.cpp index 8c527c65..1197fbc4 100644 --- a/higan/ws/interface/wonderswan-color.cpp +++ b/higan/ws/interface/wonderswan-color.cpp @@ -32,6 +32,6 @@ auto WonderSwanColorInterface::videoColor(uint32 color) -> uint64 { } auto WonderSwanColorInterface::load(uint id) -> bool { - if(id == ID::WonderSwanColor) return system.load(this, Model::WonderSwanColor); + if(id == ID::WonderSwanColor) return system.load(this, System::Model::WonderSwanColor); return false; } diff --git a/higan/ws/interface/wonderswan.cpp b/higan/ws/interface/wonderswan.cpp index 73c7b57d..90426109 100644 --- a/higan/ws/interface/wonderswan.cpp +++ b/higan/ws/interface/wonderswan.cpp @@ -35,6 +35,6 @@ auto WonderSwanInterface::videoColor(uint32 color) -> uint64 { } auto WonderSwanInterface::load(uint id) -> bool { - if(id == ID::WonderSwan) return system.load(this, Model::WonderSwan); + if(id == ID::WonderSwan) return system.load(this, System::Model::WonderSwan); return false; } diff --git a/higan/ws/memory/memory.cpp b/higan/ws/memory/memory.cpp index 9c402a56..2d46cab6 100644 --- a/higan/ws/memory/memory.cpp +++ b/higan/ws/memory/memory.cpp @@ -10,7 +10,7 @@ auto InternalRAM::power() -> void { } auto InternalRAM::serialize(serializer& s) -> void { - s.array(memory, system.model() == Model::WonderSwan ? 0x4000 : 0x10000); + s.array(memory, Model::WonderSwan() ? 0x4000 : 0x10000); } auto InternalRAM::read(uint16 addr, uint size) -> uint32 { diff --git a/higan/ws/ppu/io.cpp b/higan/ws/ppu/io.cpp index f2a009d8..1d0eafed 100644 --- a/higan/ws/ppu/io.cpp +++ b/higan/ws/ppu/io.cpp @@ -209,11 +209,11 @@ auto PPU::portWrite(uint16 addr, uint8 data) -> void { r.lcdContrast = data.bit (1); r.lcdUnknown = data.bits(2,7); - if(system.model() == Model::WonderSwanColor) { + if(Model::WonderSwanColor()) { r.lcdUnknown &= 0b111100; } - if(system.model() == Model::SwanCrystal) { + if(Model::SwanCrystal()) { r.lcdContrast = 0; r.lcdUnknown = 0; } diff --git a/higan/ws/system/system.hpp b/higan/ws/system/system.hpp index cace5ba6..ee590d79 100644 --- a/higan/ws/system/system.hpp +++ b/higan/ws/system/system.hpp @@ -1,4 +1,6 @@ struct System : IO { + enum class Model : uint { WonderSwan, WonderSwanColor, SwanCrystal }; + auto loaded() const -> bool { return _loaded; } auto model() const -> Model { return _model; } auto color() const -> bool { return r.color; } @@ -61,3 +63,7 @@ private: }; extern System system; + +auto Model::WonderSwan() -> bool { return system.model() == System::Model::WonderSwan; } +auto Model::WonderSwanColor() -> bool { return system.model() == System::Model::WonderSwanColor; } +auto Model::SwanCrystal() -> bool { return system.model() == System::Model::SwanCrystal; } diff --git a/higan/ws/ws.hpp b/higan/ws/ws.hpp index d8abee82..bf055fe4 100644 --- a/higan/ws/ws.hpp +++ b/higan/ws/ws.hpp @@ -18,12 +18,6 @@ namespace WonderSwan { extern Scheduler scheduler; extern Cheat cheat; - enum class Model : uint { - WonderSwan, //SW-001 (ASWAN) - WonderSwanColor, //WSC-001 (SPHINX) - SwanCrystal, //SCT-001 (SPHINX2) - }; - enum : uint { Byte = 1, Word = 2, Long = 4 }; struct Thread : Emulator::Thread { @@ -35,10 +29,12 @@ namespace WonderSwan { inline auto synchronize(Thread& thread) -> void { if(clock() >= thread.clock()) scheduler.resume(thread); } + }; - inline auto step(uint clocks) -> void { - _clock += clocks; - } + struct Model { + inline static auto WonderSwan() -> bool; //SW-001 (ASWAN) + inline static auto WonderSwanColor() -> bool; //WSC-001 (SPHINX) + inline static auto SwanCrystal() -> bool; //SCT-001 (SPHINX2) }; #include diff --git a/ruby/audio/alsa.cpp b/ruby/audio/alsa.cpp index 1e52c8aa..d8abf843 100644 --- a/ruby/audio/alsa.cpp +++ b/ruby/audio/alsa.cpp @@ -4,17 +4,23 @@ struct AudioALSA : Audio { AudioALSA() { initialize(); } ~AudioALSA() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = queryDevices(); - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {20, 40, 60, 80, 100}; - information.channels = {2}; - return information; + auto availableDevices() -> string_vector { + return queryDevices(); } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {20, 40, 60, 80, 100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto device() -> string { return _device; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return 2; } diff --git a/ruby/audio/ao.cpp b/ruby/audio/ao.cpp index 3afa0b2e..a2f8e37f 100644 --- a/ruby/audio/ao.cpp +++ b/ruby/audio/ao.cpp @@ -4,17 +4,23 @@ struct AudioAO : Audio { AudioAO() { initialize(); } ~AudioAO() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = {_device}; - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {100}; - information.channels = {2}; - return information; + auto availableDevices() -> string_vector { + return {"Default"}; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto blocking() -> bool { return true; } auto channels() -> uint { return 2; } auto frequency() -> double { return _frequency; } diff --git a/ruby/audio/asio.cpp b/ruby/audio/asio.cpp index 41dc6b2a..02bc013e 100644 --- a/ruby/audio/asio.cpp +++ b/ruby/audio/asio.cpp @@ -5,22 +5,32 @@ struct AudioASIO : Audio { AudioASIO() { self = this; initialize(); } ~AudioASIO() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - for(auto& device : _devices) information.devices.append(device.name); - information.frequencies = {_frequency}; - uint latencies[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 6144}; //factors of 6144 - for(auto& latency : latencies) { - if(latency < _active.minimumBufferSize) continue; - if(latency > _active.maximumBufferSize) continue; - information.latencies.append(latency); - } - information.channels = {1, 2}; - return information; + auto availableDevices() -> string_vector { + string_vector devices; + for(auto& device : _devices) devices.append(device.name); + return devices; } + auto availableFrequencies() -> vector { + return {_frequency}; + } + + auto availableLatencies() -> vector { + vector latencies; + uint latencyList[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 6144}; //factors of 6144 + for(auto& latency : latencyList) { + if(latency < _active.minimumBufferSize) continue; + if(latency > _active.maximumBufferSize) continue; + latencies.append(latency); + } + return latencies; + } + + auto availableChannels() -> vector { + return {1, 2}; + } + + auto ready() -> bool { return _ready; } auto context() -> uintptr { return _context; } auto device() -> string { return _device; } auto blocking() -> bool { return _blocking; } diff --git a/ruby/audio/directsound.cpp b/ruby/audio/directsound.cpp index ec234f9b..af760e5e 100644 --- a/ruby/audio/directsound.cpp +++ b/ruby/audio/directsound.cpp @@ -4,17 +4,23 @@ struct AudioDirectSound : Audio { AudioDirectSound() { initialize(); } ~AudioDirectSound() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = {"Default"}; - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {40, 60, 80, 100}; - information.channels = {2}; - return information; + auto availableDevices() -> string_vector { + return {"Default"}; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {40, 60, 80, 100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return _channels; } auto frequency() -> double { return _frequency; } diff --git a/ruby/audio/openal.cpp b/ruby/audio/openal.cpp index 60eac408..06a0973b 100644 --- a/ruby/audio/openal.cpp +++ b/ruby/audio/openal.cpp @@ -10,17 +10,25 @@ struct AudioOpenAL : Audio { AudioOpenAL() { initialize(); } ~AudioOpenAL() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - for(auto& device : queryDevices()) information.devices.append(device); - information.channels = {2}; - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {20, 40, 60, 80, 100}; - return information; + auto availableDevices() -> string_vector { + string_vector devices; + for(auto& device : queryDevices()) devices.append(device); + return devices; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {20, 40, 60, 80, 100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto device() -> string { return _device; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return _channels; } diff --git a/ruby/audio/oss.cpp b/ruby/audio/oss.cpp index d501079b..705c7a48 100644 --- a/ruby/audio/oss.cpp +++ b/ruby/audio/oss.cpp @@ -17,18 +17,26 @@ struct AudioOSS : Audio { AudioOSS() { initialize(); } ~AudioOSS() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = {"/dev/dsp"}; - for(auto& device : directory::files("/dev/", "dsp?*")) information.devices.append(string{"/dev/", device}); - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - information.channels = {1, 2}; - return information; + auto availableDevices() -> string_vector { + string_vector devices; + devices.append("/dev/dsp"); + for(auto& device : directory::files("/dev/", "dsp?*")) devices.append(string{"/dev/", device}); + return devices; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + } + + auto availableChannels() -> vector { + return {1, 2}; + } + + auto ready() -> bool { return _ready; } auto device() -> string { return _device; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return _channels; } @@ -78,8 +86,8 @@ private: auto initialize() -> bool { terminate(); - if(!information().devices.find(_device)) { - _device = information().devices.left(); + if(!availableDevices().find(_device)) { + _device = availableDevices().left(); } _fd = open(_device, O_WRONLY, O_NONBLOCK); diff --git a/ruby/audio/pulseaudio.cpp b/ruby/audio/pulseaudio.cpp index 0700f738..1e41e591 100644 --- a/ruby/audio/pulseaudio.cpp +++ b/ruby/audio/pulseaudio.cpp @@ -4,17 +4,23 @@ struct AudioPulseAudio : Audio { AudioPulseAudio() { initialize(); } ~AudioPulseAudio() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = {"Default"}; - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {20, 40, 60, 80, 100}; - information.channels = {2}; - return information; + auto availableDevices() -> string_vector { + return {"Default"}; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {20, 40, 60, 80, 100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return 2; } auto frequency() -> double { return _frequency; } diff --git a/ruby/audio/pulseaudiosimple.cpp b/ruby/audio/pulseaudiosimple.cpp index 95f2b1ac..275b1cd8 100644 --- a/ruby/audio/pulseaudiosimple.cpp +++ b/ruby/audio/pulseaudiosimple.cpp @@ -5,17 +5,23 @@ struct AudioPulseAudioSimple : Audio { AudioPulseAudioSimple() { initialize(); } ~AudioPulseAudioSimple() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = {"Default"}; - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {40}; - information.channels = {2}; - return information; + auto availableDevices() -> string_vector { + return {"Default"}; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {40}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto blocking() -> bool { return true; } auto channels() -> uint { return 2; } auto frequency() -> double { return _frequency; } diff --git a/ruby/audio/wasapi.cpp b/ruby/audio/wasapi.cpp index 4031bd34..feb0f781 100644 --- a/ruby/audio/wasapi.cpp +++ b/ruby/audio/wasapi.cpp @@ -10,17 +10,23 @@ struct AudioWASAPI : Audio { AudioWASAPI() { initialize(); } ~AudioWASAPI() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - for(auto& device : _devices) information.devices.append(device); - information.channels = {2}; - information.frequencies = {(double)_frequency}; - information.latencies = {0, 20, 40, 60, 80, 100}; - return information; + auto availableDevices() -> string_vector { + return _devices; } + auto availableFrequencies() -> vector { + return {(double)_frequency}; + } + + auto availableLatencies() -> vector { + return {0, 20, 40, 60, 80, 100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto exclusive() -> bool { return _exclusive; } auto device() -> string { return _device; } auto blocking() -> bool { return _blocking; } @@ -239,7 +245,7 @@ private: } _queue; IMMDeviceEnumerator* _enumerator = nullptr; - vector _devices; + string_vector _devices; IMMDevice* _audioDevice = nullptr; IAudioClient* _audioClient = nullptr; IAudioRenderClient* _renderClient = nullptr; diff --git a/ruby/audio/xaudio2.cpp b/ruby/audio/xaudio2.cpp index fab701b4..7cf36bd6 100644 --- a/ruby/audio/xaudio2.cpp +++ b/ruby/audio/xaudio2.cpp @@ -5,17 +5,23 @@ struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback { AudioXAudio2() { initialize(); } ~AudioXAudio2() { terminate(); } - auto ready() -> bool { return _ready; } - - auto information() -> Information { - Information information; - information.devices = {"Default"}; - information.channels = {2}; - information.frequencies = {44100.0, 48000.0, 96000.0}; - information.latencies = {20, 40, 60, 80, 100}; - return information; + auto availableDevices() -> string_vector { + return {"Default"}; } + auto availableFrequencies() -> vector { + return {44100.0, 48000.0, 96000.0}; + } + + auto availableLatencies() -> vector { + return {20, 40, 60, 80, 100}; + } + + auto availableChannels() -> vector { + return {2}; + } + + auto ready() -> bool { return _ready; } auto blocking() -> bool { return _blocking; } auto channels() -> uint { return _channels; } auto frequency() -> double { return _frequency; } diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index 798b4550..d2682931 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -53,18 +53,14 @@ struct Audio { static auto safestDriver() -> nall::string; static auto availableDrivers() -> nall::string_vector; - struct Information { - nall::string_vector devices; - nall::vector frequencies; - nall::vector latencies; - nall::vector channels; - }; - virtual ~Audio() = default; - virtual auto ready() -> bool { return true; } - virtual auto information() -> Information { return {{"Default"}, {48000.0}, {0}, {2}}; } + virtual auto availableDevices() -> nall::string_vector { return {"Default"}; } + virtual auto availableFrequencies() -> nall::vector { return {44100.0}; } + virtual auto availableLatencies() -> nall::vector { return {0}; } + virtual auto availableChannels() -> nall::vector { return {2}; } + virtual auto ready() -> bool { return true; } virtual auto exclusive() -> bool { return false; } virtual auto context() -> uintptr { return 0; } virtual auto device() -> nall::string { return "None"; }