diff --git a/higan/sfc/smp/timing.cpp b/higan/sfc/smp/timing.cpp index a2f6ac37..29246e8e 100644 --- a/higan/sfc/smp/timing.cpp +++ b/higan/sfc/smp/timing.cpp @@ -50,13 +50,10 @@ template auto SMP::Timer::step(uint clocks) -> void { } template auto SMP::Timer::synchronizeStage1() -> void { - bool newLine = stage1; - if(!smp.io.timersEnable) newLine = false; - if(smp.io.timersDisable) newLine = false; - - bool oldLine = line; - line = newLine; - if(oldLine != 1 || newLine != 0) return; //only pulse on 1->0 transition + bool level = stage1; + if(!smp.io.timersEnable) level = false; + if(smp.io.timersDisable) level = false; + if(!line.lower(level)) return; //only pulse on 1->0 transition //stage 2 increment if(!enable) return; diff --git a/higan/target-bsnes/bsnes.cpp b/higan/target-bsnes/bsnes.cpp index 2b6f9650..700bfec0 100644 --- a/higan/target-bsnes/bsnes.cpp +++ b/higan/target-bsnes/bsnes.cpp @@ -27,7 +27,7 @@ auto nall::main(vector arguments) -> void { } } Application::setName("bsnes"); - Application::setScreenSaver(false); + Application::setScreenSaver(!settings["UserInterface/SuppressScreenSaver"].boolean()); Application::locale().scan(locate("locales/")); Application::locale().select(locale); emulator = new SuperFamicom::Interface; diff --git a/higan/target-bsnes/input/input.cpp b/higan/target-bsnes/input/input.cpp index 1c9d1ff6..685fa6be 100644 --- a/higan/target-bsnes/input/input.cpp +++ b/higan/target-bsnes/input/input.cpp @@ -102,6 +102,12 @@ auto InputMapping::unbind() -> void { } auto InputMapping::poll() -> int16 { + if(turboID) { + auto& mapping = inputManager->ports[portID].devices[deviceID].mappings[turboID()]; + auto result = mapping.poll(); + if(result) return inputManager->turboCounter >= inputManager->turboFrequency; + } + int16 result; for(auto& mapping : mappings) { @@ -185,23 +191,53 @@ auto InputManager::initialize() -> void { if(!input) return; input->onChange({&InputManager::onChange, this}); + + lastPoll = chrono::millisecond(); frequency = max(1u, settings["Input/Frequency"].natural()); - for(auto& port : emulator->ports()) { + turboCounter = 0; + turboFrequency = max(1, settings["Input/Turbo/Frequency"].natural()); + + auto information = emulator->information(); + auto ports = emulator->ports(); + for(uint portID : range(ports.size())) { + auto& port = ports[portID]; InputPort inputPort{port.id, port.name}; - for(auto& device : emulator->devices(port.id)) { + auto devices = emulator->devices(port.id); + for(uint deviceID : range(devices.size())) { + auto& device = devices[deviceID]; InputDevice inputDevice{device.id, device.name}; - for(auto& input : emulator->inputs(device.id)) { + auto inputs = emulator->inputs(device.id); + for(uint inputID : range(inputs.size())) { + auto& input = inputs[inputID]; InputMapping inputMapping; + inputMapping.portID = portID; + inputMapping.deviceID = deviceID; + inputMapping.inputID = inputID; inputMapping.name = input.name; inputMapping.type = input.type; - inputMapping.path = string{"Emulator/", inputPort.name, "/", inputDevice.name, "/", inputMapping.name}.replace(" ", ""); + inputMapping.path = string{information.name, "/", inputPort.name, "/", inputDevice.name, "/", inputMapping.name}.replace(" ", ""); inputMapping.assignment = settings(inputMapping.path).text(); inputDevice.mappings.append(inputMapping); } + for(uint inputID : range(inputs.size())) { + auto& input = inputs[inputID]; + if(input.type != InputMapping::Type::Button && input.type != InputMapping::Type::Trigger) continue; + uint turboID = inputDevice.mappings.size(); + InputMapping inputMapping; + inputMapping.portID = portID; + inputMapping.deviceID = deviceID; + inputMapping.inputID = turboID; + inputMapping.name = string{"Turbo ", input.name}; + inputMapping.type = input.type; + inputMapping.path = string{information.name, "/", inputPort.name, "/", inputDevice.name, "/", inputMapping.name}.replace(" ", ""); + inputMapping.assignment = settings(inputMapping.path).text(); + inputDevice.mappings.append(inputMapping); + inputDevice.mappings[inputID].turboID = turboID; + } inputPort.devices.append(inputDevice); } - ports.append(inputPort); + this->ports.append(inputPort); } bindHotkeys(); @@ -242,6 +278,10 @@ auto InputManager::poll() -> void { } } +auto InputManager::frame() -> void { + if(++turboCounter >= turboFrequency * 2) turboCounter = 0; +} + auto InputManager::onChange(shared_pointer device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void { if(settingsWindow->focused()) { settingsWindow->input.inputEvent(device, group, input, oldValue, newValue); diff --git a/higan/target-bsnes/input/input.hpp b/higan/target-bsnes/input/input.hpp index 94deeb59..cc876eca 100644 --- a/higan/target-bsnes/input/input.hpp +++ b/higan/target-bsnes/input/input.hpp @@ -18,6 +18,11 @@ struct InputMapping { return type == Type::Rumble; } + uint portID = 0; + uint deviceID = 0; + uint inputID = 0; + maybe turboID; + string path; //configuration file key path string name; //input name (human readable) uint type = 0; @@ -34,6 +39,8 @@ struct InputMapping { Qualifier qualifier = Qualifier::None; }; vector mappings; + + uint3 turboCounter = 0; }; struct InputHotkey : InputMapping { @@ -64,6 +71,7 @@ struct InputManager { auto initialize() -> void; auto bind() -> void; auto poll() -> void; + auto frame() -> void; auto onChange(shared_pointer device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void; auto mapping(uint port, uint device, uint input) -> maybe; auto findMouse() -> shared_pointer; @@ -79,6 +87,9 @@ public: uint64 lastPoll; //time in milliseconds since last call to poll() uint64 frequency; //minimum time in milliseconds before poll() can be called again + + uint turboCounter = 0; + uint turboFrequency = 0; }; extern unique_pointer inputManager; diff --git a/higan/target-bsnes/presentation/presentation.cpp b/higan/target-bsnes/presentation/presentation.cpp index c1c590e5..589e640e 100644 --- a/higan/target-bsnes/presentation/presentation.cpp +++ b/higan/target-bsnes/presentation/presentation.cpp @@ -56,14 +56,6 @@ Presentation::Presentation() { emulator->configure("video/blurEmulation", blurEmulation.checked()); }).doToggle(); shaderMenu.setIcon(Icon::Emblem::Image).setText("Shader"); - synchronizeVideo.setText("Synchronize Video").setChecked(settings["Video/Blocking"].boolean()).onToggle([&] { - settings["Video/Blocking"].setValue(synchronizeVideo.checked()); - program->updateVideoBlocking(); - }); - synchronizeAudio.setText("Synchronize Audio").setChecked(settings["Audio/Blocking"].boolean()).onToggle([&] { - settings["Audio/Blocking"].setValue(synchronizeAudio.checked()); - program->updateAudioBlocking(); - }); muteAudio.setText("Mute Audio").setChecked(settings["Audio/Mute"].boolean()).onToggle([&] { settings["Audio/Mute"].setValue(muteAudio.checked()); program->updateAudioEffects(); @@ -82,28 +74,47 @@ Presentation::Presentation() { inputSettings.setIcon(Icon::Device::Joypad).setText("Input ...").onActivate([&] { settingsWindow->show(2); }); hotkeySettings.setIcon(Icon::Device::Keyboard).setText("Hotkeys ...").onActivate([&] { settingsWindow->show(3); }); pathSettings.setIcon(Icon::Emblem::Folder).setText("Paths ...").onActivate([&] { settingsWindow->show(4); }); - advancedSettings.setIcon(Icon::Action::Settings).setText("Advanced ...").onActivate([&] { settingsWindow->show(5); }); + configurationSettings.setIcon(Icon::Action::Settings).setText("Configuration ...").onActivate([&] { settingsWindow->show(5); }); + driverSettings.setIcon(Icon::Place::Settings).setText("Drivers ...").onActivate([&] { settingsWindow->show(6); }); toolsMenu.setText(tr("Tools")).setVisible(false); saveState.setIcon(Icon::Action::Save).setText("Save State"); for(uint index : range(QuickStates)) { - saveState.append(MenuItem().setText({"Slot ", 1 + index}).onActivate([=] { - program->saveState({"quick/slot ", 1 + index}); - })); + MenuItem item{&saveState}; + item.setProperty("name", {"quick/slot ", 1 + index}); + item.setProperty("title", {"Slot ", 1 + index}); + item.setText({"Slot ", 1 + index}); + item.onActivate([=] { program->saveState({"quick/slot ", 1 + index}); }); } loadState.setIcon(Icon::Media::Play).setText("Load State"); for(uint index : range(QuickStates)) { - loadState.append(MenuItem().setText({"Slot ", 1 + index}).onActivate([=] { - program->loadState({"quick/slot ", 1 + index}); - })); + MenuItem item{&loadState}; + item.setProperty("name", {"quick/slot ", 1 + index}); + item.setProperty("title", {"Slot ", 1 + index}); + item.setText({"Slot ", 1 + index}); + item.onActivate([=] { program->loadState({"quick/slot ", 1 + index}); }); } loadState.append(MenuSeparator()); - loadState.append(MenuItem().setIcon(Icon::Edit::Undo).setText("Undo Last Save").onActivate([&] { + loadState.append(MenuItem() + .setProperty("name", "quick/undo") + .setProperty("title", "Undo Last Save") + .setIcon(Icon::Edit::Undo).setText("Undo Last Save").onActivate([&] { program->loadState("quick/undo"); })); - loadState.append(MenuItem().setIcon(Icon::Edit::Redo).setText("Redo Last Undo").onActivate([&] { + loadState.append(MenuItem() + .setProperty("name", "quick/redo") + .setProperty("title", "Redo Last Undo") + .setIcon(Icon::Edit::Redo).setText("Redo Last Undo").onActivate([&] { program->loadState("quick/redo"); })); + loadState.append(MenuItem().setIcon(Icon::Edit::Clear).setText("Remove All States").onActivate([&] { + if(MessageDialog("Are you sure you want to permanently remove all quick states for this game?").setParent(*this).question() == "Yes") { + for(uint index : range(QuickStates)) program->removeState({"quick/slot ", 1 + index}); + program->removeState("quick/undo"); + program->removeState("quick/redo"); + updateStateMenus(); + } + })); speedMenu.setIcon(Icon::Device::Clock).setText("Speed"); speedSlowest.setText("50% (Slowest)").setProperty("multiplier", "2.0").onActivate([&] { program->updateAudioFrequency(); }); speedSlow.setText("75% (Slow)").setProperty("multiplier", "1.333").onActivate([&] { program->updateAudioFrequency(); }); @@ -230,13 +241,13 @@ auto Presentation::clearViewport() -> void { uint length; uint width = 16; uint height = 16; - if(video->lock(output, length, width, height)) { + if(video->acquire(output, length, width, height)) { for(uint y : range(height)) { auto line = output + y * (length >> 2); for(uint x : range(width)) *line++ = 0xff000000; } if(!emulator->loaded()) drawIcon(output, length, width, height); - video->unlock(); + video->release(); video->output(); } } @@ -338,6 +349,7 @@ auto Presentation::updateDeviceMenu() -> void { controllerPort2.reset(); expansionPort.reset(); + auto information = emulator->information(); for(auto& port : emulator->ports()) { Menu* menu = nullptr; if(port.name == "Controller Port 1") menu = &controllerPort1; @@ -345,7 +357,7 @@ auto Presentation::updateDeviceMenu() -> void { if(port.name == "Expansion Port") menu = &expansionPort; if(!menu) continue; - auto path = string{"Emulator/", port.name}.replace(" ", ""); + auto path = string{information.name, "/", port.name}.replace(" ", ""); auto deviceName = settings(path).text(); auto deviceID = emulator->connected(port.id); @@ -427,6 +439,38 @@ auto Presentation::updateSizeMenu() -> void { })); } +auto Presentation::updateStateMenus() -> void { + auto states = program->availableStates("quick/"); + + for(auto& action : saveState.actions()) { + if(auto item = action.cast()) { + if(auto name = item.property("name")) { + if(states.find(name)) { + auto timestamp = program->stateTimestamp(item.property("name")); + item.setText({item.property("title"), " [", chrono::local::datetime(timestamp), "]"}); + } else { + item.setText({item.property("title"), " [Empty]"}); + } + } + } + } + + for(auto& action : loadState.actions()) { + if(auto item = action.cast()) { + if(auto name = item.property("name")) { + if(states.find(name)) { + auto timestamp = program->stateTimestamp(item.property("name")); + item.setEnabled(true); + item.setText({item.property("title"), " [", chrono::local::datetime(timestamp), "]"}); + } else { + item.setEnabled(false); + item.setText({item.property("title"), " [Empty]"}); + } + } + } + } +} + auto Presentation::updateRecentGames() -> void { loadRecentGame.reset(); @@ -469,7 +513,7 @@ auto Presentation::updateRecentGames() -> void { program->load(); }); } else { - item.setText(tr("Empty")); + item.setText({"[", tr("Empty"), "]"}); item.setEnabled(false); } loadRecentGame.append(item); diff --git a/higan/target-bsnes/presentation/presentation.hpp b/higan/target-bsnes/presentation/presentation.hpp index 9f90f924..d587e290 100644 --- a/higan/target-bsnes/presentation/presentation.hpp +++ b/higan/target-bsnes/presentation/presentation.hpp @@ -36,6 +36,7 @@ struct Presentation : Window { auto updateDeviceMenu() -> void; auto updateDeviceSelections() -> void; auto updateSizeMenu() -> void; + auto updateStateMenus() -> void; auto clearRecentGames() -> void; auto updateRecentGames() -> void; auto addRecentGame(string location) -> void; @@ -67,8 +68,6 @@ struct Presentation : Window { MenuCheckItem blurEmulation{&outputMenu}; Menu shaderMenu{&settingsMenu}; MenuSeparator settingsSeparatorA{&settingsMenu}; - MenuCheckItem synchronizeVideo{&settingsMenu}; - MenuCheckItem synchronizeAudio{&settingsMenu}; MenuCheckItem muteAudio{&settingsMenu}; MenuCheckItem showStatusBar{&settingsMenu}; MenuSeparator settingsSeparatorB{&settingsMenu}; @@ -77,7 +76,8 @@ struct Presentation : Window { MenuItem inputSettings{&settingsMenu}; MenuItem hotkeySettings{&settingsMenu}; MenuItem pathSettings{&settingsMenu}; - MenuItem advancedSettings{&settingsMenu}; + MenuItem configurationSettings{&settingsMenu}; + MenuItem driverSettings{&settingsMenu}; Menu toolsMenu{&menuBar}; Menu saveState{&toolsMenu}; Menu loadState{&toolsMenu}; diff --git a/higan/target-bsnes/program/audio.cpp b/higan/target-bsnes/program/audio.cpp index 5708ae89..906e33f6 100644 --- a/higan/target-bsnes/program/audio.cpp +++ b/higan/target-bsnes/program/audio.cpp @@ -1,56 +1,56 @@ -auto Program::updateAudioDriver() -> void { +auto Program::updateAudioDriver(Window parent) -> void { + auto changed = (bool)audio; audio = Audio::create(settings["Audio/Driver"].text()); audio->setContext(presentation->viewport.handle()); audio->setChannels(2); + if(changed) { + settings["Audio/Device"].setValue(audio->defaultDevice()); + settings["Audio/Frequency"].setValue(audio->defaultFrequency()); + settings["Audio/Latency"].setValue(audio->defaultLatency()); + } updateAudioExclusive(); updateAudioDevice(); updateAudioBlocking(); - - settingsWindow->advanced.updateAudioDriver(); + updateAudioDynamic(); if(!audio->ready()) { MessageDialog({ "Error: failed to initialize [", settings["Audio/Driver"].text(), "] audio driver." - }).error(); + }).setParent(parent).error(); settings["Audio/Driver"].setValue("None"); - return updateAudioDriver(); + return updateAudioDriver(parent); } } auto Program::updateAudioExclusive() -> void { - if(!audio) return; - if(audio->hasExclusive()) { - audio->setExclusive(settings["Audio/Exclusive"].boolean()); - settingsWindow->audio.exclusiveMode.setEnabled(true).setChecked(settings["Audio/Exclusive"].boolean()); - audio->clear(); - updateAudioFrequency(); - updateAudioLatency(); - } else { - settingsWindow->audio.exclusiveMode.setEnabled(false).setChecked(false); - } + audio->setExclusive(settings["Audio/Exclusive"].boolean()); + updateAudioFrequency(); + updateAudioLatency(); } auto Program::updateAudioDevice() -> void { - if(!audio) return; audio->clear(); if(!audio->availableDevices().find(settings["Audio/Device"].text())) { - settings["Audio/Device"].setValue(audio->availableDevices()(0)); + settings["Audio/Device"].setValue(audio->defaultDevice()); } audio->setDevice(settings["Audio/Device"].text()); updateAudioFrequency(); updateAudioLatency(); - settingsWindow->audio.updateDevice(); } auto Program::updateAudioBlocking() -> void { + audio->clear(); audio->setBlocking(settings["Audio/Blocking"].boolean()); } +auto Program::updateAudioDynamic() -> void { + audio->setDynamic(settings["Audio/Dynamic"].boolean()); +} + auto Program::updateAudioFrequency() -> void { - if(!audio) return; audio->clear(); if(!audio->availableFrequencies().find(settings["Audio/Frequency"].real())) { - settings["Audio/Frequency"].setValue(audio->availableFrequencies()(0)); + settings["Audio/Frequency"].setValue(audio->defaultFrequency()); } audio->setFrequency(settings["Audio/Frequency"].real()); double frequency = settings["Audio/Frequency"].real() + settings["Audio/Skew"].integer(); @@ -58,17 +58,14 @@ auto Program::updateAudioFrequency() -> void { if(item.checked()) frequency *= item.property("multiplier").real(); } Emulator::audio.setFrequency(frequency); - settingsWindow->audio.updateFrequency(); } auto Program::updateAudioLatency() -> void { - if(!audio) return; audio->clear(); if(!audio->availableLatencies().find(settings["Audio/Latency"].natural())) { - settings["Audio/Latency"].setValue(audio->availableLatencies()(0)); + settings["Audio/Latency"].setValue(audio->defaultLatency()); } audio->setLatency(settings["Audio/Latency"].natural()); - settingsWindow->audio.updateLatency(); } auto Program::updateAudioEffects() -> void { diff --git a/higan/target-bsnes/program/game.cpp b/higan/target-bsnes/program/game.cpp index 7e2ca5d1..6493a843 100644 --- a/higan/target-bsnes/program/game.cpp +++ b/higan/target-bsnes/program/game.cpp @@ -3,14 +3,14 @@ auto Program::load() -> void { if(auto configuration = string::read(locate("configuration.bml"))) { emulator->configure(configuration); - settingsWindow->advanced.updateConfiguration(); + settingsWindow->configuration.updateConfiguration(); } if(!emulator->load()) return; gameQueue = {}; screenshot = {}; frameAdvance = false; - if(!verified() && settingsWindow->advanced.warnOnUnverifiedGames.checked()) { + if(!verified() && settingsWindow->configuration.warnOnUnverifiedGames.checked()) { auto response = MessageDialog( "Warning: this game image is unverified.\n" "Running it *may* be a security risk.\n\n" @@ -21,12 +21,12 @@ auto Program::load() -> void { return showMessage("Game loading cancelled"); } if(response == "Always") { - settingsWindow->advanced.warnOnUnverifiedGames.setChecked(false).doToggle(); + settingsWindow->configuration.warnOnUnverifiedGames.setChecked(false).doToggle(); } } hackCompatibility(); emulator->power(); - if(settingsWindow->advanced.autoLoadStateOnLoad.checked()) { + if(settingsWindow->configuration.autoLoadStateOnLoad.checked()) { program->loadState("quick/undo"); } showMessage({ @@ -37,6 +37,7 @@ auto Program::load() -> void { presentation->resetSystem.setEnabled(true); presentation->unloadGame.setEnabled(true); presentation->toolsMenu.setVisible(true); + presentation->updateStateMenus(); presentation->speedNormal.setChecked(); presentation->pauseEmulation.setChecked(false); presentation->updateStatusIcon(); @@ -284,7 +285,7 @@ auto Program::unload() -> void { if(!emulator->loaded()) return; toolsWindow->cheatEditor.saveCheats(); toolsWindow->setVisible(false); - if(settingsWindow->advanced.autoSaveStateOnUnload.checked()) { + if(settingsWindow->configuration.autoSaveStateOnUnload.checked()) { saveUndoState(); } if(auto configuration = emulator->configuration()) { diff --git a/higan/target-bsnes/program/hacks.cpp b/higan/target-bsnes/program/hacks.cpp index 8a24b9d5..180bf621 100644 --- a/higan/target-bsnes/program/hacks.cpp +++ b/higan/target-bsnes/program/hacks.cpp @@ -1,8 +1,8 @@ auto Program::hackCompatibility() -> void { - bool fastPPU = settingsWindow->advanced.fastPPUOption.checked(); - bool fastPPUNoSpriteLimit = settingsWindow->advanced.noSpriteLimit.checked(); - bool fastPPUHiresMode7 = settingsWindow->advanced.hiresMode7.checked(); - bool fastDSP = settingsWindow->advanced.fastDSPOption.checked(); + bool fastPPU = settingsWindow->configuration.fastPPUOption.checked(); + bool fastPPUNoSpriteLimit = settingsWindow->configuration.noSpriteLimit.checked(); + bool fastPPUHiresMode7 = settingsWindow->configuration.hiresMode7.checked(); + bool fastDSP = settingsWindow->configuration.fastDSPOption.checked(); auto label = superFamicom.label; if(label == "AIR STRIKE PATROL" || label == "DESERT FIGHTER") fastPPU = false; @@ -33,7 +33,7 @@ auto Program::hackPatchMemory(vector& data) -> void { auto Program::hackOverclockSuperFX() -> void { //todo: implement a better way of detecting SuperFX games //todo: apply multiplier changes on reset, not just on game load? - double multiplier = settingsWindow->advanced.superFXValue.text().natural() / 100.0; + double multiplier = settingsWindow->configuration.superFXValue.text().natural() / 100.0; if(multiplier == 1.0) return; auto label = superFamicom.label; diff --git a/higan/target-bsnes/program/input.cpp b/higan/target-bsnes/program/input.cpp index 260c011b..3259f903 100644 --- a/higan/target-bsnes/program/input.cpp +++ b/higan/target-bsnes/program/input.cpp @@ -1,17 +1,19 @@ -auto Program::updateInputDriver() -> void { +auto Program::updateInputDriver(Window parent) -> void { + auto changed = (bool)input; input = Input::create(settings["Input/Driver"].text()); input->setContext(presentation->viewport.handle()); + if(changed) { + } inputManager->initialize(); settingsWindow->input.reloadPorts(); settingsWindow->hotkeys.reloadMappings(); - settingsWindow->advanced.updateInputDriver(); if(!input->ready()) { MessageDialog({ "Error: failed to initialize [", settings["Input/Driver"].text(), "] input driver." - }).error(); + }).setParent(parent).error(); settings["Input/Driver"].setValue("None"); - return updateInputDriver(); + return updateInputDriver(parent); } } diff --git a/higan/target-bsnes/program/platform.cpp b/higan/target-bsnes/program/platform.cpp index 23045625..218c317b 100644 --- a/higan/target-bsnes/program/platform.cpp +++ b/higan/target-bsnes/program/platform.cpp @@ -210,17 +210,19 @@ auto Program::videoRefresh(uint display, const uint32* data, uint pitch, uint wi screenshot.width = width; screenshot.height = height; - if(video->lock(output, length, width, height)) { + if(video->acquire(output, length, width, height)) { length >>= 2; for(auto y : range(height)) { memory::copy(output + y * length, data + y * pitch, width); } - video->unlock(); + video->release(); video->output(); } + inputManager->frame(); + if(frameAdvance) { frameAdvance = false; presentation->pauseEmulation.setChecked(); @@ -243,7 +245,7 @@ auto Program::audioSample(const double* samples, uint channels) -> void { } auto Program::inputPoll(uint port, uint device, uint input) -> int16 { - if(focused() || settingsWindow->input.allowInput().checked()) { + if(focused() || settingsWindow->configuration.allowInput().checked()) { inputManager->poll(); if(auto mapping = inputManager->mapping(port, device, input)) { return mapping->poll(); @@ -253,7 +255,7 @@ auto Program::inputPoll(uint port, uint device, uint input) -> int16 { } auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void { - if(focused() || settingsWindow->input.allowInput().checked() || !enable) { + if(focused() || settingsWindow->configuration.allowInput().checked() || !enable) { if(auto mapping = inputManager->mapping(port, device, input)) { return mapping->rumble(enable); } diff --git a/higan/target-bsnes/program/program.cpp b/higan/target-bsnes/program/program.cpp index 1a2f56f3..ca5cf550 100644 --- a/higan/target-bsnes/program/program.cpp +++ b/higan/target-bsnes/program/program.cpp @@ -40,12 +40,16 @@ Program::Program(vector arguments) { settings["Crashed"].setValue(true); settings.save(); - updateVideoDriver(); - updateAudioDriver(); - updateInputDriver(); + updateVideoDriver(*presentation); + updateAudioDriver(*presentation); + updateInputDriver(*presentation); settings["Crashed"].setValue(false); settings.save(); + settingsWindow->drivers.videoDriverChanged(); + settingsWindow->drivers.audioDriverChanged(); + settingsWindow->drivers.inputDriverChanged(); + arguments.takeLeft(); //ignore program location in argument parsing for(auto& argument : arguments) { if(argument == "--fullscreen") { @@ -74,7 +78,7 @@ auto Program::main() -> void { } emulator->run(); - if(settingsWindow->advanced.autoSaveMemory.checked()) { + if(settingsWindow->configuration.autoSaveMemory.checked()) { auto currentTime = chrono::timestamp(); if(currentTime - autoSaveTime >= settings["Emulator/AutoSaveMemory/Interval"].natural()) { autoSaveTime = currentTime; diff --git a/higan/target-bsnes/program/program.hpp b/higan/target-bsnes/program/program.hpp index 418cbca8..5eb23aff 100644 --- a/higan/target-bsnes/program/program.hpp +++ b/higan/target-bsnes/program/program.hpp @@ -49,7 +49,8 @@ struct Program : Emulator::Platform { auto screenshotPath() -> string; //states.cpp - auto managedStates() -> vector; + auto availableStates(string type) -> vector; + auto stateTimestamp(string filename) -> uint64_t; auto loadState(string filename) -> bool; auto saveState(string filename) -> bool; auto saveUndoState() -> bool; @@ -58,23 +59,26 @@ struct Program : Emulator::Platform { auto renameState(string from, string to) -> bool; //video.cpp + auto updateVideoDriver(Window parent) -> void; auto updateVideoExclusive() -> void; - auto updateVideoDriver() -> void; auto updateVideoBlocking() -> void; + auto updateVideoFlush() -> void; + auto updateVideoFormat() -> void; auto updateVideoShader() -> void; auto updateVideoPalette() -> void; //audio.cpp - auto updateAudioDriver() -> void; + auto updateAudioDriver(Window parent) -> void; auto updateAudioExclusive() -> void; auto updateAudioDevice() -> void; auto updateAudioBlocking() -> void; + auto updateAudioDynamic() -> void; auto updateAudioFrequency() -> void; auto updateAudioLatency() -> void; auto updateAudioEffects() -> void; //input.cpp - auto updateInputDriver() -> void; + auto updateInputDriver(Window parent) -> void; //utility.cpp auto showMessage(string text) -> void; diff --git a/higan/target-bsnes/program/states.cpp b/higan/target-bsnes/program/states.cpp index 33156a02..49af5cab 100644 --- a/higan/target-bsnes/program/states.cpp +++ b/higan/target-bsnes/program/states.cpp @@ -1,21 +1,45 @@ -auto Program::managedStates() -> vector { - if(!emulator->loaded()) return {}; +auto Program::availableStates(string type) -> vector { + vector result; + if(!emulator->loaded()) return result; if(gamePath().endsWith("/")) { - return directory::ifiles({statePath(), "managed/"}, "*.bst"); + for(auto& file : directory::ifiles({statePath(), type}, "*.bst")) { + result.append({type, file.trimRight(".bst", 1L)}); + } } else { Decode::ZIP input; if(input.open(statePath())) { vector filenames; for(auto& file : input.file) { - if(file.name.match("managed/*.bst")) filenames.append(file.name.trimLeft("managed/", 1L)); + if(file.name.match({type, "*.bst"})) result.append(file.name.trimRight(".bst", 1L)); } - filenames.isort(); - return filenames; } } - return {}; + result.isort(); + return result; +} + +auto Program::stateTimestamp(string filename) -> uint64_t { + auto timestamp = chrono::timestamp(); + if(!emulator->loaded()) return timestamp; + + if(gamePath().endsWith("/")) { + string location = {statePath(), filename, ".bst"}; + timestamp = file::timestamp(location, file::time::modify); + } else { + string location = {filename, ".bst"}; + Decode::ZIP input; + if(input.open(statePath())) { + for(auto& file : input.file) { + if(file.name != location) continue; + timestamp = file.timestamp; + break; + } + } + } + + return timestamp; } auto Program::loadState(string filename) -> bool { @@ -26,9 +50,6 @@ auto Program::loadState(string filename) -> bool { if(gamePath().endsWith("/")) { string location = {statePath(), filename, ".bst"}; - if(!file::exists(location)) return showMessage({"[", prefix, "] not found"}), false; - if(filename != "quick/undo") saveUndoState(); - if(filename == "quick/undo") saveRedoState(); memory = file::read(location); } else { string location = {filename, ".bst"}; @@ -43,6 +64,8 @@ auto Program::loadState(string filename) -> bool { } if(memory) { + if(filename != "quick/undo") saveUndoState(); + if(filename == "quick/undo") saveRedoState(); serializer s{memory.data(), memory.size()}; if(!emulator->unserialize(s)) return showMessage({"[", prefix, "] is in incompatible format"}), false; return showMessage({"Loaded [", prefix, "]"}), true; @@ -65,7 +88,7 @@ auto Program::saveState(string filename) -> bool { } else { string location = {filename, ".bst"}; - struct State { string name; vector memory; }; + struct State { string name; time_t timestamp; vector memory; }; vector states; Decode::ZIP input; @@ -73,18 +96,19 @@ auto Program::saveState(string filename) -> bool { for(auto& file : input.file) { if(!file.name.endsWith(".bst")) continue; if(file.name == location) continue; - states.append({file.name, input.extract(file)}); + states.append({file.name, file.timestamp, input.extract(file)}); } } input.close(); Encode::ZIP output{statePath()}; for(auto& state : states) { - output.append(state.name, state.memory.data(), state.memory.size()); + output.append(state.name, state.memory.data(), state.memory.size(), state.timestamp); } output.append(location, s.data(), s.size()); } + if(filename.beginsWith("quick/")) presentation->updateStateMenus(); return showMessage({"Saved [", prefix, "]"}), true; } @@ -116,14 +140,14 @@ auto Program::removeState(string filename) -> bool { bool found = false; string location = {filename, ".bst"}; - struct State { string name; vector memory; }; + struct State { string name; time_t timestamp; vector memory; }; vector states; Decode::ZIP input; if(input.open(statePath())) { for(auto& file : input.file) { if(file.name == location) { found = true; continue; } - states.append({file.name, input.extract(file)}); + states.append({file.name, file.timestamp, input.extract(file)}); } } input.close(); @@ -131,7 +155,7 @@ auto Program::removeState(string filename) -> bool { if(states) { Encode::ZIP output{statePath()}; for(auto& state : states) { - output.append(state.name, state.memory.data(), state.memory.size()); + output.append(state.name, state.memory.data(), state.memory.size(), state.timestamp); } } else { //remove .bsz file if there are no states left in the archive @@ -154,21 +178,21 @@ auto Program::renameState(string from, string to) -> bool { from = {from, ".bst"}; to = {to, ".bst"}; - struct State { string name; vector memory; }; + struct State { string name; time_t timestamp; vector memory; }; vector states; Decode::ZIP input; if(input.open(statePath())) { for(auto& file : input.file) { if(file.name == from) { found = true; file.name = to; } - states.append({file.name, input.extract(file)}); + states.append({file.name, file.timestamp, input.extract(file)}); } } input.close(); Encode::ZIP output{statePath()}; for(auto& state : states) { - output.append(state.name, state.memory.data(), state.memory.size()); + output.append(state.name, state.memory.data(), state.memory.size(), state.timestamp); } return found; diff --git a/higan/target-bsnes/program/utility.cpp b/higan/target-bsnes/program/utility.cpp index 1d97af3e..8e06e239 100644 --- a/higan/target-bsnes/program/utility.cpp +++ b/higan/target-bsnes/program/utility.cpp @@ -21,7 +21,7 @@ auto Program::updateStatus() -> void { frameRate = tr("Unloaded"); } else if(presentation->pauseEmulation.checked()) { frameRate = tr("Paused"); - } else if(!focused() && settingsWindow->input.pauseEmulation.checked()) { + } else if(!focused() && settingsWindow->configuration.pauseEmulation.checked()) { frameRate = tr("Paused"); } else { frameRate = statusFrameRate; @@ -48,7 +48,7 @@ auto Program::captureScreenshot() -> bool { auto Program::paused() -> bool { if(!emulator->loaded()) return true; if(presentation->pauseEmulation.checked()) return true; - if(!focused() && settingsWindow->input.pauseEmulation.checked()) return true; + if(!focused() && settingsWindow->configuration.pauseEmulation.checked()) return true; return false; } diff --git a/higan/target-bsnes/program/video.cpp b/higan/target-bsnes/program/video.cpp index f7ee9b6a..bb68c5d6 100644 --- a/higan/target-bsnes/program/video.cpp +++ b/higan/target-bsnes/program/video.cpp @@ -1,8 +1,14 @@ -auto Program::updateVideoDriver() -> void { +auto Program::updateVideoDriver(Window parent) -> void { + auto changed = (bool)video; video = Video::create(settings["Video/Driver"].text()); video->setContext(presentation->viewport.handle()); + if(changed) { + settings["Video/Format"].setValue(video->defaultFormat()); + } updateVideoExclusive(); updateVideoBlocking(); + updateVideoFlush(); + updateVideoFormat(); updateVideoShader(); if(video->ready()) { @@ -14,32 +20,37 @@ auto Program::updateVideoDriver() -> void { if(!emulator->loaded()) presentation->clearViewport(); }); - settingsWindow->advanced.updateVideoDriver(); - if(!video->ready()) { MessageDialog({ "Error: failed to initialize [", settings["Video/Driver"].text(), "] video driver." - }).error(); + }).setParent(parent).error(); settings["Video/Driver"].setValue("None"); - return updateVideoDriver(); + return updateVideoDriver(parent); } presentation->updateShaders(); } auto Program::updateVideoExclusive() -> void { + //only enabled in fullscreen mode via Presentation::toggleFullScreen() video->setExclusive(false); - if(video->hasExclusive()) { - settingsWindow->video.exclusiveMode.setEnabled(true).setChecked(settings["Video/Exclusive"].boolean()); - } else { - settingsWindow->video.exclusiveMode.setEnabled(false).setChecked(false); - } } auto Program::updateVideoBlocking() -> void { video->setBlocking(settings["Video/Blocking"].boolean()); } +auto Program::updateVideoFlush() -> void { + video->setFlush(settings["Video/Flush"].boolean()); +} + +auto Program::updateVideoFormat() -> void { + if(!video->availableFormats().find(settings["Video/Format"].text())) { + settings["Video/Format"].setValue(video->defaultFormat()); + } + video->setFormat(settings["Video/Format"].text()); +} + auto Program::updateVideoShader() -> void { if(settings["Video/Driver"].text() == "OpenGL" && settings["Video/Shader"].text() != "None" diff --git a/higan/target-bsnes/settings/advanced.cpp b/higan/target-bsnes/settings/advanced.cpp deleted file mode 100644 index 511dab4b..00000000 --- a/higan/target-bsnes/settings/advanced.cpp +++ /dev/null @@ -1,148 +0,0 @@ -AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) { - setIcon(Icon::Action::Settings); - setText("Advanced"); - - layout.setPadding(5); - driversLabel.setText("Drivers").setFont(Font().setBold()); - - videoDriverLabel.setText("Video:"); - videoDriverOption.onChange([&] { - auto item = videoDriverOption.selected(); - settings["Video/Driver"].setValue(item.text()); - if(!emulator->loaded() || item.text() == "None" || MessageDialog( - "Warning: incompatible drivers may cause bsnes to crash.\n" - "It is highly recommended you unload your game first to avoid data loss.\n" - "Do you wish to proceed with the video driver change now anyway?" - ).setParent(*settingsWindow).question() == "Yes") { - program->save(); - program->saveUndoState(); - settings["Crashed"].setValue(true); - settings.save(); - program->updateVideoDriver(); - settings["Crashed"].setValue(false); - settings.save(); - } - }); - - audioDriverLabel.setText("Audio:"); - audioDriverOption.onChange([&] { - auto item = audioDriverOption.selected(); - settings["Audio/Driver"].setValue(item.text()); - if(!emulator->loaded() || item.text() == "None" || MessageDialog( - "Warning: incompatible drivers may cause bsnes to crash.\n" - "It is highly recommended you unload your game first to avoid data loss.\n" - "Do you wish to proceed with the audio driver change now anyway?" - ).setParent(*settingsWindow).question() == "Yes") { - program->save(); - program->saveUndoState(); - settings["Crashed"].setValue(true); - settings.save(); - program->updateAudioDriver(); - settings["Crashed"].setValue(false); - settings.save(); - } - }); - - inputDriverLabel.setText("Input:"); - inputDriverOption.onChange([&] { - auto item = inputDriverOption.selected(); - settings["Input/Driver"].setValue(item.text()); - if(!emulator->loaded() || item.text() == "None" || MessageDialog( - "Warning: incompatible drivers may cause bsnes to crash.\n" - "It is highly recommended you unload your game first to avoid data loss.\n" - "Do you wish to proceed with the input driver change now anyway?" - ).setParent(*settingsWindow).question() == "Yes") { - program->save(); - program->saveUndoState(); - settings["Crashed"].setValue(true); - settings.save(); - program->updateInputDriver(); - settings["Crashed"].setValue(false); - settings.save(); - } - }); - - optionsLabel.setText("Options").setFont(Font().setBold()); - warnOnUnverifiedGames.setText("Warn when loading games that have not been verified").setChecked(settings["Emulator/WarnOnUnverifiedGames"].boolean()).onToggle([&] { - settings["Emulator/WarnOnUnverifiedGames"].setValue(warnOnUnverifiedGames.checked()); - }); - autoSaveMemory.setText("Auto-save memory periodically").setChecked(settings["Emulator/AutoSaveMemory/Enable"].boolean()).onToggle([&] { - settings["Emulator/AutoSaveMemory/Enable"].setValue(autoSaveMemory.checked()); - }); - autoSaveStateOnUnload.setText("Auto-save undo state when unloading games").setChecked(settings["Emulator/AutoSaveStateOnUnload"].boolean()).onToggle([&] { - settings["Emulator/AutoSaveStateOnUnload"].setValue(autoSaveStateOnUnload.checked()); - if(!autoSaveStateOnUnload.checked()) { - autoLoadStateOnLoad.setEnabled(false).setChecked(false).doToggle(); - } else { - autoLoadStateOnLoad.setEnabled(true); - } - }).doToggle(); - autoLoadStateOnLoad.setText("Auto-resume on load").setChecked(settings["Emulator/AutoLoadStateOnLoad"].boolean()).onToggle([&] { - settings["Emulator/AutoLoadStateOnLoad"].setValue(autoLoadStateOnLoad.checked()); - }); - - hacksLabel.setText("Emulator Hacks").setFont(Font().setBold()); - fastPPUOption.setText("Fast PPU").setChecked(settings["Emulator/Hack/FastPPU"].boolean()).onToggle([&] { - settings["Emulator/Hack/FastPPU"].setValue(fastPPUOption.checked()); - if(!fastPPUOption.checked()) { - noSpriteLimit.setEnabled(false).setChecked(false).doToggle(); - hiresMode7.setEnabled(false).setChecked(false).doToggle(); - } else { - noSpriteLimit.setEnabled(true); - hiresMode7.setEnabled(true); - } - }).doToggle(); - noSpriteLimit.setText("No sprite limit").setChecked(settings["Emulator/Hack/FastPPU/NoSpriteLimit"].boolean()).onToggle([&] { - settings["Emulator/Hack/FastPPU/NoSpriteLimit"].setValue(noSpriteLimit.checked()); - }); - hiresMode7.setText("Hires mode 7").setChecked(settings["Emulator/Hack/FastPPU/HiresMode7"].boolean()).onToggle([&] { - settings["Emulator/Hack/FastPPU/HiresMode7"].setValue(hiresMode7.checked()); - }); - fastDSPOption.setText("Fast DSP").setChecked(settings["Emulator/Hack/FastDSP"].boolean()).onToggle([&] { - settings["Emulator/Hack/FastDSP"].setValue(fastDSPOption.checked()); - }); - superFXLabel.setText("SuperFX clock speed:"); - superFXValue.setAlignment(0.5); - superFXClock.setLength(71).setPosition((settings["Emulator/Hack/FastSuperFX"].natural() - 100) / 10).onChange([&] { - settings["Emulator/Hack/FastSuperFX"].setValue({superFXClock.position() * 10 + 100, "%"}); - superFXValue.setText(settings["Emulator/Hack/FastSuperFX"].text()); - }).doChange(); - hacksNote.setForegroundColor({224, 0, 0}).setText("Note: some hack setting changes do not take effect until after reloading games."); -} - -auto AdvancedSettings::updateVideoDriver() -> void { - videoDriverOption.reset(); - for(auto& driver : Video::availableDrivers()) { - ComboButtonItem item; - item.setText(driver); - videoDriverOption.append(item); - if(video && video->driver() == driver) item.setSelected(); - } -} - -auto AdvancedSettings::updateAudioDriver() -> void { - audioDriverOption.reset(); - for(auto& driver : Audio::availableDrivers()) { - ComboButtonItem item; - item.setText(driver); - audioDriverOption.append(item); - if(audio && audio->driver() == driver) item.setSelected(); - } -} - -auto AdvancedSettings::updateInputDriver() -> void { - inputDriverOption.reset(); - for(auto& driver : Input::availableDrivers()) { - ComboButtonItem item; - item.setText(driver); - inputDriverOption.append(item); - if(input && input->driver() == driver) item.setSelected(); - } -} - -auto AdvancedSettings::updateConfiguration() -> void { - emulator->configure("hacks/ppuFast/enable", fastPPUOption.checked()); - emulator->configure("hacks/ppuFast/noSpriteLimit", noSpriteLimit.checked()); - emulator->configure("hacks/ppuFast/hiresMode7", hiresMode7.checked()); - emulator->configure("hacks/dspFast/enable", fastDSPOption.checked()); -} diff --git a/higan/target-bsnes/settings/audio.cpp b/higan/target-bsnes/settings/audio.cpp index 33c0da9e..9826c200 100644 --- a/higan/target-bsnes/settings/audio.cpp +++ b/higan/target-bsnes/settings/audio.cpp @@ -4,27 +4,6 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { layout.setPadding(5); - driverLabel.setFont(Font().setBold()).setText("Driver"); - deviceLabel.setText("Device:"); - deviceList.onChange([&] { - settings["Audio/Device"].setValue(deviceList.selected().text()); - program->updateAudioDevice(); - }); - frequencyLabel.setText("Frequency:"); - frequencyList.onChange([&] { - settings["Audio/Frequency"].setValue(frequencyList.selected().text()); - program->updateAudioFrequency(); - }); - latencyLabel.setText("Latency:"); - latencyList.onChange([&] { - settings["Audio/Latency"].setValue(latencyList.selected().text()); - program->updateAudioLatency(); - }); - exclusiveMode.setText("Exclusive mode").setChecked(settings["Audio/Exclusive"].boolean()).onToggle([&] { - settings["Audio/Exclusive"].setValue(exclusiveMode.checked()); - program->updateAudioExclusive(); - }); - effectsLabel.setFont(Font().setBold()).setText("Effects"); effectsLayout.setSize({3, 3}); effectsLayout.column(0).setAlignment(1.0); @@ -34,7 +13,7 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { string value = {skewSlider.position() > 5000 ? "+" : "", (int)skewSlider.position() - 5000}; settings["Audio/Skew"].setValue(value); skewValue.setText(value); - program->updateAudioFrequency(); + if(audio) program->updateAudioFrequency(); }).doChange(); volumeLabel.setText("Volume:"); volumeValue.setAlignment(0.5); @@ -42,7 +21,7 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { string value = {volumeSlider.position(), "%"}; settings["Audio/Volume"].setValue(value); volumeValue.setText(value); - program->updateAudioEffects(); + if(audio) program->updateAudioEffects(); }).doChange(); balanceLabel.setText("Balance:"); balanceValue.setAlignment(0.5); @@ -50,36 +29,6 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { string value = {balanceSlider.position(), "%"}; settings["Audio/Balance"].setValue(value); balanceValue.setText(value); - program->updateAudioEffects(); + if(audio) program->updateAudioEffects(); }).doChange(); } - -auto AudioSettings::updateDevice() -> void { - deviceList.reset(); - for(auto& device : audio->availableDevices()) { - deviceList.append(ComboButtonItem().setText(device)); - if(device == settings["Audio/Device"].text()) { - deviceList.items().right().setSelected(); - } - } -} - -auto AudioSettings::updateFrequency() -> void { - frequencyList.reset(); - for(auto& frequency : audio->availableFrequencies()) { - frequencyList.append(ComboButtonItem().setText((uint)frequency)); - if(frequency == settings["Audio/Frequency"].real()) { - frequencyList.items().right().setSelected(); - } - } -} - -auto AudioSettings::updateLatency() -> void { - latencyList.reset(); - for(auto& latency : audio->availableLatencies()) { - latencyList.append(ComboButtonItem().setText(latency)); - if(latency == settings["Audio/Latency"].natural()) { - latencyList.items().right().setSelected(); - } - } -} diff --git a/higan/target-bsnes/settings/configuration.cpp b/higan/target-bsnes/settings/configuration.cpp new file mode 100644 index 00000000..89b3f85f --- /dev/null +++ b/higan/target-bsnes/settings/configuration.cpp @@ -0,0 +1,77 @@ +ConfigurationSettings::ConfigurationSettings(TabFrame* parent) : TabFrameItem(parent) { + setIcon(Icon::Action::Settings); + setText("Configuration"); + + layout.setPadding(5); + + optionsLabel.setText("Options").setFont(Font().setBold()); + inputFocusLabel.setText("When focus is lost:"); + pauseEmulation.setText("Pause emulation").onActivate([&] { + settings["Input/Defocus"].setValue("Pause"); + }); + blockInput.setText("Block input").onActivate([&] { + settings["Input/Defocus"].setValue("Block"); + }); + allowInput.setText("Allow input").onActivate([&] { + settings["Input/Defocus"].setValue("Allow"); + }); + if(settings["Input/Defocus"].text() == "Pause") pauseEmulation.setChecked(); + if(settings["Input/Defocus"].text() == "Block") blockInput.setChecked(); + if(settings["Input/Defocus"].text() == "Allow") allowInput.setChecked(); + warnOnUnverifiedGames.setText("Warn when loading games that have not been verified").setChecked(settings["Emulator/WarnOnUnverifiedGames"].boolean()).onToggle([&] { + settings["Emulator/WarnOnUnverifiedGames"].setValue(warnOnUnverifiedGames.checked()); + }); + autoSaveMemory.setText("Auto-save memory periodically").setChecked(settings["Emulator/AutoSaveMemory/Enable"].boolean()).onToggle([&] { + settings["Emulator/AutoSaveMemory/Enable"].setValue(autoSaveMemory.checked()); + }); + autoSaveStateOnUnload.setText("Auto-save undo state when unloading games").setChecked(settings["Emulator/AutoSaveStateOnUnload"].boolean()).onToggle([&] { + settings["Emulator/AutoSaveStateOnUnload"].setValue(autoSaveStateOnUnload.checked()); + if(!autoSaveStateOnUnload.checked()) { + autoLoadStateOnLoad.setEnabled(false).setChecked(false).doToggle(); + } else { + autoLoadStateOnLoad.setEnabled(true); + } + }).doToggle(); + autoLoadStateOnLoad.setText("Auto-resume on load").setChecked(settings["Emulator/AutoLoadStateOnLoad"].boolean()).onToggle([&] { + settings["Emulator/AutoLoadStateOnLoad"].setValue(autoLoadStateOnLoad.checked()); + }); + suppressScreenSaver.setText("Suppress screen saver").setChecked(settings["UserInterface/SuppressScreenSaver"].boolean()).onToggle([&] { + settings["UserInterface/SuppressScreenSaver"].setValue(suppressScreenSaver.checked()); + Application::setScreenSaver(!suppressScreenSaver.checked()); + }); + + hacksLabel.setText("Emulator Hacks").setFont(Font().setBold()); + fastPPUOption.setText("Fast PPU").setChecked(settings["Emulator/Hack/FastPPU"].boolean()).onToggle([&] { + settings["Emulator/Hack/FastPPU"].setValue(fastPPUOption.checked()); + if(!fastPPUOption.checked()) { + noSpriteLimit.setEnabled(false).setChecked(false).doToggle(); + hiresMode7.setEnabled(false).setChecked(false).doToggle(); + } else { + noSpriteLimit.setEnabled(true); + hiresMode7.setEnabled(true); + } + }).doToggle(); + noSpriteLimit.setText("No sprite limit").setChecked(settings["Emulator/Hack/FastPPU/NoSpriteLimit"].boolean()).onToggle([&] { + settings["Emulator/Hack/FastPPU/NoSpriteLimit"].setValue(noSpriteLimit.checked()); + }); + hiresMode7.setText("Hires mode 7").setChecked(settings["Emulator/Hack/FastPPU/HiresMode7"].boolean()).onToggle([&] { + settings["Emulator/Hack/FastPPU/HiresMode7"].setValue(hiresMode7.checked()); + }); + fastDSPOption.setText("Fast DSP").setChecked(settings["Emulator/Hack/FastDSP"].boolean()).onToggle([&] { + settings["Emulator/Hack/FastDSP"].setValue(fastDSPOption.checked()); + }); + superFXLabel.setText("SuperFX clock speed:"); + superFXValue.setAlignment(0.5); + superFXClock.setLength(71).setPosition((settings["Emulator/Hack/FastSuperFX"].natural() - 100) / 10).onChange([&] { + settings["Emulator/Hack/FastSuperFX"].setValue({superFXClock.position() * 10 + 100, "%"}); + superFXValue.setText(settings["Emulator/Hack/FastSuperFX"].text()); + }).doChange(); + hacksNote.setForegroundColor({224, 0, 0}).setText("Note: some hack setting changes do not take effect until after reloading games."); +} + +auto ConfigurationSettings::updateConfiguration() -> void { + emulator->configure("hacks/ppuFast/enable", fastPPUOption.checked()); + emulator->configure("hacks/ppuFast/noSpriteLimit", noSpriteLimit.checked()); + emulator->configure("hacks/ppuFast/hiresMode7", hiresMode7.checked()); + emulator->configure("hacks/dspFast/enable", fastDSPOption.checked()); +} diff --git a/higan/target-bsnes/settings/drivers.cpp b/higan/target-bsnes/settings/drivers.cpp new file mode 100644 index 00000000..bc90dc4d --- /dev/null +++ b/higan/target-bsnes/settings/drivers.cpp @@ -0,0 +1,246 @@ +DriverSettings::DriverSettings(TabFrame* parent) : TabFrameItem(parent) { + setIcon(Icon::Place::Settings); + setText("Drivers"); + + layout.setPadding(5); + + videoLabel.setText("Video").setFont(Font().setBold()); + videoLayout.setSize({2, 2}); + videoDriverLabel.setText("Driver:"); + videoDriverOption.onChange([&] { + videoDriverUpdate.setEnabled(videoDriverOption.selected().text() != video->driver()); + }); + videoDriverUpdate.setText("Change").onActivate([&] { videoDriverChange(); }); + videoFormatLabel.setText("Format:"); + videoFormatOption.onChange([&] { videoFormatChange(); }); + videoExclusiveToggle.setText("Exclusive fullscreen").onToggle([&] { + settings["Video/Exclusive"].setValue(videoExclusiveToggle.checked()); + program->updateVideoExclusive(); + }); + videoBlockingToggle.setText("Synchronize").onToggle([&] { + settings["Video/Blocking"].setValue(videoBlockingToggle.checked()); + program->updateVideoBlocking(); + }); + videoFlushToggle.setText("GPU sync").onToggle([&] { + settings["Video/Flush"].setValue(videoFlushToggle.checked()); + program->updateVideoFlush(); + }); + + audioLabel.setText("Audio").setFont(Font().setBold()); + audioLayout.setSize({2, 2}); + audioDriverLabel.setText("Driver:"); + audioDriverOption.onChange([&] { + audioDriverUpdate.setEnabled(audioDriverOption.selected().text() != audio->driver()); + }); + audioDriverUpdate.setText("Change").onActivate([&] { audioDriverChange(); }); + audioDeviceLabel.setText("Device:"); + audioDeviceOption.onChange([&] { audioDeviceChange(); }); + audioFrequencyLabel.setText("Frequency:"); + audioFrequencyOption.onChange([&] { audioFrequencyChange(); }); + audioLatencyLabel.setText("Latency:"); + audioLatencyOption.onChange([&] { audioLatencyChange(); }); + audioExclusiveToggle.setText("Exclusive").onToggle([&] { + settings["Audio/Exclusive"].setValue(audioExclusiveToggle.checked()); + program->updateAudioExclusive(); + }); + audioBlockingToggle.setText("Synchronize").onToggle([&] { + settings["Audio/Blocking"].setValue(audioBlockingToggle.checked()); + program->updateAudioBlocking(); + }); + audioDynamicToggle.setText("Dynamic rate").onToggle([&] { + settings["Audio/Dynamic"].setValue(audioDynamicToggle.checked()); + program->updateAudioDynamic(); + }); + + inputLabel.setText("Input").setFont(Font().setBold()); + inputLayout.setSize({2, 1}); + inputDriverLabel.setText("Driver:"); + inputDriverOption.onChange([&] { + inputDriverUpdate.setEnabled(inputDriverOption.selected().text() != input->driver()); + }); + inputDriverUpdate.setText("Change").onActivate([&] { inputDriverChange(); }); + + //hide video format for simplicity, as it's not very useful just yet ... + videoLayout.setSize({2, 1}); + videoLayout.remove(videoFormatLabel); + videoLayout.remove(videoPropertyLayout); +} + +// + +auto DriverSettings::videoDriverChanged() -> void { + videoDriverOption.reset(); + for(auto& driver : video->availableDrivers()) { + ComboButtonItem item{&videoDriverOption}; + item.setText(driver); + if(driver == video->driver()) item.setSelected(); + } + videoDriverActive.setText({"Active driver: ", video->driver()}); + videoDriverOption.doChange(); + videoFormatChanged(); + videoExclusiveToggle.setChecked(video->exclusive()).setEnabled(video->hasExclusive()); + videoBlockingToggle.setChecked(video->blocking()).setEnabled(video->hasBlocking()); + videoFlushToggle.setChecked(video->flush()).setEnabled(video->hasFlush()); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::videoDriverChange() -> void { + auto item = videoDriverOption.selected(); + settings["Video/Driver"].setValue(item.text()); + if(!emulator->loaded() || item.text() == "None" || MessageDialog( + "Warning: incompatible drivers may cause bsnes to crash.\n" + "It is highly recommended you unload your game first to be safe.\n" + "Do you wish to proceed with the video driver change now anyway?" + ).setParent(*settingsWindow).question() == "Yes") { + program->save(); + program->saveUndoState(); + settings["Crashed"].setValue(true); + settings.save(); + program->updateVideoDriver(*settingsWindow); + settings["Crashed"].setValue(false); + settings.save(); + videoDriverChanged(); + } +} + +auto DriverSettings::videoFormatChanged() -> void { + videoFormatOption.reset(); + for(auto& format : video->availableFormats()) { + ComboButtonItem item{&videoFormatOption}; + item.setText(format); + if(format == video->format()) item.setSelected(); + } + videoFormatOption.setEnabled(video->hasFormat()); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::videoFormatChange() -> void { + auto item = videoFormatOption.selected(); + settings["Video/Format"].setValue(item.text()); + video->setFormat(item.text()); +} + +// + +auto DriverSettings::audioDriverChanged() -> void { + audioDriverOption.reset(); + for(auto& driver : audio->availableDrivers()) { + ComboButtonItem item{&audioDriverOption}; + item.setText(driver); + if(driver == audio->driver()) item.setSelected(); + } + audioDriverActive.setText({"Active driver: ", audio->driver()}); + audioDriverOption.doChange(); + audioDeviceChanged(); + audioFrequencyChanged(); + audioLatencyChanged(); + audioExclusiveToggle.setChecked(audio->exclusive()).setEnabled(audio->hasExclusive()); + audioBlockingToggle.setChecked(audio->blocking()).setEnabled(audio->hasBlocking()); + audioDynamicToggle.setChecked(audio->dynamic()).setEnabled(audio->hasDynamic()); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::audioDriverChange() -> void { + auto item = audioDriverOption.selected(); + settings["Audio/Driver"].setValue(item.text()); + if(!emulator->loaded() || item.text() == "None" || MessageDialog( + "Warning: incompatible drivers may cause bsnes to crash.\n" + "It is highly recommended you unload your game first to be safe.\n" + "Do you wish to proceed with the audio driver change now anyway?" + ).setParent(*settingsWindow).question() == "Yes") { + program->save(); + program->saveUndoState(); + settings["Crashed"].setValue(true); + settings.save(); + program->updateAudioDriver(*settingsWindow); + settings["Crashed"].setValue(false); + settings.save(); + audioDriverChanged(); + } +} + +auto DriverSettings::audioDeviceChanged() -> void { + audioDeviceOption.reset(); + for(auto& device : audio->availableDevices()) { + ComboButtonItem item{&audioDeviceOption}; + item.setText(device); + if(device == audio->device()) item.setSelected(); + } + audioDeviceOption.setEnabled(audio->hasDevice()); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::audioDeviceChange() -> void { + auto item = audioDeviceOption.selected(); + settings["Audio/Device"].setValue(item.text()); + program->updateAudioDevice(); + audioFrequencyChanged(); + audioLatencyChanged(); +} + +auto DriverSettings::audioFrequencyChanged() -> void { + audioFrequencyOption.reset(); + for(auto& frequency : audio->availableFrequencies()) { + ComboButtonItem item{&audioFrequencyOption}; + item.setText({(uint)frequency, "hz"}); + if(frequency == audio->frequency()) item.setSelected(); + } + audioFrequencyOption.setEnabled(audio->hasFrequency()); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::audioFrequencyChange() -> void { + auto item = audioFrequencyOption.selected(); + settings["Audio/Frequency"].setValue(item.text()); + program->updateAudioFrequency(); +} + +auto DriverSettings::audioLatencyChanged() -> void { + audioLatencyOption.reset(); + for(auto& latency : audio->availableLatencies()) { + ComboButtonItem item{&audioLatencyOption}; + item.setText(latency); + if(latency == audio->latency()) item.setSelected(); + } + audioLatencyOption.setEnabled(audio->hasLatency()); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::audioLatencyChange() -> void { + auto item = audioLatencyOption.selected(); + settings["Audio/Latency"].setValue(item.text()); + program->updateAudioLatency(); +} + +// + +auto DriverSettings::inputDriverChanged() -> void { + inputDriverOption.reset(); + for(auto& driver : input->availableDrivers()) { + ComboButtonItem item{&inputDriverOption}; + item.setText(driver); + if(driver == input->driver()) item.setSelected(); + } + inputDriverActive.setText({"Active driver: ", input->driver()}); + inputDriverOption.doChange(); + layout.setGeometry(layout.geometry()); +} + +auto DriverSettings::inputDriverChange() -> void { + auto item = inputDriverOption.selected(); + settings["Input/Driver"].setValue(item.text()); + if(!emulator->loaded() || item.text() == "None" || MessageDialog( + "Warning: incompatible drivers may cause bsnes to crash.\n" + "It is highly recommended you unload your game first to be safe.\n" + "Do you wish to proceed with the input driver change now anyway?" + ).setParent(*settingsWindow).question() == "Yes") { + program->save(); + program->saveUndoState(); + settings["Crashed"].setValue(true); + settings.save(); + program->updateInputDriver(*settingsWindow); + settings["Crashed"].setValue(false); + settings.save(); + inputDriverChanged(); + } +} diff --git a/higan/target-bsnes/settings/hotkeys.cpp b/higan/target-bsnes/settings/hotkeys.cpp index 810eb7ae..08e49917 100644 --- a/higan/target-bsnes/settings/hotkeys.cpp +++ b/higan/target-bsnes/settings/hotkeys.cpp @@ -54,9 +54,18 @@ auto HotkeySettings::assignMapping() -> void { activeMapping = inputManager->hotkeys[item.offset()]; settingsWindow->layout.setEnabled(false); settingsWindow->statusBar.setText({"Press a key or button to map [", activeMapping->name, "] ..."}); + settingsWindow->setDismissable(false); } } +auto HotkeySettings::cancelMapping() -> void { + activeMapping.reset(); + settingsWindow->statusBar.setText(); + settingsWindow->layout.setEnabled(); + settingsWindow->doSize(); + settingsWindow->setDismissable(true); +} + auto HotkeySettings::inputEvent(shared_pointer device, uint group, uint input, int16 oldValue, int16 newValue) -> void { if(!activeMapping) return; if(device->isMouse()) return; @@ -67,9 +76,7 @@ auto HotkeySettings::inputEvent(shared_pointer device, uint group, refreshMappings(); timer.onActivate([&] { timer.setEnabled(false); - settingsWindow->statusBar.setText(); - settingsWindow->layout.setEnabled(); - settingsWindow->doSize(); + cancelMapping(); }).setInterval(200).setEnabled(); } } diff --git a/higan/target-bsnes/settings/input.cpp b/higan/target-bsnes/settings/input.cpp index caee9150..f6781596 100644 --- a/higan/target-bsnes/settings/input.cpp +++ b/higan/target-bsnes/settings/input.cpp @@ -3,23 +3,22 @@ InputSettings::InputSettings(TabFrame* parent) : TabFrameItem(parent) { setText("Input"); layout.setPadding(5); - defocusLabel.setText("When focus is lost:"); - pauseEmulation.setText("Pause emulation").onActivate([&] { - settings["Input/Defocus"].setValue("Pause"); - }); - blockInput.setText("Block input").onActivate([&] { - settings["Input/Defocus"].setValue("Block"); - }); - allowInput.setText("Allow input").onActivate([&] { - settings["Input/Defocus"].setValue("Allow"); - }); - if(settings["Input/Defocus"].text() == "Pause") pauseEmulation.setChecked(); - if(settings["Input/Defocus"].text() == "Block") blockInput.setChecked(); - if(settings["Input/Defocus"].text() == "Allow") allowInput.setChecked(); portLabel.setText("Port:"); portList.onChange([&] { reloadDevices(); }); deviceLabel.setText("Device:"); deviceList.onChange([&] { reloadMappings(); }); + turboLabel.setText("Turbo rate:"); + for(uint frequency : range(1, 9)) { + ComboButtonItem item{&turboList}; + item.setText(frequency); + if(frequency == settings["Input/Turbo/Frequency"].natural()) item.setSelected(); + } + turboList.onChange([&] { + uint frequency = turboList.selected().text().natural(); + settings["Input/Turbo/Frequency"].setValue(frequency); + inputManager->turboCounter = 0; + inputManager->turboFrequency = frequency; + }); mappingList.setBatchable(); mappingList.onActivate([&] { if(assignButton.enabled()) assignButton.doActivate(); }); mappingList.onChange([&] { updateControls(); }); @@ -120,9 +119,18 @@ auto InputSettings::assignMapping() -> void { activeMapping = activeDevice().mappings[mapping.offset()]; settingsWindow->layout.setEnabled(false); settingsWindow->statusBar.setText({"Press a key or button to map [", activeMapping->name, "] ..."}); + settingsWindow->setDismissable(false); } } +auto InputSettings::cancelMapping() -> void { + activeMapping.reset(); + settingsWindow->statusBar.setText(); + settingsWindow->layout.setEnabled(); + settingsWindow->doSize(); + settingsWindow->setDismissable(true); +} + auto InputSettings::assignMouseInput(uint id) -> void { if(auto mapping = mappingList.selected()) { activeMapping = activeDevice().mappings[mapping.offset()]; @@ -146,9 +154,7 @@ auto InputSettings::inputEvent(shared_pointer device, uint group, u refreshMappings(); timer.onActivate([&] { timer.setEnabled(false); - settingsWindow->statusBar.setText(); - settingsWindow->layout.setEnabled(); - settingsWindow->doSize(); + cancelMapping(); }).setInterval(200).setEnabled(); } } diff --git a/higan/target-bsnes/settings/settings.cpp b/higan/target-bsnes/settings/settings.cpp index bb26b5f7..95cb90aa 100644 --- a/higan/target-bsnes/settings/settings.cpp +++ b/higan/target-bsnes/settings/settings.cpp @@ -4,7 +4,8 @@ #include "input.cpp" #include "hotkeys.cpp" #include "paths.cpp" -#include "advanced.cpp" +#include "configuration.cpp" +#include "drivers.cpp" Settings settings; unique_pointer settingsWindow; @@ -19,6 +20,8 @@ Settings::Settings() { set("Video/Driver", Video::safestDriver()); set("Video/Exclusive", false); set("Video/Blocking", false); + set("Video/Flush", false); + set("Video/Format", "Default"); set("Video/Shader", "Blur"); set("Video/Luminance", "100%"); set("Video/Saturation", "100%"); @@ -26,9 +29,10 @@ Settings::Settings() { set("Audio/Driver", Audio::safestDriver()); set("Audio/Exclusive", false); - set("Audio/Blocking", true); set("Audio/Device", ""); - set("Audio/Frequency", 48000.0); + set("Audio/Blocking", true); + set("Audio/Dynamic", false); + set("Audio/Frequency", "48000hz"); set("Audio/Latency", 0); set("Audio/Mute", false); set("Audio/Skew", "0"); @@ -38,6 +42,7 @@ Settings::Settings() { set("Input/Driver", Input::safestDriver()); set("Input/Frequency", 5); set("Input/Defocus", "Pause"); + set("Input/Turbo/Frequency", 4); set("View/Multiplier", "2"); set("View/Output", "Scale"); @@ -58,6 +63,7 @@ Settings::Settings() { set("Path/Recent/SufamiTurboB", Path::user()); set("UserInterface/ShowStatusBar", true); + set("UserInterface/SuppressScreenSaver", true); set("Emulator/WarnOnUnverifiedGames", false); set("Emulator/AutoSaveMemory/Enable", true); @@ -93,6 +99,12 @@ SettingsWindow::SettingsWindow() { input.mappingList.resizeColumns(); hotkeys.mappingList.resizeColumns(); }); + + onClose([&] { + if(input.activeMapping) input.cancelMapping(); + if(hotkeys.activeMapping) hotkeys.cancelMapping(); + setVisible(false); + }); } auto SettingsWindow::setVisible(bool visible) -> SettingsWindow& { diff --git a/higan/target-bsnes/settings/settings.hpp b/higan/target-bsnes/settings/settings.hpp index d368cc11..c93b29fc 100644 --- a/higan/target-bsnes/settings/settings.hpp +++ b/higan/target-bsnes/settings/settings.hpp @@ -21,27 +21,13 @@ public: Label gammaLabel{&colorLayout, Size{0, 0}}; Label gammaValue{&colorLayout, Size{50, 0}}; HorizontalSlider gammaSlider{&colorLayout, Size{~0, 0}}; - Label fullscreenLabel{&layout, Size{~0, 0}, 2}; - CheckLabel exclusiveMode{&layout, Size{~0, 0}}; }; struct AudioSettings : TabFrameItem { AudioSettings(TabFrame*); - auto updateDevice() -> void; - auto updateFrequency() -> void; - auto updateLatency() -> void; public: VerticalLayout layout{this}; - Label driverLabel{&layout, Size{~0, 0}, 2}; - HorizontalLayout driverLayout{&layout, Size{~0, 0}}; - Label deviceLabel{&driverLayout, Size{0, 0}}; - ComboButton deviceList{&driverLayout, Size{~0, 0}}; - Label frequencyLabel{&driverLayout, Size{0, 0}}; - ComboButton frequencyList{&driverLayout, Size{80, 0}}; - Label latencyLabel{&driverLayout, Size{0, 0}}; - ComboButton latencyList{&driverLayout, Size{80, 0}}; - CheckLabel exclusiveMode{&layout, Size{~0, 0}}; Label effectsLabel{&layout, Size{~0, 0}, 2}; TableLayout effectsLayout{&layout, Size{~0, 0}}; Label skewLabel{&effectsLayout, Size{0, 0}}; @@ -67,6 +53,7 @@ struct InputSettings : TabFrameItem { auto reloadMappings() -> void; auto refreshMappings() -> void; auto assignMapping() -> void; + auto cancelMapping() -> void; auto assignMouseInput(uint id) -> void; auto inputEvent(shared_pointer device, uint group, uint input, int16 oldValue, int16 newValue, bool allowMouseInput = false) -> void; @@ -75,17 +62,13 @@ public: Timer timer; VerticalLayout layout{this}; - HorizontalLayout defocusLayout{&layout, Size{~0, 0}}; - Label defocusLabel{&defocusLayout, Size{0, 0}}; - RadioLabel pauseEmulation{&defocusLayout, Size{0, 0}}; - RadioLabel blockInput{&defocusLayout, Size{0, 0}}; - RadioLabel allowInput{&defocusLayout, Size{0, 0}}; - Group defocusGroup{&pauseEmulation, &blockInput, &allowInput}; HorizontalLayout selectionLayout{&layout, Size{~0, 0}}; Label portLabel{&selectionLayout, Size{0, 0}}; ComboButton portList{&selectionLayout, Size{~0, 0}}; Label deviceLabel{&selectionLayout, Size{0, 0}}; ComboButton deviceList{&selectionLayout, Size{~0, 0}}; + Label turboLabel{&selectionLayout, Size{0, 0}}; + ComboButton turboList{&selectionLayout, Size{0, 0}}; TableView mappingList{&layout, Size{~0, ~0}}; HorizontalLayout controlLayout{&layout, Size{~0, 0}}; Button assignMouse1{&controlLayout, Size{100, 0}}; @@ -101,6 +84,7 @@ struct HotkeySettings : TabFrameItem { auto reloadMappings() -> void; auto refreshMappings() -> void; auto assignMapping() -> void; + auto cancelMapping() -> void; auto inputEvent(shared_pointer device, uint group, uint input, int16 oldValue, int16 newValue) -> void; public: @@ -152,29 +136,25 @@ public: Button screenshotsReset{&layout, Size{80, 0}}; }; -struct AdvancedSettings : TabFrameItem { - AdvancedSettings(TabFrame*); - auto updateVideoDriver() -> void; - auto updateAudioDriver() -> void; - auto updateInputDriver() -> void; +struct ConfigurationSettings : TabFrameItem { + ConfigurationSettings(TabFrame*); auto updateConfiguration() -> void; public: VerticalLayout layout{this}; - Label driversLabel{&layout, Size{~0, 0}, 2}; - HorizontalLayout driverLayout{&layout, Size{~0, 0}}; - Label videoDriverLabel{&driverLayout, Size{0, 0}}; - ComboButton videoDriverOption{&driverLayout, Size{~0, 0}}; - Label audioDriverLabel{&driverLayout, Size{0, 0}}; - ComboButton audioDriverOption{&driverLayout, Size{~0, 0}}; - Label inputDriverLabel{&driverLayout, Size{0, 0}}; - ComboButton inputDriverOption{&driverLayout, Size{~0, 0}}; Label optionsLabel{&layout, Size{~0, 0}, 2}; + HorizontalLayout inputFocusLayout{&layout, Size{~0, 0}}; + Label inputFocusLabel{&inputFocusLayout, Size{0, 0}}; + RadioLabel pauseEmulation{&inputFocusLayout, Size{0, 0}}; + RadioLabel blockInput{&inputFocusLayout, Size{0, 0}}; + RadioLabel allowInput{&inputFocusLayout, Size{0, 0}}; + Group inputFocusGroup{&pauseEmulation, &blockInput, &allowInput}; CheckLabel warnOnUnverifiedGames{&layout, Size{~0, 0}}; CheckLabel autoSaveMemory{&layout, Size{~0, 0}}; HorizontalLayout autoStateLayout{&layout, Size{~0, 0}}; CheckLabel autoSaveStateOnUnload{&autoStateLayout, Size{0, 0}}; CheckLabel autoLoadStateOnLoad{&autoStateLayout, Size{0, 0}}; + CheckLabel suppressScreenSaver{&layout, Size{~0, 0}}; Label hacksLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout fastPPULayout{&layout, Size{~0, 0}}; CheckLabel fastPPUOption{&fastPPULayout, Size{0, 0}}; @@ -188,6 +168,66 @@ public: Label hacksNote{&layout, Size{~0, 0}}; }; +struct DriverSettings : TabFrameItem { + DriverSettings(TabFrame*); + auto videoDriverChanged() -> void; + auto videoDriverChange() -> void; + auto videoFormatChanged() -> void; + auto videoFormatChange() -> void; + auto audioDriverChanged() -> void; + auto audioDriverChange() -> void; + auto audioDeviceChanged() -> void; + auto audioDeviceChange() -> void; + auto audioFrequencyChanged() -> void; + auto audioFrequencyChange() -> void; + auto audioLatencyChanged() -> void; + auto audioLatencyChange() -> void; + auto inputDriverChanged() -> void; + auto inputDriverChange() -> void; + +public: + VerticalLayout layout{this}; + Label videoLabel{&layout, Size{~0, 0}, 2}; + TableLayout videoLayout{&layout, Size{~0, 0}}; + Label videoDriverLabel{&videoLayout, Size{0, 0}}; + HorizontalLayout videoDriverLayout{&videoLayout, Size{~0, 0}}; + ComboButton videoDriverOption{&videoDriverLayout, Size{0, 0}}; + Button videoDriverUpdate{&videoDriverLayout, Size{0, 0}}; + Label videoDriverActive{&videoDriverLayout, Size{0, 0}}; + Label videoFormatLabel{&videoLayout, Size{0, 0}}; + HorizontalLayout videoPropertyLayout{&videoLayout, Size{~0, 0}}; + ComboButton videoFormatOption{&videoPropertyLayout, Size{0, 0}}; + HorizontalLayout videoToggleLayout{&layout, Size{~0, 0}}; + CheckLabel videoExclusiveToggle{&videoToggleLayout, Size{0, 0}}; + CheckLabel videoBlockingToggle{&videoToggleLayout, Size{0, 0}}; + CheckLabel videoFlushToggle{&videoToggleLayout, Size{0, 0}}; + Label audioLabel{&layout, Size{~0, 0}, 2}; + TableLayout audioLayout{&layout, Size{~0, 0}}; + Label audioDriverLabel{&audioLayout, Size{0, 0}}; + HorizontalLayout audioDriverLayout{&audioLayout, Size{~0, 0}}; + ComboButton audioDriverOption{&audioDriverLayout, Size{0, 0}}; + Button audioDriverUpdate{&audioDriverLayout, Size{0, 0}}; + Label audioDriverActive{&audioDriverLayout, Size{0, 0}}; + Label audioDeviceLabel{&audioLayout, Size{0, 0}}; + HorizontalLayout audioPropertyLayout{&audioLayout, Size{~0, 0}}; + ComboButton audioDeviceOption{&audioPropertyLayout, Size{0, 0}}; + Label audioFrequencyLabel{&audioPropertyLayout, Size{0, 0}}; + ComboButton audioFrequencyOption{&audioPropertyLayout, Size{0, 0}}; + Label audioLatencyLabel{&audioPropertyLayout, Size{0, 0}}; + ComboButton audioLatencyOption{&audioPropertyLayout, Size{0, 0}}; + HorizontalLayout audioToggleLayout{&layout, Size{~0, 0}}; + CheckLabel audioExclusiveToggle{&audioToggleLayout, Size{0, 0}}; + CheckLabel audioBlockingToggle{&audioToggleLayout, Size{0, 0}}; + CheckLabel audioDynamicToggle{&audioToggleLayout, Size{0, 0}}; + Label inputLabel{&layout, Size{~0, 0}, 2}; + TableLayout inputLayout{&layout, Size{~0, 0}}; + Label inputDriverLabel{&inputLayout, Size{0, 0}}; + HorizontalLayout inputDriverLayout{&inputLayout, Size{~0, 0}}; + ComboButton inputDriverOption{&inputDriverLayout, Size{0, 0}}; + Button inputDriverUpdate{&inputDriverLayout, Size{0, 0}}; + Label inputDriverActive{&inputDriverLayout, Size{0, 0}}; +}; + struct SettingsWindow : Window { SettingsWindow(); auto setVisible(bool visible = true) -> SettingsWindow&; @@ -201,7 +241,8 @@ public: InputSettings input{&panel}; HotkeySettings hotkeys{&panel}; PathSettings paths{&panel}; - AdvancedSettings advanced{&panel}; + ConfigurationSettings configuration{&panel}; + DriverSettings drivers{&panel}; StatusBar statusBar{this}; }; diff --git a/higan/target-bsnes/settings/video.cpp b/higan/target-bsnes/settings/video.cpp index d5b93953..b8620ae4 100644 --- a/higan/target-bsnes/settings/video.cpp +++ b/higan/target-bsnes/settings/video.cpp @@ -31,9 +31,4 @@ VideoSettings::VideoSettings(TabFrame* parent) : TabFrameItem(parent) { gammaValue.setText(value); program->updateVideoPalette(); }).doChange(); - - fullscreenLabel.setFont(Font().setBold()).setText("Fullscreen"); - exclusiveMode.setText("Exclusive mode").setChecked(settings["Video/Exclusive"].boolean()).onToggle([&] { - settings["Video/Exclusive"].setValue(exclusiveMode.checked()); - }); } diff --git a/higan/target-bsnes/tools/state-manager.cpp b/higan/target-bsnes/tools/state-manager.cpp index 55b12573..33c3b7af 100644 --- a/higan/target-bsnes/tools/state-manager.cpp +++ b/higan/target-bsnes/tools/state-manager.cpp @@ -81,12 +81,15 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) { }); loadButton.setText("Load").onActivate([&] { if(auto item = stateList.selected()) { - program->loadState({"managed/", item.cell(0).text()}); + string filename = {"managed/", item.cell(0).text()}; + program->loadState(filename); } }); saveButton.setText("Save").onActivate([&] { if(auto item = stateList.selected()) { - program->saveState({"managed/", item.cell(0).text()}); + string filename = {"managed/", item.cell(0).text()}; + program->saveState(filename); + item.cell(1).setText(chrono::local::datetime(program->stateTimestamp(filename))); } }); addButton.setText("Add").onActivate([&] { @@ -104,12 +107,14 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) { auto StateManager::loadStates() -> void { stateList.reset(); - stateList.append(TableViewHeader().setVisible(false) - .append(TableViewColumn().setExpandable()) + stateList.append(TableViewHeader() + .append(TableViewColumn().setText("Name").setExpandable()) + .append(TableViewColumn().setText("Date").setForegroundColor({160, 160, 160})) ); - for(auto filename : program->managedStates()) { + for(auto& filename : program->availableStates("managed/")) { stateList.append(TableViewItem() - .append(TableViewCell().setText(filename.trimRight(".bst", 1L))) + .append(TableViewCell().setText(string{filename}.trimLeft("managed/", 1L))) + .append(TableViewCell().setText(chrono::local::datetime(program->stateTimestamp(filename)))) ); } stateList.resizeColumns().doChange(); @@ -118,7 +123,7 @@ auto StateManager::loadStates() -> void { auto StateManager::createState(string name) -> void { program->saveState({"managed/", name}); loadStates(); - for(auto item : stateList.items()) { + for(auto& item : stateList.items()) { if(item.cell(0).text() == name) item.setSelected(); } stateList.doChange(); @@ -131,7 +136,7 @@ auto StateManager::modifyState(string name) -> void { if(from != to) { program->renameState(from, to); loadStates(); - for(auto item : stateList.items()) { + for(auto& item : stateList.items()) { if(item.cell(0).text() == name) item.setSelected(); } stateList.doChange(); @@ -143,7 +148,7 @@ auto StateManager::removeStates() -> void { if(auto batched = stateList.batched()) { if(MessageDialog("Are you sure you want to permanently remove the selected state(s)?") .setParent(*toolsWindow).question() == "Yes") { - for(auto item : batched) { + for(auto& item : batched) { program->removeState({"managed/", item.cell(0).text()}); } loadStates(); diff --git a/hiro/GNUmakefile b/hiro/GNUmakefile index d5ebfff8..463988da 100644 --- a/hiro/GNUmakefile +++ b/hiro/GNUmakefile @@ -1,8 +1,3 @@ -ifeq ($(platform),) - hiro.flags = $(flags.cpp) -DHIRO_REFERENCE - hiro.options = -endif - ifeq ($(platform),windows) ifeq ($(hiro),) hiro := windows diff --git a/hiro/cocoa/utility.cpp b/hiro/cocoa/utility.cpp index 17d145f8..1570176c 100644 --- a/hiro/cocoa/utility.cpp +++ b/hiro/cocoa/utility.cpp @@ -33,8 +33,8 @@ auto DropPathsOperation(id sender) -> NSDragOperation { return NSDragOperationNone; } -auto DropPaths(id sender) -> string_vector { - string_vector paths; +auto DropPaths(id sender) -> vector { + vector paths; NSPasteboard* pboard = [sender draggingPasteboard]; if([[pboard types] containsObject:NSFilenamesPboardType]) { NSArray* files = [pboard propertyListForType:NSFilenamesPboardType]; diff --git a/hiro/cocoa/window.cpp b/hiro/cocoa/window.cpp index 262fb6e9..8482cf00 100644 --- a/hiro/cocoa/window.cpp +++ b/hiro/cocoa/window.cpp @@ -241,6 +241,11 @@ auto pWindow::frameMargin() const -> Geometry { } } +auto pWindow::monitor() const -> uint { + //TODO + return 0; +} + auto pWindow::remove(sMenuBar menuBar) -> void { } diff --git a/hiro/cocoa/window.hpp b/hiro/cocoa/window.hpp index 1650064a..f5e19b8e 100644 --- a/hiro/cocoa/window.hpp +++ b/hiro/cocoa/window.hpp @@ -35,6 +35,7 @@ struct pWindow : pObject { auto append(sStatusBar statusBar) -> void; auto focused() const -> bool override; auto frameMargin() const -> Geometry; + auto monitor() const -> uint; auto remove(sMenuBar menuBar) -> void; auto remove(sSizable sizable) -> void; auto remove(sStatusBar statusBar) -> void; diff --git a/hiro/core/core.cpp b/hiro/core/core.cpp index e64f58c1..d41883ed 100644 --- a/hiro/core/core.cpp +++ b/hiro/core/core.cpp @@ -8,8 +8,6 @@ #include "../gtk/header.hpp" #elif defined(HIRO_COCOA) #include "../cocoa/header.hpp" -#elif defined(HIRO_REFERENCE) - #include "../reference/header.hpp" #endif #include "core.hpp" @@ -23,8 +21,6 @@ using namespace nall; #include "../gtk/platform.cpp" #elif defined(HIRO_COCOA) #include "../cocoa/platform.cpp" -#elif defined(HIRO_REFERENCE) - #include "../reference/platform.cpp" #endif #define signal(function, ...) \ diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index 3921f5f1..888ec254 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -371,18 +371,7 @@ struct Hotkey { #include "application.hpp" #include "desktop.hpp" - -#if defined(Hiro_Monitor) -struct Monitor { - Monitor() = delete; - - static auto count() -> uint; - static auto dpi(maybe monitor = nothing) -> Position; - static auto geometry(maybe monitor = nothing) -> Geometry; - static auto primary() -> uint; - static auto workspace(maybe monitor = nothing) -> Geometry; -}; -#endif +#include "monitor.hpp" #if defined(Hiro_Keyboard) struct Keyboard { @@ -504,71 +493,7 @@ private: } \ virtual auto allocate() -> pObject*; \ -#if defined(Hiro_Object) -struct mObject { - Declare(Object) - - mObject(); - virtual ~mObject(); - mObject(const mObject&) = delete; - mObject& operator=(const mObject&) = delete; - - explicit operator bool() const; - - auto abstract() const -> bool; - auto adjustOffset(int displacement) -> type&; - auto enabled(bool recursive = false) const -> bool; - virtual auto focused() const -> bool; - auto font(bool recursive = false) const -> Font; - virtual auto group() const -> Group; - auto offset() const -> int; - auto parent() const -> mObject*; - auto parentComboButton(bool recursive = false) const -> mComboButton*; - auto parentComboEdit(bool recursive = false) const -> mComboEdit*; - auto parentFrame(bool recursive = false) const -> mFrame*; - auto parentIconView(bool recursive = false) const -> mIconView*; - auto parentMenu(bool recursive = false) const -> mMenu*; - auto parentMenuBar(bool recursive = false) const -> mMenuBar*; - auto parentPopupMenu(bool recursive = false) const -> mPopupMenu*; - auto parentSizable(bool recursive = false) const -> mSizable*; - auto parentTabFrame(bool recursive = false) const -> mTabFrame*; - auto parentTabFrameItem(bool recursive = false) const -> mTabFrameItem*; - auto parentTableView(bool recursive = false) const -> mTableView*; - auto parentTableViewHeader(bool recursive = false) const -> mTableViewHeader*; - auto parentTableViewItem(bool recursive = false) const -> mTableViewItem*; - auto parentTreeView(bool recursive = false) const -> mTreeView*; - auto parentTreeViewItem(bool recursive = false) const -> mTreeViewItem*; - auto parentWidget(bool recursive = false) const -> mWidget*; - auto parentWindow(bool recursive = false) const -> mWindow*; - auto property(const string& name) const -> string; - virtual auto remove() -> type&; - virtual auto reset() -> type&; - virtual auto setEnabled(bool enabled = true) -> type&; - virtual auto setFocused() -> type&; - virtual auto setFont(const Font& font = {}) -> type&; - virtual auto setGroup(sGroup group = {}) -> type&; - virtual auto setParent(mObject* parent = nullptr, int offset = -1) -> type&; - virtual auto setProperty(const string& name, const string& value = "") -> type&; - virtual auto setVisible(bool visible = true) -> type&; - auto visible(bool recursive = false) const -> bool; - -//private: - struct State { - bool enabled = true; - Font font; - int offset = -1; - mObject* parent = nullptr; - set properties; - bool visible = true; - } state; - - wObject instance; - pObject* delegate = nullptr; - - virtual auto construct() -> void; - virtual auto destruct() -> void; -}; -#endif +#include "object.hpp" #if defined(Hiro_Group) struct mGroup : mObject { @@ -605,97 +530,7 @@ struct mTimer : mObject { }; #endif -#if defined(Hiro_Window) -struct mWindow : mObject { - Declare(Window) - using mObject::remove; - - mWindow(); - - auto append(sMenuBar menuBar) -> type&; - auto append(sSizable sizable) -> type&; - auto append(sStatusBar statusBar) -> type&; - auto backgroundColor() const -> Color; - auto dismissable() const -> bool; - auto doClose() const -> void; - auto doDrop(vector) const -> void; - auto doKeyPress(int) const -> void; - auto doKeyRelease(int) const -> void; - auto doMove() const -> void; - auto doSize() const -> void; - auto droppable() const -> bool; - auto frameGeometry() const -> Geometry; - auto fullScreen() const -> bool; - auto geometry() const -> Geometry; - auto maximized() const -> bool; - auto maximumSize() const -> Size; - auto menuBar() const -> MenuBar; - auto minimized() const -> bool; - auto minimumSize() const -> Size; - auto modal() const -> bool; - auto onClose(const function& callback = {}) -> type&; - auto onDrop(const function)>& callback = {}) -> type&; - auto onKeyPress(const function& callback = {}) -> type&; - auto onKeyRelease(const function& callback = {}) -> type&; - auto onMove(const function& callback = {}) -> type&; - auto onSize(const function& callback = {}) -> type&; - auto remove(sMenuBar menuBar) -> type&; - auto remove(sSizable sizable) -> type&; - auto remove(sStatusBar statusBar) -> type&; - auto reset() -> type& override; - auto resizable() const -> bool; - auto setAlignment(Alignment alignment) -> type&; - auto setBackgroundColor(Color color = {}) -> type&; - auto setCentered(sWindow parent = {}) -> type&; - auto setDismissable(bool dismissable = true) -> type&; - auto setDroppable(bool droppable = true) -> type&; - auto setFrameGeometry(Geometry geometry) -> type&; - auto setFramePosition(Position position) -> type&; - auto setFrameSize(Size size) -> type&; - auto setFullScreen(bool fullScreen = true) -> type&; - auto setGeometry(Geometry geometry) -> type&; - auto setMaximized(bool maximized = true) -> type&; - auto setMaximumSize(Size size = {}) -> type&; - auto setMinimized(bool minimized = true) -> type&; - auto setMinimumSize(Size size = {}) -> type&; - auto setModal(bool modal = true) -> type&; - auto setPosition(Position position) -> type&; - auto setResizable(bool resizable = true) -> type&; - auto setSize(Size size) -> type&; - auto setTitle(const string& title = "") -> type&; - auto setVisible(bool visible = true) -> type&; - auto sizable() const -> Sizable; - auto statusBar() const -> StatusBar; - auto title() const -> string; - -//private: - struct State { - Color backgroundColor; - bool dismissable = false; - bool droppable = false; - bool fullScreen = false; - Geometry geometry = {128, 128, 256, 256}; - bool maximized = false; - Size maximumSize; - bool minimized = false; - Size minimumSize; - sMenuBar menuBar; - bool modal = false; - function onClose; - function)> onDrop; - function onKeyPress; - function onKeyRelease; - function onMove; - function onSize; - bool resizable = true; - sSizable sizable; - sStatusBar statusBar; - string title; - } state; - - auto destruct() -> void; -}; -#endif +#include "window.hpp" #if defined(Hiro_StatusBar) struct mStatusBar : mObject { diff --git a/hiro/core/monitor.hpp b/hiro/core/monitor.hpp new file mode 100644 index 00000000..213c87e7 --- /dev/null +++ b/hiro/core/monitor.hpp @@ -0,0 +1,11 @@ +#if defined(Hiro_Monitor) +struct Monitor { + Monitor() = delete; + + static auto count() -> uint; + static auto dpi(maybe monitor = nothing) -> Position; + static auto geometry(maybe monitor = nothing) -> Geometry; + static auto primary() -> uint; + static auto workspace(maybe monitor = nothing) -> Geometry; +}; +#endif diff --git a/hiro/core/object.cpp b/hiro/core/object.cpp index ab919c95..505418d6 100644 --- a/hiro/core/object.cpp +++ b/hiro/core/object.cpp @@ -68,8 +68,7 @@ auto mObject::enabled(bool recursive) const -> bool { } auto mObject::focused() const -> bool { - if(signal(focused)) return true; - return false; + return signal(focused); } auto mObject::font(bool recursive) const -> Font { diff --git a/hiro/core/object.hpp b/hiro/core/object.hpp new file mode 100644 index 00000000..9a3f4b64 --- /dev/null +++ b/hiro/core/object.hpp @@ -0,0 +1,65 @@ +#if defined(Hiro_Object) +struct mObject { + Declare(Object) + + mObject(); + virtual ~mObject(); + mObject(const mObject&) = delete; + mObject& operator=(const mObject&) = delete; + + explicit operator bool() const; + + auto abstract() const -> bool; + auto adjustOffset(int displacement) -> type&; + auto enabled(bool recursive = false) const -> bool; + virtual auto focused() const -> bool; + auto font(bool recursive = false) const -> Font; + virtual auto group() const -> Group; + auto offset() const -> int; + auto parent() const -> mObject*; + auto parentComboButton(bool recursive = false) const -> mComboButton*; + auto parentComboEdit(bool recursive = false) const -> mComboEdit*; + auto parentFrame(bool recursive = false) const -> mFrame*; + auto parentIconView(bool recursive = false) const -> mIconView*; + auto parentMenu(bool recursive = false) const -> mMenu*; + auto parentMenuBar(bool recursive = false) const -> mMenuBar*; + auto parentPopupMenu(bool recursive = false) const -> mPopupMenu*; + auto parentSizable(bool recursive = false) const -> mSizable*; + auto parentTabFrame(bool recursive = false) const -> mTabFrame*; + auto parentTabFrameItem(bool recursive = false) const -> mTabFrameItem*; + auto parentTableView(bool recursive = false) const -> mTableView*; + auto parentTableViewHeader(bool recursive = false) const -> mTableViewHeader*; + auto parentTableViewItem(bool recursive = false) const -> mTableViewItem*; + auto parentTreeView(bool recursive = false) const -> mTreeView*; + auto parentTreeViewItem(bool recursive = false) const -> mTreeViewItem*; + auto parentWidget(bool recursive = false) const -> mWidget*; + auto parentWindow(bool recursive = false) const -> mWindow*; + auto property(const string& name) const -> string; + virtual auto remove() -> type&; + virtual auto reset() -> type&; + virtual auto setEnabled(bool enabled = true) -> type&; + virtual auto setFocused() -> type&; + virtual auto setFont(const Font& font = {}) -> type&; + virtual auto setGroup(sGroup group = {}) -> type&; + virtual auto setParent(mObject* parent = nullptr, int offset = -1) -> type&; + virtual auto setProperty(const string& name, const string& value = "") -> type&; + virtual auto setVisible(bool visible = true) -> type&; + auto visible(bool recursive = false) const -> bool; + +//private: + struct State { + bool enabled = true; + Font font; + int offset = -1; + mObject* parent = nullptr; + set properties; + bool visible = true; + } state; + + wObject instance; + pObject* delegate = nullptr; + + virtual auto construct() -> void; + virtual auto destruct() -> void; +}; +#endif diff --git a/hiro/core/shared.hpp b/hiro/core/shared.hpp index 1940b2f0..d918ba25 100644 --- a/hiro/core/shared.hpp +++ b/hiro/core/shared.hpp @@ -944,6 +944,7 @@ struct Window : sWindow { auto minimized() const { return self().minimized(); } auto minimumSize() const { return self().minimumSize(); } auto modal() const { return self().modal(); } + auto monitor() const { return self().monitor(); } auto onClose(const function& callback = {}) { return self().onClose(callback), *this; } auto onDrop(const function)>& callback = {}) { return self().onDrop(callback), *this; } auto onKeyPress(const function& callback = {}) { return self().onKeyPress(callback), *this; } diff --git a/hiro/core/window.cpp b/hiro/core/window.cpp index 745f7c93..bd8b6882 100644 --- a/hiro/core/window.cpp +++ b/hiro/core/window.cpp @@ -117,6 +117,10 @@ auto mWindow::modal() const -> bool { return state.modal; } +auto mWindow::monitor() const -> uint { + return signal(monitor); +} + auto mWindow::onClose(const function& callback) -> type& { state.onClose = callback; return *this; @@ -183,8 +187,8 @@ auto mWindow::setAlignment(Alignment alignment) -> type& { if(!alignment) alignment = {0.0, 0.0}; auto workspace = Desktop::workspace(); auto geometry = frameGeometry(); - signed left = alignment.horizontal() * (workspace.width() - geometry.width()); - signed top = alignment.vertical() * (workspace.height() - geometry.height()); + int left = alignment.horizontal() * (workspace.width() - geometry.width()); + int top = alignment.vertical() * (workspace.height() - geometry.height()); setFramePosition({left, top}); return *this; } @@ -196,12 +200,17 @@ auto mWindow::setBackgroundColor(Color color) -> type& { } auto mWindow::setCentered(sWindow parent) -> type& { - Geometry workspace = parent ? parent->frameGeometry() : Desktop::workspace(); + Geometry workspace = Desktop::workspace(); + Geometry parentGeometry = parent ? parent->frameGeometry() : workspace; Geometry geometry = frameGeometry(); - signed x = workspace.x(); - signed y = workspace.y(); - if(workspace.width() > geometry.width()) x += (workspace.width() - geometry.width()) / 2; - if(workspace.height() > geometry.height()) y += (workspace.height() - geometry.height()) / 2; + //center the window to its parent window ... + int x = parentGeometry.x() + (parentGeometry.width() - geometry.width()) / 2; + int y = parentGeometry.y() + (parentGeometry.height() - geometry.height()) / 2; + //try and keep the window onscreen ... + if(x + geometry.width() > workspace.width()) x = workspace.width() - geometry.width(); + if(y + geometry.height() > workspace.height()) y = workspace.height() - geometry.height(); + if(x < workspace.x()) x = workspace.x(); + if(y < workspace.y()) y = workspace.y(); return setFrameGeometry({x, y, geometry.width(), geometry.height()}); } diff --git a/hiro/core/window.hpp b/hiro/core/window.hpp new file mode 100644 index 00000000..9133c76e --- /dev/null +++ b/hiro/core/window.hpp @@ -0,0 +1,92 @@ +#if defined(Hiro_Window) +struct mWindow : mObject { + Declare(Window) + using mObject::remove; + + mWindow(); + + auto append(sMenuBar menuBar) -> type&; + auto append(sSizable sizable) -> type&; + auto append(sStatusBar statusBar) -> type&; + auto backgroundColor() const -> Color; + auto dismissable() const -> bool; + auto doClose() const -> void; + auto doDrop(vector) const -> void; + auto doKeyPress(int) const -> void; + auto doKeyRelease(int) const -> void; + auto doMove() const -> void; + auto doSize() const -> void; + auto droppable() const -> bool; + auto frameGeometry() const -> Geometry; + auto fullScreen() const -> bool; + auto geometry() const -> Geometry; + auto maximized() const -> bool; + auto maximumSize() const -> Size; + auto menuBar() const -> MenuBar; + auto minimized() const -> bool; + auto minimumSize() const -> Size; + auto modal() const -> bool; + auto monitor() const -> uint; + auto onClose(const function& callback = {}) -> type&; + auto onDrop(const function)>& callback = {}) -> type&; + auto onKeyPress(const function& callback = {}) -> type&; + auto onKeyRelease(const function& callback = {}) -> type&; + auto onMove(const function& callback = {}) -> type&; + auto onSize(const function& callback = {}) -> type&; + auto remove(sMenuBar menuBar) -> type&; + auto remove(sSizable sizable) -> type&; + auto remove(sStatusBar statusBar) -> type&; + auto reset() -> type& override; + auto resizable() const -> bool; + auto setAlignment(Alignment alignment) -> type&; + auto setBackgroundColor(Color color = {}) -> type&; + auto setCentered(sWindow parent = {}) -> type&; + auto setDismissable(bool dismissable = true) -> type&; + auto setDroppable(bool droppable = true) -> type&; + auto setFrameGeometry(Geometry geometry) -> type&; + auto setFramePosition(Position position) -> type&; + auto setFrameSize(Size size) -> type&; + auto setFullScreen(bool fullScreen = true) -> type&; + auto setGeometry(Geometry geometry) -> type&; + auto setMaximized(bool maximized = true) -> type&; + auto setMaximumSize(Size size = {}) -> type&; + auto setMinimized(bool minimized = true) -> type&; + auto setMinimumSize(Size size = {}) -> type&; + auto setModal(bool modal = true) -> type&; + auto setPosition(Position position) -> type&; + auto setResizable(bool resizable = true) -> type&; + auto setSize(Size size) -> type&; + auto setTitle(const string& title = "") -> type&; + auto setVisible(bool visible = true) -> type&; + auto sizable() const -> Sizable; + auto statusBar() const -> StatusBar; + auto title() const -> string; + +//private: + struct State { + Color backgroundColor; + bool dismissable = false; + bool droppable = false; + bool fullScreen = false; + Geometry geometry = {128, 128, 256, 256}; + bool maximized = false; + Size maximumSize; + bool minimized = false; + Size minimumSize; + sMenuBar menuBar; + bool modal = false; + function onClose; + function)> onDrop; + function onKeyPress; + function onKeyRelease; + function onMove; + function onSize; + bool resizable = true; + sSizable sizable; + sStatusBar statusBar; + string title; + } state; + + auto destruct() -> void; +}; +#endif diff --git a/hiro/extension/fixed-layout.cpp b/hiro/extension/fixed-layout.cpp index b7666054..ef061536 100644 --- a/hiro/extension/fixed-layout.cpp +++ b/hiro/extension/fixed-layout.cpp @@ -38,6 +38,13 @@ auto mFixedLayout::minimumSize() const -> Size { return {width, height}; } +auto mFixedLayout::remove(sSizable sizable) -> type& { + for(auto& cell : state.cells) { + if(cell->state.sizable == sizable) return remove(cell); + } + return *this; +} + auto mFixedLayout::remove(sFixedLayoutCell cell) -> type& { if(cell->parent() != this) return *this; auto offset = cell->offset(); diff --git a/hiro/extension/fixed-layout.hpp b/hiro/extension/fixed-layout.hpp index 45649ebf..46f07687 100644 --- a/hiro/extension/fixed-layout.hpp +++ b/hiro/extension/fixed-layout.hpp @@ -18,6 +18,7 @@ struct mFixedLayout : mSizable { auto cell(sSizable sizable) const -> FixedLayoutCell; auto cellCount() const -> uint; auto minimumSize() const -> Size override; + auto remove(sSizable sizable) -> type&; auto remove(sFixedLayoutCell cell) -> type&; auto reset() -> type& override; auto setEnabled(bool enabled) -> type& override; diff --git a/hiro/extension/horizontal-layout.cpp b/hiro/extension/horizontal-layout.cpp index b88ebf9e..a30ff306 100644 --- a/hiro/extension/horizontal-layout.cpp +++ b/hiro/extension/horizontal-layout.cpp @@ -66,6 +66,13 @@ auto mHorizontalLayout::padding() const -> Geometry { return state.padding; } +auto mHorizontalLayout::remove(sSizable sizable) -> type& { + for(auto& cell : state.cells) { + if(cell->state.sizable == sizable) return remove(cell); + } + return *this; +} + auto mHorizontalLayout::remove(sHorizontalLayoutCell cell) -> type& { if(cell->parent() != this) return *this; auto offset = cell->offset(); diff --git a/hiro/extension/horizontal-layout.hpp b/hiro/extension/horizontal-layout.hpp index 196fbf2b..eaf08b47 100644 --- a/hiro/extension/horizontal-layout.hpp +++ b/hiro/extension/horizontal-layout.hpp @@ -20,6 +20,7 @@ struct mHorizontalLayout : mSizable { auto cellCount() const -> uint; auto minimumSize() const -> Size override; auto padding() const -> Geometry; + auto remove(sSizable sizable) -> type&; auto remove(sHorizontalLayoutCell cell) -> type&; auto reset() -> type& override; auto setAlignment(maybe alignment) -> type&; diff --git a/hiro/extension/shared.hpp b/hiro/extension/shared.hpp index 5ec33961..eb6412e4 100644 --- a/hiro/extension/shared.hpp +++ b/hiro/extension/shared.hpp @@ -15,6 +15,7 @@ struct FixedLayout : sFixedLayout { auto cell(uint position) const { return self().cell(position); } auto cell(sSizable sizable) const { return self().cell(sizable); } auto cellCount() const { return self().cellCount(); } + auto remove(sSizable sizable) { return self().remove(sizable), *this; } auto remove(sFixedLayoutCell cell) { return self().remove(cell), *this; } auto reset() { return self().reset(), *this; } }; @@ -42,6 +43,7 @@ struct HorizontalLayout : sHorizontalLayout { auto cell(uint position) const { return self().cell(position); } auto cell(sSizable sizable) const { return self().cell(sizable); } auto cellCount() const { return self().cellCount(); } + auto remove(sSizable sizable) { return self().remove(sizable), *this; } auto remove(sHorizontalLayoutCell cell) { return self().remove(cell), *this; } auto reset() { return self().reset(), *this; } auto setAlignment(maybe alignment = {}) { return self().setAlignment(alignment), *this; } @@ -125,6 +127,7 @@ struct TableLayout : sTableLayout { auto column(uint position) const { return self().column(position); } auto columnCount() const { return self().columnCount(); } auto padding() const { return self().padding(); } + auto remove(sSizable sizable) { return self().remove(sizable), *this; } auto remove(sTableLayoutCell cell) { return self().remove(cell), *this; } auto reset() { return self().reset(), *this; } auto row(uint position) const { return self().row(position); } diff --git a/hiro/extension/table-layout.cpp b/hiro/extension/table-layout.cpp index 77b689e0..973db6ce 100644 --- a/hiro/extension/table-layout.cpp +++ b/hiro/extension/table-layout.cpp @@ -93,6 +93,13 @@ auto mTableLayout::padding() const -> Geometry { return state.padding; } +auto mTableLayout::remove(sSizable sizable) -> type& { + for(auto& cell : state.cells) { + if(cell->state.sizable == sizable) return remove(cell); + } + return *this; +} + auto mTableLayout::remove(sTableLayoutCell cell) -> type& { if(cell->parent() != this) return *this; auto offset = cell->offset(); diff --git a/hiro/extension/table-layout.hpp b/hiro/extension/table-layout.hpp index c270a3b8..e67ef54d 100644 --- a/hiro/extension/table-layout.hpp +++ b/hiro/extension/table-layout.hpp @@ -29,6 +29,7 @@ struct mTableLayout : mSizable { auto columnCount() const -> uint; auto minimumSize() const -> Size override; auto padding() const -> Geometry; + auto remove(sSizable sizable) -> type&; auto remove(sTableLayoutCell cell) -> type&; auto reset() -> type&; auto row(uint position) const -> TableLayoutRow; diff --git a/hiro/extension/vertical-layout.cpp b/hiro/extension/vertical-layout.cpp index 737e01d6..0bb6e79f 100644 --- a/hiro/extension/vertical-layout.cpp +++ b/hiro/extension/vertical-layout.cpp @@ -68,10 +68,7 @@ auto mVerticalLayout::padding() const -> Geometry { auto mVerticalLayout::remove(sSizable sizable) -> type& { for(auto& cell : state.cells) { - if(cell->state.sizable == sizable) { - remove(cell); - break; - } + if(cell->state.sizable == sizable) return remove(cell); } return *this; } diff --git a/hiro/gtk/window.cpp b/hiro/gtk/window.cpp index 74a4bfa1..5dbd1e9a 100644 --- a/hiro/gtk/window.cpp +++ b/hiro/gtk/window.cpp @@ -269,6 +269,12 @@ auto pWindow::handle() const -> uintptr { return (uintptr)nullptr; } +auto pWindow::monitor() const -> uint { + if(!gtk_widget_get_realized(widget)) return 0; + auto window = gtk_widget_get_window(widget); + return gdk_screen_get_monitor_at_window(gdk_screen_get_default(), window); +} + auto pWindow::remove(sMenuBar menuBar) -> void { _setMenuVisible(false); } @@ -558,7 +564,9 @@ auto pWindow::_synchronizeGeometry() -> void { } lastSize = allocation; - gtk_widget_get_allocation(widget, &allocation); + auto gdkWindow = gtk_widget_get_window(widget); + gdk_window_get_origin(gdkWindow, &allocation.x, &allocation.y); + allocation.y += _menuHeight(); if(allocation.x != lastMove.x || allocation.y != lastMove.y) { state().geometry.setPosition({allocation.x, allocation.y}); self().doMove(); diff --git a/hiro/gtk/window.hpp b/hiro/gtk/window.hpp index 73e03281..95758452 100644 --- a/hiro/gtk/window.hpp +++ b/hiro/gtk/window.hpp @@ -11,6 +11,7 @@ struct pWindow : pObject { auto focused() const -> bool override; auto frameMargin() const -> Geometry; auto handle() const -> uintptr; + auto monitor() const -> uint; auto remove(sMenuBar menuBar) -> void; auto remove(sSizable sizable) -> void; auto remove(sStatusBar statusBar) -> void; diff --git a/hiro/qt/utility.cpp b/hiro/qt/utility.cpp index dd6810f2..17008b5e 100644 --- a/hiro/qt/utility.cpp +++ b/hiro/qt/utility.cpp @@ -28,11 +28,11 @@ static auto CreateIcon(const image& icon, bool scale = false) -> QIcon { return QIcon(QPixmap::fromImage(qtImage)); } -static auto DropPaths(QDropEvent* event) -> string_vector { +static auto DropPaths(QDropEvent* event) -> vector { QList urls = event->mimeData()->urls(); if(urls.size() == 0) return {}; - string_vector paths; + vector paths; for(auto n : range(urls.size())) { string path{urls[n].path().toUtf8().constData()}; if(!path) continue; diff --git a/hiro/qt/window.cpp b/hiro/qt/window.cpp index f16b23f5..34773a5c 100644 --- a/hiro/qt/window.cpp +++ b/hiro/qt/window.cpp @@ -78,6 +78,11 @@ auto pWindow::frameMargin() const -> Geometry { }; } +auto pWindow::monitor() const -> uint { + //TODO + return 0; +} + auto pWindow::remove(sMenuBar menuBar) -> void { //QMenuBar::removeMenu() does not exist //qtMenu->clear(); diff --git a/hiro/qt/window.hpp b/hiro/qt/window.hpp index e2daeb4b..0d22e675 100644 --- a/hiro/qt/window.hpp +++ b/hiro/qt/window.hpp @@ -10,6 +10,7 @@ struct pWindow : pObject { auto append(sStatusBar statusBar) -> void; auto focused() const -> bool override; auto frameMargin() const -> Geometry; + auto monitor() const -> uint; auto remove(sMenuBar menuBar) -> void; auto remove(sSizable sizable) -> void; auto remove(sStatusBar statusBar) -> void; diff --git a/hiro/reference/action/action.cpp b/hiro/reference/action/action.cpp deleted file mode 100644 index 320911d3..00000000 --- a/hiro/reference/action/action.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pAction::setEnabled(bool enabled) { -} - -void pAction::setVisible(bool visible) { -} - -void pAction::constructor() { -} - -void pAction::destructor() { -} - -} diff --git a/hiro/reference/action/action.hpp b/hiro/reference/action/action.hpp deleted file mode 100644 index 5e91be2d..00000000 --- a/hiro/reference/action/action.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pAction : public pObject { - Action& action; - - void setEnabled(bool enabled); - void setVisible(bool visible); - - pAction(Action& action) : pObject(action), action(action) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/action/check-item.cpp b/hiro/reference/action/check-item.cpp deleted file mode 100644 index f7a33af5..00000000 --- a/hiro/reference/action/check-item.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pCheckItem::setChecked(bool checked) { -} - -void pCheckItem::setText(string text) { -} - -void pCheckItem::constructor() { -} - -void pCheckItem::destructor() { -} - -} diff --git a/hiro/reference/action/check-item.hpp b/hiro/reference/action/check-item.hpp deleted file mode 100644 index 3c1da56b..00000000 --- a/hiro/reference/action/check-item.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pCheckItem : public pAction { - CheckItem& checkItem; - - void setChecked(bool checked); - void setText(string text); - - pCheckItem(CheckItem& checkItem) : pAction(checkItem), checkItem(checkItem) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/action/item.cpp b/hiro/reference/action/item.cpp deleted file mode 100644 index b010da65..00000000 --- a/hiro/reference/action/item.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pItem::setImage(const image& image) { -} - -void pItem::setText(string text) { -} - -void pItem::constructor() { -} - -void pItem::destructor() { -} - -} diff --git a/hiro/reference/action/item.hpp b/hiro/reference/action/item.hpp deleted file mode 100644 index 9e255fb4..00000000 --- a/hiro/reference/action/item.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pItem : public pAction { - Item& item; - - void setImage(const image& image); - void setText(string text); - - pItem(Item& item) : pAction(item), item(item) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/action/menu.cpp b/hiro/reference/action/menu.cpp deleted file mode 100644 index 157858be..00000000 --- a/hiro/reference/action/menu.cpp +++ /dev/null @@ -1,21 +0,0 @@ -namespace phoenix { - -void pMenu::append(Action& action) { -} - -void pMenu::remove(Action& action) { -} - -void pMenu::setImage(const image& image) { -} - -void pMenu::setText(string text) { -} - -void pMenu::constructor() { -} - -void pMenu::destructor() { -} - -} diff --git a/hiro/reference/action/menu.hpp b/hiro/reference/action/menu.hpp deleted file mode 100644 index 9bcddf60..00000000 --- a/hiro/reference/action/menu.hpp +++ /dev/null @@ -1,16 +0,0 @@ -namespace phoenix { - -struct pMenu : public pAction { - Menu& menu; - - void append(Action& action); - void remove(Action& action); - void setImage(const image& image); - void setText(string text); - - pMenu(Menu& menu) : pAction(menu), menu(menu) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/action/radio-item.cpp b/hiro/reference/action/radio-item.cpp deleted file mode 100644 index e6fc1236..00000000 --- a/hiro/reference/action/radio-item.cpp +++ /dev/null @@ -1,18 +0,0 @@ -namespace phoenix { - -void pRadioItem::setChecked() { -} - -void pRadioItem::setGroup(const group& group) { -} - -void pRadioItem::setText(string text) { -} - -void pRadioItem::constructor() { -} - -void pRadioItem::destructor() { -} - -} diff --git a/hiro/reference/action/radio-item.hpp b/hiro/reference/action/radio-item.hpp deleted file mode 100644 index c574341f..00000000 --- a/hiro/reference/action/radio-item.hpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -struct pRadioItem : public pAction { - RadioItem& radioItem; - - void setChecked(); - void setGroup(const group& group); - void setText(string text); - - pRadioItem(RadioItem& radioItem) : pAction(radioItem), radioItem(radioItem) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/action/separator.cpp b/hiro/reference/action/separator.cpp deleted file mode 100644 index 64e21197..00000000 --- a/hiro/reference/action/separator.cpp +++ /dev/null @@ -1,9 +0,0 @@ -namespace phoenix { - -void pSeparator::constructor() { -} - -void pSeparator::destructor() { -} - -} diff --git a/hiro/reference/action/separator.hpp b/hiro/reference/action/separator.hpp deleted file mode 100644 index de93d34a..00000000 --- a/hiro/reference/action/separator.hpp +++ /dev/null @@ -1,11 +0,0 @@ -namespace phoenix { - -struct pSeparator : public pAction { - Separator& separator; - - pSeparator(Separator& separator) : pAction(separator), separator(separator) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/application.cpp b/hiro/reference/application.cpp deleted file mode 100644 index a05d1c3f..00000000 --- a/hiro/reference/application.cpp +++ /dev/null @@ -1,19 +0,0 @@ -namespace phoenix { - -void pApplication::run() { -} - -bool pApplication::pendingEvents() { - return false; -} - -void pApplication::processEvents() { -} - -void pApplication::quit() { -} - -void pApplication::initialize() { -} - -} diff --git a/hiro/reference/application.hpp b/hiro/reference/application.hpp deleted file mode 100644 index effab50b..00000000 --- a/hiro/reference/application.hpp +++ /dev/null @@ -1,12 +0,0 @@ -namespace phoenix { - -struct pApplication { - static void run(); - static bool pendingEvents(); - static void processEvents(); - static void quit(); - - static void initialize(); -}; - -} diff --git a/hiro/reference/browser-window.cpp b/hiro/reference/browser-window.cpp deleted file mode 100644 index f1885a74..00000000 --- a/hiro/reference/browser-window.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -string pBrowserWindow::directory(BrowserWindow::State& state) { - return ""; -} - -string pBrowserWindow::open(BrowserWindow::State& state) { - return ""; -} - -string pBrowserWindow::save(BrowserWindow::State& state) { - return ""; -} - -} diff --git a/hiro/reference/browser-window.hpp b/hiro/reference/browser-window.hpp deleted file mode 100644 index 56563bc7..00000000 --- a/hiro/reference/browser-window.hpp +++ /dev/null @@ -1,9 +0,0 @@ -namespace phoenix { - -struct pBrowserWindow { - static string directory(BrowserWindow::State& state); - static string open(BrowserWindow::State& state); - static string save(BrowserWindow::State& state); -}; - -} diff --git a/hiro/reference/desktop.cpp b/hiro/reference/desktop.cpp deleted file mode 100644 index ba385d9e..00000000 --- a/hiro/reference/desktop.cpp +++ /dev/null @@ -1,11 +0,0 @@ -namespace phoenix { - -Size pDesktop::size() { - return {0, 0}; -} - -Geometry pDesktop::workspace() { - return {0, 0, 0, 0}; -} - -} diff --git a/hiro/reference/desktop.hpp b/hiro/reference/desktop.hpp deleted file mode 100644 index fed9ab6a..00000000 --- a/hiro/reference/desktop.hpp +++ /dev/null @@ -1,8 +0,0 @@ -namespace phoenix { - -struct pDesktop { - static Size size(); - static Geometry workspace(); -}; - -} diff --git a/hiro/reference/font.cpp b/hiro/reference/font.cpp deleted file mode 100644 index e382add9..00000000 --- a/hiro/reference/font.cpp +++ /dev/null @@ -1,19 +0,0 @@ -namespace phoenix { - -string pFont::serif(unsigned size, string style) { - return ""; -} - -string pFont::sans(unsigned size, string style) { - return ""; -} - -string pFont::monospace(unsigned size, string style) { - return ""; -} - -Size pFont::size(string font, string text) { - return {0, 0}; -} - -} diff --git a/hiro/reference/font.hpp b/hiro/reference/font.hpp deleted file mode 100644 index 235806ac..00000000 --- a/hiro/reference/font.hpp +++ /dev/null @@ -1,10 +0,0 @@ -namespace phoenix { - -struct pFont { - static string serif(unsigned size, string style); - static string sans(unsigned size, string style); - static string monospace(unsigned size, string style); - static Size size(string font, string text); -}; - -} diff --git a/hiro/reference/header.hpp b/hiro/reference/header.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/hiro/reference/keyboard.cpp b/hiro/reference/keyboard.cpp deleted file mode 100644 index 9c2f8bb9..00000000 --- a/hiro/reference/keyboard.cpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -bool pKeyboard::pressed(Keyboard::Scancode scancode) { - return false; -} - -vector pKeyboard::state() { - vector output; - output.resize((unsigned)Keyboard::Scancode::Limit); - for(auto& n : output) n = false; - return output; -} - -} diff --git a/hiro/reference/keyboard.hpp b/hiro/reference/keyboard.hpp deleted file mode 100644 index 2c0a42ae..00000000 --- a/hiro/reference/keyboard.hpp +++ /dev/null @@ -1,8 +0,0 @@ -namespace phoenix { - -struct pKeyboard { - static bool pressed(Keyboard::Scancode scancode); - static vector state(); -}; - -} diff --git a/hiro/reference/message-window.cpp b/hiro/reference/message-window.cpp deleted file mode 100644 index 0334369e..00000000 --- a/hiro/reference/message-window.cpp +++ /dev/null @@ -1,19 +0,0 @@ -namespace phoenix { - -MessageWindow::Response pMessageWindow::error(MessageWindow::State& state) { - return MessageWindow::Response::Ok; -} - -MessageWindow::Response pMessageWindow::information(MessageWindow::State& state) { - return MessageWindow::Response::Ok; -} - -MessageWindow::Response pMessageWindow::question(MessageWindow::State& state) { - return MessageWindow::Response::Ok; -} - -MessageWindow::Response pMessageWindow::warning(MessageWindow::State& state) { - return MessageWindow::Response::Ok; -} - -} diff --git a/hiro/reference/message-window.hpp b/hiro/reference/message-window.hpp deleted file mode 100644 index b73b19e8..00000000 --- a/hiro/reference/message-window.hpp +++ /dev/null @@ -1,10 +0,0 @@ -namespace phoenix { - -struct pMessageWindow { - static MessageWindow::Response error(MessageWindow::State& state); - static MessageWindow::Response information(MessageWindow::State& state); - static MessageWindow::Response question(MessageWindow::State& state); - static MessageWindow::Response warning(MessageWindow::State& state); -}; - -} diff --git a/hiro/reference/monitor.cpp b/hiro/reference/monitor.cpp deleted file mode 100644 index de090e87..00000000 --- a/hiro/reference/monitor.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -unsigned pMonitor::count() { - return 1; -} - -Geometry pMonitor::geometry(unsigned monitor) { - return {0, 0, 0, 0}; -} - -unsigned pMonitor::primary() { - return 0; -} - -} diff --git a/hiro/reference/monitor.hpp b/hiro/reference/monitor.hpp deleted file mode 100644 index 0b5964c0..00000000 --- a/hiro/reference/monitor.hpp +++ /dev/null @@ -1,9 +0,0 @@ -namespace phoenix { - -struct pMonitor { - static unsigned count(); - static Geometry geometry(unsigned monitor); - static unsigned primary(); -}; - -} diff --git a/hiro/reference/mouse.cpp b/hiro/reference/mouse.cpp deleted file mode 100644 index ca5e8556..00000000 --- a/hiro/reference/mouse.cpp +++ /dev/null @@ -1,11 +0,0 @@ -namespace phoenix { - -Position pMouse::position() { - return {0, 0}; -} - -bool pMouse::pressed(Mouse::Button button) { - return false; -} - -} diff --git a/hiro/reference/mouse.hpp b/hiro/reference/mouse.hpp deleted file mode 100644 index 7e21f2ea..00000000 --- a/hiro/reference/mouse.hpp +++ /dev/null @@ -1,8 +0,0 @@ -namespace phoenix { - -struct pMouse { - static Position position(); - static bool pressed(Mouse::Button button); -}; - -} diff --git a/hiro/reference/object.cpp b/hiro/reference/object.cpp deleted file mode 100644 index d1397b10..00000000 --- a/hiro/reference/object.cpp +++ /dev/null @@ -1,9 +0,0 @@ -namespace phoenix { - -void pObject::constructor() { -} - -void pObject::destructor() { -} - -} diff --git a/hiro/reference/object.hpp b/hiro/reference/object.hpp deleted file mode 100644 index 2c4e013e..00000000 --- a/hiro/reference/object.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pObject { - Object& object; - bool locked; - - pObject(Object& object) : object(object), locked(locked) {} - virtual ~pObject() {} - - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/platform.cpp b/hiro/reference/platform.cpp deleted file mode 100644 index 883b0b2d..00000000 --- a/hiro/reference/platform.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "platform.hpp" - -#include "font.cpp" -#include "desktop.cpp" -#include "monitor.cpp" -#include "keyboard.cpp" -#include "mouse.cpp" -#include "browser-window.cpp" -#include "message-window.cpp" -#include "object.cpp" -#include "timer.cpp" -#include "window.cpp" -#include "popup-menu.cpp" - -#include "action/action.cpp" -#include "action/menu.cpp" -#include "action/separator.cpp" -#include "action/item.cpp" -#include "action/check-item.cpp" -#include "action/radio-item.cpp" - -#include "widget/widget.cpp" -#include "widget/button.cpp" -#include "widget/canvas.cpp" -#include "widget/check-button.cpp" -#include "widget/check-label.cpp" -#include "widget/combo-button.cpp" -#include "widget/console.cpp" -#include "widget/frame.cpp" -#include "widget/hex-edit.cpp" -#include "widget/horizontal-scroller.cpp" -#include "widget/horizontal-slider.cpp" -#include "widget/label.cpp" -#include "widget/line-edit.cpp" -#include "widget/list-view.cpp" -#include "widget/progress-bar.cpp" -#include "widget/radio-button.cpp" -#include "widget/radio-label.cpp" -#include "widget/tab-frame.cpp" -#include "widget/text-edit.cpp" -#include "widget/vertical-scroller.cpp" -#include "widget/vertical-slider.cpp" -#include "widget/viewport.cpp" - -#include "application.cpp" diff --git a/hiro/reference/platform.hpp b/hiro/reference/platform.hpp deleted file mode 100644 index 15cecec4..00000000 --- a/hiro/reference/platform.hpp +++ /dev/null @@ -1,53 +0,0 @@ -namespace phoenix { - struct pFont; - struct pWindow; - struct pMenu; - struct pLayout; - struct pWidget; -} - -#include "font.hpp" -#include "desktop.hpp" -#include "monitor.hpp" -#include "keyboard.hpp" -#include "mouse.hpp" -#include "browser-window.hpp" -#include "message-window.hpp" -#include "object.hpp" -#include "timer.hpp" -#include "window.hpp" -#include "popup-menu.hpp" - -#include "action/action.hpp" -#include "action/menu.hpp" -#include "action/separator.hpp" -#include "action/item.hpp" -#include "action/check-item.hpp" -#include "action/radio-item.hpp" - -#include "widget/sizable.hpp" -#include "widget/layout.hpp" -#include "widget/widget.hpp" -#include "widget/button.hpp" -#include "widget/canvas.hpp" -#include "widget/check-button.hpp" -#include "widget/check-label.hpp" -#include "widget/combo-button.hpp" -#include "widget/console.hpp" -#include "widget/frame.hpp" -#include "widget/hex-edit.hpp" -#include "widget/horizontal-scroller.hpp" -#include "widget/horizontal-slider.hpp" -#include "widget/label.hpp" -#include "widget/line-edit.hpp" -#include "widget/list-view.hpp" -#include "widget/progress-bar.hpp" -#include "widget/radio-button.hpp" -#include "widget/radio-label.hpp" -#include "widget/tab-frame.hpp" -#include "widget/text-edit.hpp" -#include "widget/vertical-scroller.hpp" -#include "widget/vertical-slider.hpp" -#include "widget/viewport.hpp" - -#include "application.hpp" diff --git a/hiro/reference/popup-menu.cpp b/hiro/reference/popup-menu.cpp deleted file mode 100644 index 1dea8c2f..00000000 --- a/hiro/reference/popup-menu.cpp +++ /dev/null @@ -1,18 +0,0 @@ -namespace phoenix { - -void pPopupMenu::append(Action& action) { -} - -void pPopupMenu::remove(Action& action) { -} - -void pPopupMenu::setVisible() { -} - -void pPopupMenu::constructor() { -} - -void pPopupMenu::destructor() { -} - -} diff --git a/hiro/reference/popup-menu.hpp b/hiro/reference/popup-menu.hpp deleted file mode 100644 index c1eb0641..00000000 --- a/hiro/reference/popup-menu.hpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -struct pPopupMenu : public pObject { - PopupMenu& popupMenu; - - void append(Action& action); - void remove(Action& action); - void setVisible(); - - pPopupMenu(PopupMenu& popupMenu) : pObject(popupMenu), popupMenu(popupMenu) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/timer.cpp b/hiro/reference/timer.cpp deleted file mode 100644 index 1d24c5a5..00000000 --- a/hiro/reference/timer.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pTimer::setEnabled(bool enabled) { -} - -void pTimer::setInterval(unsigned interval) { -} - -void pTimer::constructor() { -} - -void pTimer::destructor() { -} - -} diff --git a/hiro/reference/timer.hpp b/hiro/reference/timer.hpp deleted file mode 100644 index a924a9eb..00000000 --- a/hiro/reference/timer.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pTimer : public pObject { - Timer& timer; - - void setEnabled(bool enabled); - void setInterval(unsigned interval); - - pTimer(Timer& timer) : pObject(timer), timer(timer) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/button.cpp b/hiro/reference/widget/button.cpp deleted file mode 100644 index ad7c3362..00000000 --- a/hiro/reference/widget/button.cpp +++ /dev/null @@ -1,18 +0,0 @@ -namespace phoenix { - -void pButton::setBordered(bool bordered) { -} - -void pButton::setImage(const image& image, Orientation orientation) { -} - -void pButton::setText(string text) { -} - -void pButton::constructor() { -} - -void pButton::destructor() { -} - -} diff --git a/hiro/reference/widget/button.hpp b/hiro/reference/widget/button.hpp deleted file mode 100644 index c4e697b1..00000000 --- a/hiro/reference/widget/button.hpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -struct pButton : public pWidget { - Button& button; - - void setBordered(bool bordered); - void setImage(const image& image, Orientation orientation); - void setText(string text); - - pButton(Button& button) : pWidget(button), button(button) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/canvas.cpp b/hiro/reference/widget/canvas.cpp deleted file mode 100644 index b62da56a..00000000 --- a/hiro/reference/widget/canvas.cpp +++ /dev/null @@ -1,18 +0,0 @@ -namespace phoenix { - -void pCanvas::setDroppable(bool droppable) { -} - -void pCanvas::setMode(Canvas::Mode mode) { -} - -void pCanvas::setSize(Size size) { -} - -void pCanvas::constructor() { -} - -void pCanvas::destructor() { -} - -} diff --git a/hiro/reference/widget/canvas.hpp b/hiro/reference/widget/canvas.hpp deleted file mode 100644 index 67167cbd..00000000 --- a/hiro/reference/widget/canvas.hpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -struct pCanvas : public pWidget { - Canvas& canvas; - - void setDroppable(bool droppable); - void setMode(Canvas::Mode mode); - void setSize(Size size); - - pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/check-button.cpp b/hiro/reference/widget/check-button.cpp deleted file mode 100644 index ff13e279..00000000 --- a/hiro/reference/widget/check-button.cpp +++ /dev/null @@ -1,18 +0,0 @@ -namespace phoenix { - -void pCheckButton::setChecked(bool checked) { -} - -void pCheckButton::setImage(const image& image, Orientation orientation) { -} - -void pCheckButton::setText(string text) { -} - -void pCheckButton::constructor() { -} - -void pCheckButton::destructor() { -} - -} diff --git a/hiro/reference/widget/check-button.hpp b/hiro/reference/widget/check-button.hpp deleted file mode 100644 index eae9ad26..00000000 --- a/hiro/reference/widget/check-button.hpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -struct pCheckButton : public pWidget { - CheckButton& checkButton; - - void setChecked(bool checked); - void setImage(const image& image, Orientation orientation); - void setText(string text); - - pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/check-label.cpp b/hiro/reference/widget/check-label.cpp deleted file mode 100644 index f3751203..00000000 --- a/hiro/reference/widget/check-label.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pCheckLabel::setChecked(bool checked) { -} - -void pCheckLabel::setText(string text) { -} - -void pCheckLabel::constructor() { -} - -void pCheckLabel::destructor() { -} - -} diff --git a/hiro/reference/widget/check-label.hpp b/hiro/reference/widget/check-label.hpp deleted file mode 100644 index 254092f9..00000000 --- a/hiro/reference/widget/check-label.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pCheckLabel : public pWidget { - CheckLabel& checkLabel; - - void setChecked(bool checked); - void setText(string text); - - pCheckLabel(CheckLabel& checkLabel) : pWidget(checkLabel), checkLabel(checkLabel) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/combo-button.cpp b/hiro/reference/widget/combo-button.cpp deleted file mode 100644 index d9f5d3b1..00000000 --- a/hiro/reference/widget/combo-button.cpp +++ /dev/null @@ -1,24 +0,0 @@ -namespace phoenix { - -void pComboButton::append() { -} - -void pComboButton::remove(unsigned selection) { -} - -void pComboButton::reset() { -} - -void pComboButton::setSelected(unsigned selection) { -} - -void pComboButton::setText(unsigned selection, string text) { -} - -void pComboButton::constructor() { -} - -void pComboButton::destructor() { -} - -} diff --git a/hiro/reference/widget/combo-button.hpp b/hiro/reference/widget/combo-button.hpp deleted file mode 100644 index 8b2b303f..00000000 --- a/hiro/reference/widget/combo-button.hpp +++ /dev/null @@ -1,17 +0,0 @@ -namespace phoenix { - -struct pComboButton : public pWidget { - ComboButton& comboButton; - - void append(); - void remove(unsigned selection); - void reset(); - void setSelected(unsigned selection); - void setText(unsigned selection, string text); - - pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/console.cpp b/hiro/reference/widget/console.cpp deleted file mode 100644 index fc27bcf6..00000000 --- a/hiro/reference/widget/console.cpp +++ /dev/null @@ -1,24 +0,0 @@ -namespace phoenix { - -void pConsole::print(string text) { -} - -void pConsole::reset() { -} - -void pConsole::setBackgroundColor(Color color) { -} - -void pConsole::setForegroundColor(Color color) { -} - -void pConsole::setPrompt(string prompt) { -} - -void pConsole::constructor() { -} - -void pConsole::destructor() { -} - -} diff --git a/hiro/reference/widget/console.hpp b/hiro/reference/widget/console.hpp deleted file mode 100644 index 50d2ce0a..00000000 --- a/hiro/reference/widget/console.hpp +++ /dev/null @@ -1,17 +0,0 @@ -namespace phoenix { - -struct pConsole : public pWidget { - Console& console; - - void print(string text); - void reset(); - void setBackgroundColor(Color color); - void setForegroundColor(Color color); - void setPrompt(string prompt); - - pConsole(Console& console) : pWidget(console), console(console) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/frame.cpp b/hiro/reference/widget/frame.cpp deleted file mode 100644 index cfac6257..00000000 --- a/hiro/reference/widget/frame.cpp +++ /dev/null @@ -1,12 +0,0 @@ -namespace phoenix { - -void pFrame::setText(string text) { -} - -void pFrame::constructor() { -} - -void pFrame::destructor() { -} - -} diff --git a/hiro/reference/widget/frame.hpp b/hiro/reference/widget/frame.hpp deleted file mode 100644 index f4477343..00000000 --- a/hiro/reference/widget/frame.hpp +++ /dev/null @@ -1,13 +0,0 @@ -namespace phoenix { - -struct pFrame : public pWidget { - Frame& frame; - - void setText(string text); - - pFrame(Frame& frame) : pWidget(frame), frame(frame) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/hex-edit.cpp b/hiro/reference/widget/hex-edit.cpp deleted file mode 100644 index b816cbc3..00000000 --- a/hiro/reference/widget/hex-edit.cpp +++ /dev/null @@ -1,30 +0,0 @@ -namespace phoenix { - -void pHexEdit::setBackgroundColor(Color color) { -} - -void pHexEdit::setColumns(unsigned columns) { -} - -void pHexEdit::setForegroundColor(Color color) { -} - -void pHexEdit::setLength(unsigned length) { -} - -void pHexEdit::setOffset(unsigned offset) { -} - -void pHexEdit::setRows(unsigned rows) { -} - -void pHexEdit::update() { -} - -void pHexEdit::constructor() { -} - -void pHexEdit::destructor() { -} - -} diff --git a/hiro/reference/widget/hex-edit.hpp b/hiro/reference/widget/hex-edit.hpp deleted file mode 100644 index e79b929b..00000000 --- a/hiro/reference/widget/hex-edit.hpp +++ /dev/null @@ -1,19 +0,0 @@ -namespace phoenix { - -struct pHexEdit : public pWidget { - HexEdit& hexEdit; - - void setBackgroundColor(Color color); - void setColumns(unsigned columns); - void setForegroundColor(Color color); - void setLength(unsigned length); - void setOffset(unsigned offset); - void setRows(unsigned rows); - void update(); - - pHexEdit(HexEdit& hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/horizontal-scroller.cpp b/hiro/reference/widget/horizontal-scroller.cpp deleted file mode 100644 index 6bd66d06..00000000 --- a/hiro/reference/widget/horizontal-scroller.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pHorizontalScroller::setLength(unsigned length) { -} - -void pHorizontalScroller::setPosition(unsigned position) { -} - -void pHorizontalScroller::constructor() { -} - -void pHorizontalScroller::destructor() { -} - -} diff --git a/hiro/reference/widget/horizontal-scroller.hpp b/hiro/reference/widget/horizontal-scroller.hpp deleted file mode 100644 index 8649b420..00000000 --- a/hiro/reference/widget/horizontal-scroller.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pHorizontalScroller : public pWidget { - HorizontalScroller& horizontalScroller; - - void setLength(unsigned length); - void setPosition(unsigned position); - - pHorizontalScroller(HorizontalScroller& horizontalScroller) : pWidget(horizontalScroller), horizontalScroller(horizontalScroller) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/horizontal-slider.cpp b/hiro/reference/widget/horizontal-slider.cpp deleted file mode 100644 index 96c2f8c5..00000000 --- a/hiro/reference/widget/horizontal-slider.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pHorizontalSlider::setLength(unsigned length) { -} - -void pHorizontalSlider::setPosition(unsigned position) { -} - -void pHorizontalSlider::constructor() { -} - -void pHorizontalSlider::destructor() { -} - -} diff --git a/hiro/reference/widget/horizontal-slider.hpp b/hiro/reference/widget/horizontal-slider.hpp deleted file mode 100644 index 2bb7a402..00000000 --- a/hiro/reference/widget/horizontal-slider.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pHorizontalSlider : public pWidget { - HorizontalSlider& horizontalSlider; - - void setLength(unsigned length); - void setPosition(unsigned position); - - pHorizontalSlider(HorizontalSlider& horizontalSlider) : pWidget(horizontalSlider), horizontalSlider(horizontalSlider) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/label.cpp b/hiro/reference/widget/label.cpp deleted file mode 100644 index cf5af2c7..00000000 --- a/hiro/reference/widget/label.cpp +++ /dev/null @@ -1,12 +0,0 @@ -namespace phoenix { - -void pLabel::setText(string text) { -} - -void pLabel::constructor() { -} - -void pLabel::destructor() { -} - -} diff --git a/hiro/reference/widget/label.hpp b/hiro/reference/widget/label.hpp deleted file mode 100644 index 1d6a94fa..00000000 --- a/hiro/reference/widget/label.hpp +++ /dev/null @@ -1,13 +0,0 @@ -namespace phoenix { - -struct pLabel : public pWidget { - Label& label; - - void setText(string text); - - pLabel(Label& label) : pWidget(label), label(label) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/layout.hpp b/hiro/reference/widget/layout.hpp deleted file mode 100644 index 45b0d2d5..00000000 --- a/hiro/reference/widget/layout.hpp +++ /dev/null @@ -1,9 +0,0 @@ -namespace phoenix { - -struct pLayout : public pSizable { - Layout& layout; - - pLayout(Layout& layout) : pSizable(layout), layout(layout) {} -}; - -} diff --git a/hiro/reference/widget/line-edit.cpp b/hiro/reference/widget/line-edit.cpp deleted file mode 100644 index 2ccdb29d..00000000 --- a/hiro/reference/widget/line-edit.cpp +++ /dev/null @@ -1,24 +0,0 @@ -namespace phoenix { - -void pLineEdit::setBackgroundColor(Color color) { -} - -void pLineEdit::setEditable(bool editable) { -} - -void pLineEdit::setForegroundColor(Color color) { -} - -void pLineEdit::setText(string text) { -} - -string pLineEdit::text() { -} - -void pLineEdit::constructor() { -} - -void pLineEdit::destructor() { -} - -} diff --git a/hiro/reference/widget/line-edit.hpp b/hiro/reference/widget/line-edit.hpp deleted file mode 100644 index bf1c3196..00000000 --- a/hiro/reference/widget/line-edit.hpp +++ /dev/null @@ -1,17 +0,0 @@ -namespace phoenix { - -struct pLineEdit : public pWidget { - LineEdit& lineEdit; - - void setBackgroundColor(Color color); - void setEditable(bool editable); - void setForegroundColor(Color color); - void setText(string text); - string text(); - - pLineEdit(LineEdit& lineEdit) : pWidget(lineEdit), lineEdit(lineEdit) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/list-view.cpp b/hiro/reference/widget/list-view.cpp deleted file mode 100644 index 7b732993..00000000 --- a/hiro/reference/widget/list-view.cpp +++ /dev/null @@ -1,69 +0,0 @@ -namespace phoenix { - -void pListView::append() { -} - -void pListView::autoSizeColumns() { -} - -void pListView::remove(unsigned selection) { -} - -void pListView::reset() { -} - -void pListView::setBackgroundColor(Color color) { -} - -void pListView::setCheckable(bool checkable) { -} - -void pListView::setChecked(unsigned selection, bool checked) { -} - -void pListView::setChecked(const vector& selections) { -} - -void pListView::setCheckedAll() { -} - -void pListView::setCheckedNone() { -} - -void pListView::setForegroundColor(Color color) { -} - -void pListView::setHeaderText(const string_vector& text) { -} - -void pListView::setHeaderVisible(bool visible) { -} - -void pListView::setImage(unsigned selection, unsigned position, const image& image) { -} - -void pListView::setSelected(unsigned selection, bool selected) { -} - -void pListView::setSelected(const vector& selections) { -} - -void pListView::setSelectedAll() { -} - -void pListView::setSelectedNone() { -} - -void pListView::setSingleSelection(bool singleSelection) { -} - -void pListView::setText(unsigned selection, unsigned position, string text) { -} - -void pListView::constructor() { -} - -void pListView::destructor() { -} - -} diff --git a/hiro/reference/widget/list-view.hpp b/hiro/reference/widget/list-view.hpp deleted file mode 100644 index 3b2e1528..00000000 --- a/hiro/reference/widget/list-view.hpp +++ /dev/null @@ -1,32 +0,0 @@ -namespace phoenix { - -struct pListView : public pWidget { - ListView& listView; - - void append(); - void autoSizeColumns(); - void remove(unsigned selection); - void reset(); - void setBackgroundColor(Color color); - void setCheckable(bool checkable); - void setChecked(unsigned selection, bool checked); - void setChecked(const vector& selections); - void setCheckedAll(); - void setCheckedNone(); - void setForegroundColor(Color color); - void setHeaderText(const lstring& text); - void setHeaderVisible(bool visible); - void setImage(unsigned selection, unsigned position, const image& image); - void setSelected(unsigned selection, bool selected); - void setSelected(const vector& selections); - void setSelectedAll(); - void setSelectedNone(); - void setSingleSelection(bool singleSelection); - void setText(unsigned selection, unsigned position, string text); - - pListView(ListView& listView) : pWidget(listView), listView(listView) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/progress-bar.cpp b/hiro/reference/widget/progress-bar.cpp deleted file mode 100644 index 7697f65a..00000000 --- a/hiro/reference/widget/progress-bar.cpp +++ /dev/null @@ -1,12 +0,0 @@ -namespace phoenix { - -void pProgressBar::setPosition(unsigned position) { -} - -void pProgressBar::constructor() { -} - -void pProgressBar::destructor() { -} - -} diff --git a/hiro/reference/widget/progress-bar.hpp b/hiro/reference/widget/progress-bar.hpp deleted file mode 100644 index c0767083..00000000 --- a/hiro/reference/widget/progress-bar.hpp +++ /dev/null @@ -1,13 +0,0 @@ -namespace phoenix { - -struct pProgressBar : public pWidget { - ProgressBar& progressBar; - - void setPosition(unsigned position); - - pProgressBar(ProgressBar& progressBar) : pWidget(progressBar), progressBar(progressBar) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/radio-button.cpp b/hiro/reference/widget/radio-button.cpp deleted file mode 100644 index 457499e6..00000000 --- a/hiro/reference/widget/radio-button.cpp +++ /dev/null @@ -1,21 +0,0 @@ -namespace phoenix { - -void pRadioButton::setChecked() { -} - -void pRadioButton::setGroup(const group& group) { -} - -void pRadioButton::setImage(const image& image, Orientation orientation) { -} - -void pRadioButton::setText(string text) { -} - -void pRadioButton::constructor() { -} - -void pRadioButton::destructor() { -} - -} diff --git a/hiro/reference/widget/radio-button.hpp b/hiro/reference/widget/radio-button.hpp deleted file mode 100644 index d9377bc9..00000000 --- a/hiro/reference/widget/radio-button.hpp +++ /dev/null @@ -1,16 +0,0 @@ -namespace phoenix { - -struct pRadioButton : public pWidget { - RadioButton& radioButton; - - void setChecked(); - void setGroup(const group& group); - void setImage(const image& image, Orientation orientation); - void setText(string text); - - pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/radio-label.cpp b/hiro/reference/widget/radio-label.cpp deleted file mode 100644 index 61811514..00000000 --- a/hiro/reference/widget/radio-label.cpp +++ /dev/null @@ -1,18 +0,0 @@ -namespace phoenix { - -void pRadioLabel::setChecked() { -} - -void pRadioLabel::setGroup(const group& group) { -} - -void pRadioLabel::setText(string text) { -} - -void pRadioLabel::constructor() { -} - -void pRadioLabel::destructor() { -} - -} diff --git a/hiro/reference/widget/radio-label.hpp b/hiro/reference/widget/radio-label.hpp deleted file mode 100644 index ddd6b8a1..00000000 --- a/hiro/reference/widget/radio-label.hpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -struct pRadioLabel : public pWidget { - RadioLabel& radioLabel; - - void setChecked(); - void setGroup(const group& group); - void setText(string text); - - pRadioLabel(RadioLabel& radioLabel) : pWidget(radioLabel), radioLabel(radioLabel) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/sizable.hpp b/hiro/reference/widget/sizable.hpp deleted file mode 100644 index afb33e67..00000000 --- a/hiro/reference/widget/sizable.hpp +++ /dev/null @@ -1,9 +0,0 @@ -namespace phoenix { - -struct pSizable : public pObject { - Sizable& sizable; - - pSizable(Sizable& sizable) : pObject(sizable), sizable(sizable) {} -}; - -} diff --git a/hiro/reference/widget/tab-frame.cpp b/hiro/reference/widget/tab-frame.cpp deleted file mode 100644 index 065a89b7..00000000 --- a/hiro/reference/widget/tab-frame.cpp +++ /dev/null @@ -1,24 +0,0 @@ -namespace phoenix { - -void pTabFrame::append() { -} - -void pTabFrame::remove(unsigned selection) { -} - -void pTabFrame::setImage(unsigned selection, const image& image) { -} - -void pTabFrame::setSelected(unsigned selection) { -} - -void pTabFrame::setText(unsigned selection, string text) { -} - -void pTabFrame::constructor() { -} - -void pTabFrame::destructor() { -} - -} diff --git a/hiro/reference/widget/tab-frame.hpp b/hiro/reference/widget/tab-frame.hpp deleted file mode 100644 index 9984ef1d..00000000 --- a/hiro/reference/widget/tab-frame.hpp +++ /dev/null @@ -1,17 +0,0 @@ -namespace phoenix { - -struct pTabFrame : public pWidget { - TabFrame& tabFrame; - - void append(); - void remove(unsigned selection); - void setImage(unsigned selection, const image& image); - void setSelected(unsigned selection); - void setText(unsigned selection, string text); - - pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/text-edit.cpp b/hiro/reference/widget/text-edit.cpp deleted file mode 100644 index 064e304b..00000000 --- a/hiro/reference/widget/text-edit.cpp +++ /dev/null @@ -1,30 +0,0 @@ -namespace phoenix { - -void pTextEdit::setBackgroundColor(Color color) { -} - -void pTextEdit::setCursorPosition(unsigned position) { -} - -void pTextEdit::setEditable(bool editable) { -} - -void pTextEdit::setForegroundColor(Color color) { -} - -void pTextEdit::setText(string text) { -} - -void pTextEdit::setWordWrap(bool wordWrap) { -} - -string pTextEdit::text() { -} - -void pTextEdit::constructor() { -} - -void pTextEdit::destructor() { -} - -} diff --git a/hiro/reference/widget/text-edit.hpp b/hiro/reference/widget/text-edit.hpp deleted file mode 100644 index 8d4cf77a..00000000 --- a/hiro/reference/widget/text-edit.hpp +++ /dev/null @@ -1,19 +0,0 @@ -namespace phoenix { - -struct pTextEdit : public pWidget { - TextEdit& textEdit; - - void setBackgroundColor(Color color); - void setCursorPosition(unsigned position); - void setEditable(bool editable); - void setForegroundColor(Color color); - void setText(string text); - void setWordWrap(bool wordWrap); - string text(); - - pTextEdit(TextEdit& textEdit) : pWidget(textEdit), textEdit(textEdit) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/vertical-scroller.cpp b/hiro/reference/widget/vertical-scroller.cpp deleted file mode 100644 index 533653cb..00000000 --- a/hiro/reference/widget/vertical-scroller.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pVerticalScroller::setLength(unsigned length) { -} - -void pVerticalScroller::setPosition(unsigned position) { -} - -void pVerticalScroller::constructor() { -} - -void pVerticalScroller::destructor() { -} - -} diff --git a/hiro/reference/widget/vertical-scroller.hpp b/hiro/reference/widget/vertical-scroller.hpp deleted file mode 100644 index 77e13a43..00000000 --- a/hiro/reference/widget/vertical-scroller.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pVerticalScroller : public pWidget { - VerticalScroller& verticalScroller; - - void setLength(unsigned length); - void setPosition(unsigned position); - - pVerticalScroller(VerticalScroller& verticalScroller) : pWidget(verticalScroller), verticalScroller(verticalScroller) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/vertical-slider.cpp b/hiro/reference/widget/vertical-slider.cpp deleted file mode 100644 index 36d62eb8..00000000 --- a/hiro/reference/widget/vertical-slider.cpp +++ /dev/null @@ -1,15 +0,0 @@ -namespace phoenix { - -void pVerticalSlider::setLength(unsigned length) { -} - -void pVerticalSlider::setPosition(unsigned position) { -} - -void pVerticalSlider::constructor() { -} - -void pVerticalSlider::destructor() { -} - -} diff --git a/hiro/reference/widget/vertical-slider.hpp b/hiro/reference/widget/vertical-slider.hpp deleted file mode 100644 index 0cfdf43b..00000000 --- a/hiro/reference/widget/vertical-slider.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pVerticalSlider : public pWidget { - VerticalSlider& verticalSlider; - - void setLength(unsigned length); - void setPosition(unsigned position); - - pVerticalSlider(VerticalSlider& verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/viewport.cpp b/hiro/reference/widget/viewport.cpp deleted file mode 100644 index 7ed229a2..00000000 --- a/hiro/reference/widget/viewport.cpp +++ /dev/null @@ -1,16 +0,0 @@ -namespace phoenix { - -uintptr_t pViewport::handle() { - return 0; -} - -void pViewport::setDroppable(bool droppable) { -} - -void pViewport::constructor() { -} - -void pViewport::destructor() { -} - -} diff --git a/hiro/reference/widget/viewport.hpp b/hiro/reference/widget/viewport.hpp deleted file mode 100644 index 75ef63ad..00000000 --- a/hiro/reference/widget/viewport.hpp +++ /dev/null @@ -1,14 +0,0 @@ -namespace phoenix { - -struct pViewport : public pWidget { - Viewport& viewport; - - uintptr_t handle(); - void setDroppable(bool droppable); - - pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/widget/widget.cpp b/hiro/reference/widget/widget.cpp deleted file mode 100644 index 8589f5db..00000000 --- a/hiro/reference/widget/widget.cpp +++ /dev/null @@ -1,36 +0,0 @@ -namespace phoenix { - -bool pWidget::enabled() { - return false; -} - -bool pWidget::focused() { - return false; -} - -Size pWidget::minimumSize() { - return {0, 0}; -} - -void pWidget::setEnabled(bool enabled) { -} - -void pWidget::setFocused() { -} - -void pWidget::setFont(string font) { -} - -void pWidget::setGeometry(Geometry geometry) { -} - -void pWidget::setVisible(bool visible) { -} - -void pWidget::constructor() { -} - -void pWidget::destructor() { -} - -} diff --git a/hiro/reference/widget/widget.hpp b/hiro/reference/widget/widget.hpp deleted file mode 100644 index 6a624a0f..00000000 --- a/hiro/reference/widget/widget.hpp +++ /dev/null @@ -1,20 +0,0 @@ -namespace phoenix { - -struct pWidget : public pSizable { - Widget& widget; - - bool enabled(); - bool focused(); - Size minimumSize(); - void setEnabled(bool enabled); - void setFocused(); - void setFont(string font); - void setGeometry(Geometry geometry); - void setVisible(bool visible); - - pWidget(Widget& widget) : pSizable(widget), widget(widget) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/reference/window.cpp b/hiro/reference/window.cpp deleted file mode 100644 index 20b63eba..00000000 --- a/hiro/reference/window.cpp +++ /dev/null @@ -1,86 +0,0 @@ -namespace phoenix { - -Window& pWindow::none() { - static Window* window = nullptr; - if(window == nullptr) window = new Window; - return *window; -} - -void pWindow::append(Layout& layout) { -} - -void pWindow::append(Menu& menu) { -} - -void pWindow::append(Widget& widget) { -} - -bool pWindow::focused() { - return false; -} - -Geometry pWindow::frameMargin() { - return {0, 0, 0, 0}; -} - -void pWindow::remove(Layout& layout) { -} - -void pWindow::remove(Menu& menu) { -} - -void pWindow::remove(Widget& widget) { -} - -void pWindow::setBackgroundColor(Color color) { -} - -void pWindow::setDroppable(bool droppable) { -} - -void pWindow::setFocused() { -} - -void pWindow::setFullScreen(bool fullScreen) { -} - -void pWindow::setGeometry(Geometry geometry) { -} - -void pWindow::setMenuFont(string font) { -} - -void pWindow::setMenuVisible(bool visible) { -} - -void pWindow::setModal(bool modal) { -} - -void pWindow::setResizable(bool resizable) { -} - -void pWindow::setStatusFont(string font) { -} - -void pWindow::setStatusText(string text) { -} - -void pWindow::setStatusVisible(bool visible) { -} - -void pWindow::setTitle(string text) { -} - -void pWindow::setVisible(bool visible) { -} - -void pWindow::setWidgetFont(string font) { -} - -void pWindow::constructor() { -} - -void pWindow::destructor() { -} - -} diff --git a/hiro/reference/window.hpp b/hiro/reference/window.hpp deleted file mode 100644 index b72efc84..00000000 --- a/hiro/reference/window.hpp +++ /dev/null @@ -1,37 +0,0 @@ -namespace phoenix { - -struct pWindow : public pObject { - Window& window; - - static Window& none(); - - void append(Layout& layout); - void append(Menu& menu); - void append(Widget& widget); - bool focused(); - Geometry frameMargin(); - void remove(Layout& layout); - void remove(Menu& menu); - void remove(Widget& widget); - void setBackgroundColor(Color color); - void setDroppable(bool droppable); - void setFocused(); - void setFullScreen(bool fullScreen); - void setGeometry(Geometry geometry); - void setMenuFont(string font); - void setMenuVisible(bool visible); - void setModal(bool modal); - void setResizable(bool resizable); - void setStatusFont(string font); - void setStatusText(string text); - void setStatusVisible(bool visible); - void setTitle(string text); - void setVisible(bool visible); - void setWidgetFont(string font); - - pWindow(Window& window) : pObject(window), window(window) {} - void constructor(); - void destructor(); -}; - -} diff --git a/hiro/windows/utility.cpp b/hiro/windows/utility.cpp index c3078794..d6d383b9 100644 --- a/hiro/windows/utility.cpp +++ b/hiro/windows/utility.cpp @@ -38,11 +38,11 @@ static auto CreateRGB(const Color& color) -> COLORREF { return RGB(color.red(), color.green(), color.blue()); } -static auto DropPaths(WPARAM wparam) -> string_vector { +static auto DropPaths(WPARAM wparam) -> vector { auto dropList = HDROP(wparam); auto fileCount = DragQueryFile(dropList, ~0u, nullptr, 0); - string_vector paths; + vector paths; for(auto n : range(fileCount)) { auto length = DragQueryFile(dropList, n, nullptr, 0); auto buffer = new wchar_t[length + 1]; diff --git a/hiro/windows/window.cpp b/hiro/windows/window.cpp index fcaf2d3e..f39408df 100644 --- a/hiro/windows/window.cpp +++ b/hiro/windows/window.cpp @@ -55,6 +55,11 @@ auto pWindow::frameMargin() const -> Geometry { return {abs(rc.left), abs(rc.top), (rc.right - rc.left) - 640, (rc.bottom - rc.top) + _statusHeight() - 480}; } +auto pWindow::monitor() const -> uint { + //TODO + return 0; +} + auto pWindow::remove(sMenuBar menuBar) -> void { } diff --git a/hiro/windows/window.hpp b/hiro/windows/window.hpp index 2e361de8..8c5d3d71 100644 --- a/hiro/windows/window.hpp +++ b/hiro/windows/window.hpp @@ -14,6 +14,7 @@ struct pWindow : pObject { auto append(sStatusBar statusBar) -> void; auto focused() const -> bool override; auto frameMargin() const -> Geometry; + auto monitor() const -> uint; auto remove(sMenuBar menuBar) -> void; auto remove(sSizable sizable) -> void; auto remove(sStatusBar statusBar) -> void; diff --git a/nall/beat/archive.hpp b/nall/beat/archive.hpp index 3e940375..03f7276a 100644 --- a/nall/beat/archive.hpp +++ b/nall/beat/archive.hpp @@ -10,7 +10,7 @@ struct Archive { static auto extract(const string& beatname, const string& pathname) -> vector; private: - static auto scan(string_vector& result, const string& basename, const string& pathname) -> void; + static auto scan(vector& result, const string& basename, const string& pathname) -> void; }; auto Archive::create(const string& beatname, const string& pathname, const string& metadata) -> bool { @@ -23,7 +23,7 @@ auto Archive::create(const string& beatname, const string& pathname, const strin beat.writevu(metadata.size()); beat.writes(metadata); - string_vector contents; + vector contents; scan(contents, pathname, pathname); for(auto& name : contents) { @@ -121,7 +121,7 @@ auto Archive::extract(const string& beatname, const string& filename) -> vector< return {}; } -auto Archive::scan(string_vector& result, const string& basename, const string& pathname) -> void { +auto Archive::scan(vector& result, const string& basename, const string& pathname) -> void { for(auto& name : directory::contents(pathname)) { result.append(string{pathname, name}.trimLeft(basename, 1L)); if(name.endsWith("/")) scan(result, basename, {pathname, name}); diff --git a/nall/beat/multi.hpp b/nall/beat/multi.hpp index 651bded3..442f3a59 100644 --- a/nall/beat/multi.hpp +++ b/nall/beat/multi.hpp @@ -28,7 +28,7 @@ struct bpsmulti { writeNumber(metadata.length()); writeString(metadata); - string_vector sourceList, targetList; + vector sourceList, targetList; ls(sourceList, sourcePath, sourcePath); ls(targetList, targetPath, targetPath); @@ -156,7 +156,7 @@ protected: Hash::CRC32 checksum; //create() functions - auto ls(string_vector& list, const string& path, const string& basepath) -> void { + auto ls(vector& list, const string& path, const string& basepath) -> void { auto paths = directory::folders(path); for(auto& pathname : paths) { list.append(string{path, pathname}.trimLeft(basepath, 1L)); diff --git a/nall/decode/zip.hpp b/nall/decode/zip.hpp index e6314aa7..c4177cc5 100644 --- a/nall/decode/zip.hpp +++ b/nall/decode/zip.hpp @@ -15,6 +15,7 @@ struct ZIP { uint csize; uint cmode; //0 = uncompressed, 8 = deflate uint crc32; + time_t timestamp; }; ~ZIP() { @@ -60,6 +61,18 @@ struct ZIP { file.csize = read(directory + 20, 4); file.size = read(directory + 24, 4); + uint16_t dosTime = read(directory + 12, 2); + uint16_t dosDate = read(directory + 14, 2); + tm info = {}; + info.tm_sec = (dosTime >> 0 & 31) << 1; + info.tm_min = (dosTime >> 5 & 63); + info.tm_hour = (dosTime >> 11 & 31); + info.tm_mday = (dosDate >> 0 & 31); + info.tm_mon = (dosDate >> 5 & 15) - 1; + info.tm_year = (dosDate >> 9 & 127) + 80; + info.tm_isdst = -1; + file.timestamp = mktime(&info); + uint namelength = read(directory + 28, 2); uint extralength = read(directory + 30, 2); uint commentlength = read(directory + 32, 2); diff --git a/nall/dsp/dsp.hpp b/nall/dsp/dsp.hpp index 3bf21127..2e0d160a 100644 --- a/nall/dsp/dsp.hpp +++ b/nall/dsp/dsp.hpp @@ -2,10 +2,4 @@ namespace nall { namespace DSP { -#if defined(NALL_DSP_PRECISION) -using real = NALL_DSP_PRECISION; -#else -using real = double; -#endif - }} diff --git a/nall/dsp/iir/biquad.hpp b/nall/dsp/iir/biquad.hpp index 5bc63043..661a204a 100644 --- a/nall/dsp/iir/biquad.hpp +++ b/nall/dsp/iir/biquad.hpp @@ -17,22 +17,22 @@ struct Biquad { HighShelf, }; - inline auto reset(Type type, real cutoffFrequency, real samplingFrequency, real quality, real gain = 0.0) -> void; - inline auto process(real in) -> real; //normalized sample (-1.0 to +1.0) + inline auto reset(Type type, double cutoffFrequency, double samplingFrequency, double quality, double gain = 0.0) -> void; + inline auto process(double in) -> double; //normalized sample (-1.0 to +1.0) - inline static auto butterworth(uint order, uint phase) -> real; + inline static auto butterworth(uint order, uint phase) -> double; private: Type type; - real cutoffFrequency; - real samplingFrequency; - real quality; //frequency response quality - real gain; //peak gain - real a0, a1, a2, b1, b2; //coefficients - real z1, z2; //second-order IIR + double cutoffFrequency; + double samplingFrequency; + double quality; //frequency response quality + double gain; //peak gain + double a0, a1, a2, b1, b2; //coefficients + double z1, z2; //second-order IIR }; -auto Biquad::reset(Type type, real cutoffFrequency, real samplingFrequency, real quality, real gain) -> void { +auto Biquad::reset(Type type, double cutoffFrequency, double samplingFrequency, double quality, double gain) -> void { this->type = type; this->cutoffFrequency = cutoffFrequency; this->samplingFrequency = samplingFrequency; @@ -42,10 +42,10 @@ auto Biquad::reset(Type type, real cutoffFrequency, real samplingFrequency, real z1 = 0.0; z2 = 0.0; - real v = pow(10, fabs(gain) / 20.0); - real k = tan(Math::Pi * cutoffFrequency / samplingFrequency); - real q = quality; - real n = 0.0; + double v = pow(10, fabs(gain) / 20.0); + double k = tan(Math::Pi * cutoffFrequency / samplingFrequency); + double q = quality; + double n = 0.0; switch(type) { @@ -142,15 +142,15 @@ auto Biquad::reset(Type type, real cutoffFrequency, real samplingFrequency, real } } -auto Biquad::process(real in) -> real { - real out = in * a0 + z1; +auto Biquad::process(double in) -> double { + double out = in * a0 + z1; z1 = in * a1 + z2 - b1 * out; z2 = in * a2 - b2 * out; return out; } //compute Q values for N-order butterworth filtering -auto Biquad::butterworth(uint order, uint phase) -> real { +auto Biquad::butterworth(uint order, uint phase) -> double { return -0.5 / cos(Math::Pi * (phase + order + 0.5) / order); } diff --git a/nall/dsp/iir/one-pole.hpp b/nall/dsp/iir/one-pole.hpp index 74effc0c..99d0a682 100644 --- a/nall/dsp/iir/one-pole.hpp +++ b/nall/dsp/iir/one-pole.hpp @@ -12,24 +12,24 @@ struct OnePole { HighPass, }; - inline auto reset(Type type, real cutoffFrequency, real samplingFrequency) -> void; - inline auto process(real in) -> real; //normalized sample (-1.0 to +1.0) + inline auto reset(Type type, double cutoffFrequency, double samplingFrequency) -> void; + inline auto process(double in) -> double; //normalized sample (-1.0 to +1.0) private: Type type; - real cutoffFrequency; - real samplingFrequency; - real a0, b1; //coefficients - real z1; //first-order IIR + double cutoffFrequency; + double samplingFrequency; + double a0, b1; //coefficients + double z1; //first-order IIR }; -auto OnePole::reset(Type type, real cutoffFrequency, real samplingFrequency) -> void { +auto OnePole::reset(Type type, double cutoffFrequency, double samplingFrequency) -> void { this->type = type; this->cutoffFrequency = cutoffFrequency; this->samplingFrequency = samplingFrequency; z1 = 0.0; - real x = cos(2.0 * Math::Pi * cutoffFrequency / samplingFrequency); + double x = cos(2.0 * Math::Pi * cutoffFrequency / samplingFrequency); if(type == Type::LowPass) { b1 = +2.0 - x - sqrt((+2.0 - x) * (+2.0 - x) - 1); a0 = 1.0 - b1; @@ -39,7 +39,7 @@ auto OnePole::reset(Type type, real cutoffFrequency, real samplingFrequency) -> } } -auto OnePole::process(real in) -> real { +auto OnePole::process(double in) -> double { return z1 = in * a0 + z1 * b1; } diff --git a/nall/dsp/resampler/cubic.hpp b/nall/dsp/resampler/cubic.hpp index 66a909de..0d7a719a 100644 --- a/nall/dsp/resampler/cubic.hpp +++ b/nall/dsp/resampler/cubic.hpp @@ -6,23 +6,23 @@ namespace nall { namespace DSP { namespace Resampler { struct Cubic { - inline auto reset(real inputFrequency, real outputFrequency, uint queueSize = 0) -> void; - inline auto setInputFrequency(real inputFrequency) -> void; + inline auto reset(double inputFrequency, double outputFrequency, uint queueSize = 0) -> void; + inline auto setInputFrequency(double inputFrequency) -> void; inline auto pending() const -> bool; - inline auto read() -> real; - inline auto write(real sample) -> void; + inline auto read() -> double; + inline auto write(double sample) -> void; private: - real inputFrequency; - real outputFrequency; + double inputFrequency; + double outputFrequency; - real ratio; - real fraction; - real history[4]; - queue samples; + double ratio; + double fraction; + double history[4]; + queue samples; }; -auto Cubic::reset(real inputFrequency, real outputFrequency, uint queueSize) -> void { +auto Cubic::reset(double inputFrequency, double outputFrequency, uint queueSize) -> void { this->inputFrequency = inputFrequency; this->outputFrequency = outputFrequency; if(!queueSize) queueSize = outputFrequency * 0.02; //20ms @@ -33,7 +33,7 @@ auto Cubic::reset(real inputFrequency, real outputFrequency, uint queueSize) -> samples.resize(queueSize); } -auto Cubic::setInputFrequency(real inputFrequency) -> void { +auto Cubic::setInputFrequency(double inputFrequency) -> void { this->inputFrequency = inputFrequency; ratio = inputFrequency / outputFrequency; } @@ -42,11 +42,11 @@ auto Cubic::pending() const -> bool { return samples.pending(); } -auto Cubic::read() -> real { +auto Cubic::read() -> double { return samples.read(); } -auto Cubic::write(real sample) -> void { +auto Cubic::write(double sample) -> void { auto& mu = fraction; auto& s = history; @@ -56,10 +56,10 @@ auto Cubic::write(real sample) -> void { s[3] = sample; while(mu <= 1.0) { - real A = s[3] - s[2] - s[0] + s[1]; - real B = s[0] - s[1] - A; - real C = s[2] - s[0]; - real D = s[1]; + double A = s[3] - s[2] - s[0] + s[1]; + double B = s[0] - s[1] - A; + double C = s[2] - s[0]; + double D = s[1]; samples.write(A * mu * mu * mu + B * mu * mu + C * mu + D); mu += ratio; diff --git a/nall/emulation/21fx.hpp b/nall/emulation/21fx.hpp index 03d451a4..1cb18e3f 100644 --- a/nall/emulation/21fx.hpp +++ b/nall/emulation/21fx.hpp @@ -17,7 +17,7 @@ using uint32 = Natural<32>; using uint64 = Natural<64>; struct FX { - auto open(string_vector& args) -> bool; + auto open(vector& arguments) -> bool; auto close() -> void; auto readable() -> bool; auto read() -> uint8_t; @@ -35,12 +35,12 @@ struct FX { serial device; }; -auto FX::open(string_vector& args) -> bool { +auto FX::open(vector& arguments) -> bool { //device name override support string name; - for(uint n : range(args)) { - if(args[n].beginsWith("--device=")) { - name = args.take(n).trimLeft("--device=", 1L); + for(uint n : range(arguments)) { + if(arguments[n].beginsWith("--device=")) { + name = arguments.take(n).trimLeft("--device=", 1L); break; } } diff --git a/nall/encode/zip.hpp b/nall/encode/zip.hpp index 20fa4635..dcd0f28e 100644 --- a/nall/encode/zip.hpp +++ b/nall/encode/zip.hpp @@ -10,25 +10,23 @@ namespace nall { namespace Encode { struct ZIP { ZIP(const string& filename) { fp.open(filename, file::mode::write); - time_t currentTime = time(nullptr); - tm* info = localtime(¤tTime); - dosTime = (info->tm_hour << 11) | (info->tm_min << 5) | (info->tm_sec >> 1); - dosDate = ((info->tm_year - 80) << 9) | ((1 + info->tm_mon) << 5) + (info->tm_mday); + timestamp = time(nullptr); } //append path: append("path/"); //append file: append("path/file", data, size); - auto append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) -> void { + auto append(string filename, const uint8_t* data = nullptr, uint size = 0u, time_t timestamp = 0) -> void { filename.transform("\\", "/"); + if(!timestamp) timestamp = this->timestamp; uint32_t checksum = Hash::CRC32(data, size).digest().hex(); - directory.append({filename, checksum, size, fp.offset()}); + directory.append({filename, timestamp, checksum, size, fp.offset()}); fp.writel(0x04034b50, 4); //signature fp.writel(0x0014, 2); //minimum version (2.0) fp.writel(0x0000, 2); //general purpose bit flags fp.writel(0x0000, 2); //compression method (0 = uncompressed) - fp.writel(dosTime, 2); - fp.writel(dosDate, 2); + fp.writel(makeTime(timestamp), 2); + fp.writel(makeDate(timestamp), 2); fp.writel(checksum, 4); fp.writel(size, 4); //compressed size fp.writel(size, 4); //uncompressed size @@ -41,15 +39,15 @@ struct ZIP { ~ZIP() { //central directory - unsigned baseOffset = fp.offset(); + uint baseOffset = fp.offset(); for(auto& entry : directory) { fp.writel(0x02014b50, 4); //signature fp.writel(0x0014, 2); //version made by (2.0) fp.writel(0x0014, 2); //version needed to extract (2.0) fp.writel(0x0000, 2); //general purpose bit flags fp.writel(0x0000, 2); //compression method (0 = uncompressed) - fp.writel(dosTime, 2); - fp.writel(dosDate, 2); + fp.writel(makeTime(entry.timestamp), 2); + fp.writel(makeDate(entry.timestamp), 2); fp.writel(entry.checksum, 4); fp.writel(entry.size, 4); //compressed size fp.writel(entry.size, 4); //uncompressed size @@ -62,7 +60,7 @@ struct ZIP { fp.writel(entry.offset, 4); //relative offset of file header fp.print(entry.filename); } - unsigned finishOffset = fp.offset(); + uint finishOffset = fp.offset(); //end of central directory fp.writel(0x06054b50, 4); //signature @@ -78,10 +76,21 @@ struct ZIP { } protected: + auto makeTime(time_t timestamp) -> uint16_t { + tm* info = localtime(×tamp); + return (info->tm_hour << 11) | (info->tm_min << 5) | (info->tm_sec >> 1); + } + + auto makeDate(time_t timestamp) -> uint16_t { + tm* info = localtime(×tamp); + return ((info->tm_year - 80) << 9) | ((1 + info->tm_mon) << 5) + (info->tm_mday); + } + file fp; - uint16_t dosTime, dosDate; + time_t timestamp; struct entry_t { string filename; + time_t timestamp; uint32_t checksum; uint32_t size; uint32_t offset; diff --git a/nall/string.hpp b/nall/string.hpp index 9b48fc9c..51ec1a75 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -27,10 +27,6 @@ namespace nall { struct string; struct string_format; -//temporary compatibility shim -using string_vector = vector; -using string_view = view; - template<> struct view { using type = view; @@ -57,8 +53,6 @@ protected: mutable int _size; }; -//using string_view = view; - #define NALL_STRING_ALLOCATOR_ADAPTIVE //#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE //#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION diff --git a/nall/vector.hpp b/nall/vector.hpp index 5312ab71..11563e68 100644 --- a/nall/vector.hpp +++ b/nall/vector.hpp @@ -68,6 +68,12 @@ struct vector_base { alwaysinline auto right() -> T&; alwaysinline auto right() const -> const T&; + alwaysinline auto first() -> T& { return left(); } + alwaysinline auto first() const -> const T& { return left(); } + + alwaysinline auto last() -> T& { return right(); } + alwaysinline auto last() const -> const T& { return right(); } + //modify.hpp auto prepend(const T& value) -> void; auto prepend(T&& value) -> void; diff --git a/nall/windows/registry.hpp b/nall/windows/registry.hpp index aad2a32c..09e1b96f 100644 --- a/nall/windows/registry.hpp +++ b/nall/windows/registry.hpp @@ -79,8 +79,8 @@ struct registry { return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS; } - static auto contents(const string& name) -> string_vector { - string_vector result; + static auto contents(const string& name) -> vector { + vector result; auto part = name.split("\\"); HKEY handle, rootKey = root(part.takeLeft()); part.removeRight(); diff --git a/ruby/audio.cpp b/ruby/audio.cpp index 231cfdc9..8b13e451 100644 --- a/ruby/audio.cpp +++ b/ruby/audio.cpp @@ -150,6 +150,16 @@ auto Audio::create(string driver) -> Audio* { #endif if(!audio) audio = new Audio; + + audio->_exclusive = audio->exclusive(); + audio->_context = audio->context(); + audio->_device = audio->defaultDevice(); + audio->_blocking = audio->blocking(); + audio->_dynamic = audio->dynamic(); + audio->_channels = audio->defaultChannels(); + audio->_frequency = audio->defaultFrequency(); + audio->_latency = audio->defaultLatency(); + return audio; } diff --git a/ruby/audio.hpp b/ruby/audio.hpp index 861a4be9..37699b62 100644 --- a/ruby/audio.hpp +++ b/ruby/audio.hpp @@ -9,11 +9,6 @@ struct Audio { virtual auto driver() -> string { return "None"; } virtual auto ready() -> bool { return true; } - virtual auto availableDevices() -> vector { return {"Default"}; } - virtual auto availableChannels() -> vector { return {2}; } - virtual auto availableFrequencies() -> vector { return {48000.0}; } - virtual auto availableLatencies() -> vector { return {0}; } - virtual auto hasExclusive() -> bool { return false; } virtual auto hasContext() -> bool { return false; } virtual auto hasDevice() -> bool { return false; } @@ -23,6 +18,16 @@ struct Audio { virtual auto hasFrequency() -> bool { return false; } virtual auto hasLatency() -> bool { return false; } + virtual auto availableDevices() -> vector { return {"Default"}; } + virtual auto availableChannels() -> vector { return {2}; } + virtual auto availableFrequencies() -> vector { return {48000.0}; } + virtual auto availableLatencies() -> vector { return {0}; } + + virtual auto defaultDevice() -> string { return availableDevices().first(); } + virtual auto defaultChannels() -> uint { return availableChannels().first(); } + virtual auto defaultFrequency() -> double { return availableFrequencies().first(); } + virtual auto defaultLatency() -> uint { return availableLatencies().first(); } + virtual auto exclusive() -> bool { return _exclusive; } virtual auto context() -> uintptr { return _context; } virtual auto device() -> string { return _device; } diff --git a/ruby/audio/alsa.cpp b/ruby/audio/alsa.cpp index 444be473..6d780b72 100644 --- a/ruby/audio/alsa.cpp +++ b/ruby/audio/alsa.cpp @@ -4,13 +4,14 @@ struct AudioALSA : Audio { AudioALSA() { initialize(); } ~AudioALSA() { terminate(); } - auto driver() -> string override { - return "ALSA"; - } + auto driver() -> string override { return "ALSA"; } + auto ready() -> bool override { return _ready; } - auto ready() -> bool override { - return _ready; - } + auto hasDevice() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasChannels() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } auto availableDevices() -> vector override { return queryDevices(); @@ -28,48 +29,48 @@ struct AudioALSA : Audio { return {20, 40, 60, 80, 100}; } - auto hasDevice() -> bool override { return true; } - auto hasBlocking() -> bool override { return true; } - auto hasChannels() -> bool override { return true; } - auto hasFrequency() -> bool override { return true; } - auto hasLatency() -> bool override { return true; } - auto setDevice(string device) -> bool override { - if(device == this->device()) return true; + if(device == Audio::device()) return true; if(!Audio::setDevice(device)) return false; return initialize(); } auto setBlocking(bool blocking) -> bool override { - if(blocking == this->blocking()) return true; + if(blocking == Audio::blocking()) return true; if(!Audio::setBlocking(blocking)) return false; return true; } auto setChannels(uint channels) -> bool override { - if(channels == this->channels()) return true; + if(channels == Audio::channels()) return true; if(!Audio::setChannels(channels)) return false; return true; } auto setFrequency(double frequency) -> bool override { - if(frequency == this->frequency()) return true; + if(frequency == Audio::frequency()) return true; if(!Audio::setFrequency(frequency)) return false; return initialize(); } auto setLatency(uint latency) -> bool override { - if(latency == this->latency()) return true; + if(latency == Audio::latency()) return true; if(!Audio::setLatency(latency)) return false; return initialize(); } + auto level() -> double override { + snd_pcm_sframes_t available = snd_pcm_avail_update(_interface); + if(available < 0) return 0.5; + return (double)(_bufferSize - available) / _bufferSize; + } + auto output(const double samples[]) -> void override { if(!ready()) return; _buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; _buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16; - if(++_offset < _periodSize) return; + _offset++; snd_pcm_sframes_t available; do { @@ -118,7 +119,7 @@ private: uint rate = (uint)_frequency; uint bufferTime = _latency * 1000; - uint periodTime = _latency * 1000 / 4; + uint periodTime = _latency * 1000 / 8; snd_pcm_hw_params_t* hardwareParameters; snd_pcm_hw_params_alloca(&hardwareParameters); @@ -138,9 +139,7 @@ private: snd_pcm_sw_params_t* softwareParameters; snd_pcm_sw_params_alloca(&softwareParameters); if(snd_pcm_sw_params_current(_interface, softwareParameters) < 0) return terminate(), false; - if(snd_pcm_sw_params_set_start_threshold(_interface, softwareParameters, - (_bufferSize / _periodSize) * _periodSize) < 0 - ) return terminate(), false; + if(snd_pcm_sw_params_set_start_threshold(_interface, softwareParameters, _bufferSize / 2) < 0) return terminate(), false; if(snd_pcm_sw_params(_interface, softwareParameters) < 0) return terminate(), false; _buffer = new uint32_t[_periodSize](); @@ -163,8 +162,8 @@ private: } } - auto queryDevices() -> string_vector { - string_vector devices; + auto queryDevices() -> vector { + vector devices; char** list; if(snd_device_name_hint(-1, "pcm", (void***)&list) == 0) { diff --git a/ruby/audio/ao.cpp b/ruby/audio/ao.cpp index 839fa4b3..8a4a19fa 100644 --- a/ruby/audio/ao.cpp +++ b/ruby/audio/ao.cpp @@ -4,41 +4,29 @@ struct AudioAO : Audio { AudioAO() { initialize(); } ~AudioAO() { terminate(); } - auto availableDevices() -> string_vector { - return {"Default"}; - } + auto driver() -> string override { return "libao"; } + auto ready() -> bool override { return _ready; } - auto availableFrequencies() -> vector { + auto hasFrequencies() -> bool override { return true; } + + auto availableFrequencies() -> vector override { 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; } - auto latency() -> uint { return 100; } - - auto setFrequency(double frequency) -> bool { - if(_frequency == frequency) return true; - _frequency = frequency; + auto setFrequency(double frequency) -> bool override { + if(frequency == Audio::frequency()) return true; + if(!Audio::setFrequency(frequency)) return false; return initialize(); } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { uint32_t sample = 0; sample |= (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; sample |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16; ao_play(_interface, (char*)&sample, 4); } +private: auto initialize() -> bool { terminate(); @@ -56,10 +44,10 @@ struct AudioAO : Audio { ao_info* information = ao_driver_info(driverID); if(!information) return false; - _device = information->short_name; + string device = information->short_name; ao_option* options = nullptr; - if(_device == "alsa") { + if(device == "alsa") { ao_append_option(&options, "buffer_time", "100000"); //100ms latency (default was 500ms) } @@ -79,8 +67,6 @@ struct AudioAO : Audio { } bool _ready = false; - string _device = "Default"; - double _frequency = 48000.0; ao_device* _interface = nullptr; }; diff --git a/ruby/audio/asio.cpp b/ruby/audio/asio.cpp index 6f46a3e2..ed40bd7b 100644 --- a/ruby/audio/asio.cpp +++ b/ruby/audio/asio.cpp @@ -5,17 +5,31 @@ struct AudioASIO : Audio { AudioASIO() { self = this; initialize(); } ~AudioASIO() { terminate(); } - auto availableDevices() -> string_vector { - string_vector devices; + auto driver() -> string override { return "ASIO"; } + auto ready() -> bool override { return _ready; } + + auto hasContext() -> bool override { return true; } + auto hasDevice() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasChannels() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } + + auto availableDevices() -> vector override { + vector devices; for(auto& device : _devices) devices.append(device.name); return devices; } - auto availableFrequencies() -> vector { + auto availableChannels() -> vector override { + return {1, 2}; + } + + auto availableFrequencies() -> vector override { return {_frequency}; } - auto availableLatencies() -> vector { + auto availableLatencies() -> vector override { vector latencies; uint latencyList[] = {64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 6144}; //factors of 6144 for(auto& latency : latencyList) { @@ -26,49 +40,37 @@ struct AudioASIO : Audio { 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; } - auto channels() -> uint { return _channels; } - auto frequency() -> double { return _frequency; } - auto latency() -> uint { return _latency; } - - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Audio::context()) return true; + if(!Audio::setContext(context)) return false; return initialize(); } - auto setDevice(string device) -> bool { - if(_device == device) return true; - _device = device; + auto setDevice(string device) -> bool override { + if(device == Audio::device()) return true; + if(!Audio::setDevice(device)) return false; return initialize(); } - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Audio::blocking()) return true; + if(!Audio::setBlocking(blocking)) return false; return initialize(); } - auto setChannels(uint channels) -> bool { - if(_channels == channels) return true; - _channels = channels; + auto setChannels(uint channels) -> bool override { + if(channels == Audio::channels()) return true; + if(!Audio::setChannels(channels)) return false; return initialize(); } - auto setLatency(uint latency) -> bool { - if(_latency == latency) return true; - _latency = latency; + auto setLatency(uint latency) -> bool override { + if(latency == Audio::latency()) return true; + if(!Audio::setLatency(latency)) return false; return initialize(); } - auto clear() -> void { + auto clear() -> void override { if(!ready()) return; for(uint n : range(_channels)) { memory::fill(_channel[n].buffers[0], _latency * _sampleSize); @@ -80,7 +82,7 @@ struct AudioASIO : Audio { _queue.count = 0; } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { if(!ready()) return; if(_blocking) { while(_queue.count >= _latency); @@ -251,12 +253,6 @@ private: } bool _ready = false; - uintptr _context = 0; - string _device; - bool _blocking = true; - uint _channels = 2; - double _frequency = 48000.0; - uint _latency = 0; struct Queue { double samples[65536][8]; diff --git a/ruby/audio/directsound.cpp b/ruby/audio/directsound.cpp index 1888f24f..203e43a6 100644 --- a/ruby/audio/directsound.cpp +++ b/ruby/audio/directsound.cpp @@ -4,47 +4,40 @@ struct AudioDirectSound : Audio { AudioDirectSound() { initialize(); } ~AudioDirectSound() { terminate(); } - auto availableDevices() -> string_vector { - return {"Default"}; - } + auto driver() -> string override { return "DirectSound"; } + auto ready() -> bool override { return _ready; } - auto availableFrequencies() -> vector { + auto hasBlocking() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } + + auto availableFrequencies() -> vector override { return {44100.0, 48000.0, 96000.0}; } - auto availableLatencies() -> vector { + auto availableLatencies() -> vector override { 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; } - auto latency() -> uint { return _latency; } - - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Audio::blocking()) return true; + if(!Audio::setBlocking(blocking)) return false; return true; } - auto setFrequency(double frequency) -> bool { - if(_frequency == frequency) return true; - _frequency = frequency; + auto setFrequency(double frequency) -> bool override { + if(frequency == Audio::frequency()) return true; + if(!Audio::setFrequency(frequency)) return false; return initialize(); } - auto setLatency(uint latency) -> bool { - if(_latency == latency) return true; - _latency = latency; + auto setLatency(uint latency) -> bool override { + if(latency == Audio::latency()) return true; + if(!Audio::setLatency(latency)) return false; return initialize(); } - auto clear() -> void { + auto clear() -> void override { if(!ready()) return; _ringRead = 0; @@ -67,7 +60,7 @@ struct AudioDirectSound : Audio { _secondary->Play(0, 0, DSBPLAY_LOOPING); } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { if(!ready()) return; _buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; @@ -159,10 +152,6 @@ private: } bool _ready = false; - bool _blocking = true; - uint _channels = 2; - double _frequency = 48000.0; - uint _latency = 40; LPDIRECTSOUND _interface = nullptr; LPDIRECTSOUNDBUFFER _primary = nullptr; diff --git a/ruby/audio/openal.cpp b/ruby/audio/openal.cpp index 794a9f3f..27071858 100644 --- a/ruby/audio/openal.cpp +++ b/ruby/audio/openal.cpp @@ -10,13 +10,14 @@ struct AudioOpenAL : Audio { AudioOpenAL() { initialize(); } ~AudioOpenAL() { terminate(); } - auto driver() -> string override { - return "OpenAL"; - } + auto driver() -> string override { return "OpenAL"; } + auto ready() -> bool override { return _ready; } - auto ready() -> bool override { - return _ready; - } + auto hasDevice() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasChannels() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } auto availableDevices() -> vector override { vector devices; @@ -36,12 +37,6 @@ struct AudioOpenAL : Audio { return {20, 40, 60, 80, 100}; } - auto hasDevice() -> bool override { return true; } - auto hasBlocking() -> bool override { return true; } - auto hasChannels() -> bool override { return true; } - auto hasFrequency() -> bool override { return true; } - auto hasLatency() -> bool override { return true; } - auto setDevice(string device) -> bool override { if(device == this->device()) return true; if(!Audio::setDevice(device)) return false; diff --git a/ruby/audio/oss.cpp b/ruby/audio/oss.cpp index c17958f8..d20869ad 100644 --- a/ruby/audio/oss.cpp +++ b/ruby/audio/oss.cpp @@ -17,13 +17,15 @@ struct AudioOSS : Audio { AudioOSS() { initialize(); } ~AudioOSS() { terminate(); } - auto driver() -> string override { - return "OSS"; - } + auto driver() -> string override { return "OSS"; } + auto ready() -> bool override { return _fd >= 0; } - auto ready() -> bool override { - return _fd >= 0; - } + auto hasDevice() -> bool override { return true; } + auto hasDynamic() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasChannels() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } auto availableDevices() -> vector override { vector devices; @@ -32,6 +34,10 @@ struct AudioOSS : Audio { return devices; } + auto defaultChannels() -> uint override { return 2; } + auto defaultFrequency() -> double override { return 48000.0; } + auto defaultLatency() -> uint override { return 3; } + auto availableChannels() -> vector override { return {1, 2}; } @@ -44,45 +50,38 @@ struct AudioOSS : Audio { return {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; } - auto hasDevice() -> bool override { return true; } - auto hasDynamic() -> bool override { return true; } - auto hasBlocking() -> bool override { return true; } - auto hasChannels() -> bool override { return true; } - auto hasFrequency() -> bool override { return true; } - auto hasLatency() -> bool override { return true; } - auto setDevice(string device) -> bool override { - if(device == this->device()) return true; + if(device == Audio::device()) return true; if(!Audio::setDevice(device)) return false; return initialize(); } auto setBlocking(bool blocking) -> bool override { - if(blocking == this->blocking()) return true; + if(blocking == Audio::blocking()) return true; if(!Audio::setBlocking(blocking)) return false; return updateBlocking(); } auto setDynamic(bool dynamic) -> bool override { - if(dynamic == this->dynamic()) return true; + if(dynamic == Audio::dynamic()) return true; if(!Audio::setDynamic(dynamic)) return false; return true; } auto setChannels(uint channels) -> bool override { - if(channels == this->channels()) return true; + if(channels == Audio::channels()) return true; if(!Audio::setChannels(channels)) return false; return initialize(); } auto setFrequency(double frequency) -> bool override { - if(frequency == this->frequency()) return true; + if(frequency == Audio::frequency()) return true; if(!Audio::setFrequency(frequency)) return false; return initialize(); } auto setLatency(uint latency) -> bool override { - if(latency == this->latency()) return true; + if(latency == Audio::latency()) return true; if(!Audio::setLatency(latency)) return false; return initialize(); } @@ -169,5 +168,5 @@ private: int _bufferSize = 1; uint _outputOffset = 0; - uint16_t _outputBuffer[256]; + uint16_t _outputBuffer[64]; }; diff --git a/ruby/audio/pulseaudio.cpp b/ruby/audio/pulseaudio.cpp index 1f7866e3..b48e2ada 100644 --- a/ruby/audio/pulseaudio.cpp +++ b/ruby/audio/pulseaudio.cpp @@ -4,47 +4,40 @@ struct AudioPulseAudio : Audio { AudioPulseAudio() { initialize(); } ~AudioPulseAudio() { terminate(); } - auto availableDevices() -> string_vector { - return {"Default"}; - } + auto driver() -> string override { return "PulseAudio"; } + auto ready() -> bool override { return _ready; } - auto availableFrequencies() -> vector { + auto hasBlocking() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } + + auto availableFrequencies() -> vector override { return {44100.0, 48000.0, 96000.0}; } - auto availableLatencies() -> vector { + auto availableLatencies() -> vector override { 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; } - auto latency() -> uint { return _latency; } - - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Audio::blocking()) return true; + if(!Audio::setBlocking(blocking)) return false; return true; } - auto setFrequency(double frequency) -> bool { - if(_frequency == frequency) return true; - _frequency = frequency; + auto setFrequency(double frequency) -> bool override { + if(frequency == Audio::frequency()) return true; + if(!Audio::setFrequency(frequency)) return false; return initialize(); } - auto setLatency(uint latency) -> bool { - if(_latency == latency) return true; - _latency = latency; + auto setLatency(uint latency) -> bool override { + if(latency == Audio::latency()) return true; + if(!Audio::setLatency(latency)) return false; return initialize(); } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { pa_stream_begin_write(_stream, (void**)&_buffer, &_period); _buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; _buffer[_offset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16; @@ -140,9 +133,6 @@ private: } bool _ready = false; - bool _blocking = true; - double _frequency = 48000.0; - uint _latency = 40; uint32_t* _buffer = nullptr; size_t _period = 0; diff --git a/ruby/audio/pulseaudiosimple.cpp b/ruby/audio/pulseaudiosimple.cpp index b0f0a498..c7347d0b 100644 --- a/ruby/audio/pulseaudiosimple.cpp +++ b/ruby/audio/pulseaudiosimple.cpp @@ -5,35 +5,22 @@ struct AudioPulseAudioSimple : Audio { AudioPulseAudioSimple() { initialize(); } ~AudioPulseAudioSimple() { terminate(); } - auto availableDevices() -> string_vector { - return {"Default"}; - } + auto driver() -> string override { return "PulseAudioSimple"; } + auto ready() -> bool override { return _ready; } - auto availableFrequencies() -> vector { + auto hasFrequency() -> bool override { return true; } + + auto availableFrequencies() -> vector override { 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; } - auto latency() -> uint { return 40; } - - auto setFrequency(double frequency) -> bool { - if(_frequency == frequency) return true; - _frequency = frequency; + auto setFrequency(double frequency) -> bool override { + if(frequency == Audio::frequency()) return true; + if(!Audio::setFrequency(frequency)) return false; return initialize(); } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { if(!ready()) return; _buffer[_offset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; @@ -90,7 +77,6 @@ private: } bool _ready = false; - double _frequency = 48000.0; pa_simple* _interface = nullptr; diff --git a/ruby/audio/wasapi.cpp b/ruby/audio/wasapi.cpp index d62b58f5..691635c2 100644 --- a/ruby/audio/wasapi.cpp +++ b/ruby/audio/wasapi.cpp @@ -10,61 +10,58 @@ struct AudioWASAPI : Audio { AudioWASAPI() { initialize(); } ~AudioWASAPI() { terminate(); } - auto availableDevices() -> string_vector { + auto driver() -> string override { return "WASAPI"; } + auto ready() -> bool override { return _ready; } + + auto hasExclusive() -> bool override { return true; } + auto hasDevice() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } + + auto availableDevices() -> vector override { return _devices; } - auto availableFrequencies() -> vector { - return {(double)_frequency}; + auto availableFrequencies() -> vector override { + return {_frequency}; } - auto availableLatencies() -> vector { + auto availableLatencies() -> vector override { 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; } - auto channels() -> uint { return _channels; } - auto frequency() -> double { return (double)_frequency; } - auto latency() -> uint { return _latency; } - - auto setExclusive(bool exclusive) -> bool { - if(_exclusive == exclusive) return true; - _exclusive = exclusive; + auto setExclusive(bool exclusive) -> bool override { + if(exclusive == Audio::exclusive()) return true; + if(!Audio::setExclusive(exclusive)) return false; return initialize(); } - auto setDevice(string device) -> bool { - if(_device == device) return true; - _device = device; + auto setDevice(string device) -> bool override { + if(device == Audio::device()) return true; + if(!Audio::setDevice(device)) return false; return initialize(); } - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Audio::blocking()) return true; + if(!Audio::setBlocking(blocking)) return false; return true; } - auto setFrequency(double frequency) -> bool { - if(_frequency == frequency) return true; - _frequency = frequency; + auto setFrequency(double frequency) -> bool override { + if(frequency == Audio::frequency()) return true; + if(!Audio::setFrequency(frequency)) return false; return initialize(); } - auto setLatency(uint latency) -> bool { - if(_latency == latency) return true; - _latency = latency; + auto setLatency(uint latency) -> bool override { + if(latency == Audio::latency()) return true; + if(!Audio::setLatency(latency)) return false; return initialize(); } - auto clear() -> void { + auto clear() -> void override { if(!ready()) return; _queue.read = 0; _queue.write = 0; @@ -74,7 +71,7 @@ struct AudioWASAPI : Audio { _audioClient->Start(); } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { if(!ready()) return; for(uint n : range(_channels)) { @@ -227,12 +224,6 @@ private: } bool _ready = false; - bool _exclusive = false; - string _device; - bool _blocking = true; - uint _channels = 2; - uint _frequency = 48000; - uint _latency = 20; uint _mode = 0; uint _precision = 0; @@ -245,7 +236,7 @@ private: } _queue; IMMDeviceEnumerator* _enumerator = nullptr; - string_vector _devices; + vector _devices; IMMDevice* _audioDevice = nullptr; IAudioClient* _audioClient = nullptr; IAudioRenderClient* _renderClient = nullptr; diff --git a/ruby/audio/xaudio2.cpp b/ruby/audio/xaudio2.cpp index 75675b64..d3f80e5f 100644 --- a/ruby/audio/xaudio2.cpp +++ b/ruby/audio/xaudio2.cpp @@ -5,47 +5,40 @@ struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback { AudioXAudio2() { initialize(); } ~AudioXAudio2() { terminate(); } - auto availableDevices() -> string_vector { - return {"Default"}; - } + auto driver() -> string override { return "XAudio2"; } + auto ready() -> bool override { return _ready; } - auto availableFrequencies() -> vector { + auto hasBlocking() -> bool override { return true; } + auto hasFrequency() -> bool override { return true; } + auto hasLatency() -> bool override { return true; } + + auto availableFrequencies() -> vector override { return {44100.0, 48000.0, 96000.0}; } - auto availableLatencies() -> vector { + auto availableLatencies() -> vector override { 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; } - auto latency() -> uint { return _latency; } - - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Audio::blocking()) return true; + if(!Audio::setBlocking(blocking)) return false; return true; } - auto setFrequency(double frequency) -> bool { - if(_frequency == frequency) return true; - _frequency = frequency; + auto setFrequency(double frequency) -> bool override { + if(frequency == Audio::frequency()) return true; + if(!Audio::setFrequency(frequency)) return false; return initialize(); } - auto setLatency(uint latency) -> bool { - if(_latency == latency) return true; - _latency = latency; + auto setLatency(uint latency) -> bool override { + if(latency == Audio::latency()) return true; + if(!Audio::setLatency(latency)) return false; return initialize(); } - auto clear() -> void { + auto clear() -> void override { if(!_sourceVoice) return; _sourceVoice->Stop(0); _sourceVoice->FlushSourceBuffers(); //calls OnBufferEnd for all currently submitted buffers @@ -58,7 +51,7 @@ struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback { _sourceVoice->Start(0); } - auto output(const double samples[]) -> void { + auto output(const double samples[]) -> void override { _buffer[_bufferIndex * _period + _bufferOffset] = (uint16_t)sclamp<16>(samples[0] * 32767.0) << 0; _buffer[_bufferIndex * _period + _bufferOffset] |= (uint16_t)sclamp<16>(samples[1] * 32767.0) << 16; if(++_bufferOffset < _period) return; @@ -151,10 +144,6 @@ private: } bool _ready = false; - bool _blocking = true; - uint _channels = 2; - double _frequency = 48000.0; - uint _latency = 80; uint32_t* _buffer = nullptr; uint _period = 0; diff --git a/ruby/input.cpp b/ruby/input.cpp index 87858ba8..accf2db4 100644 --- a/ruby/input.cpp +++ b/ruby/input.cpp @@ -70,6 +70,9 @@ auto Input::create(string driver) -> Input* { #endif if(!input) input = new Input; + + input->_context = input->context(); + return input; } diff --git a/ruby/input/carbon.cpp b/ruby/input/carbon.cpp index c645a9b2..1df09e18 100644 --- a/ruby/input/carbon.cpp +++ b/ruby/input/carbon.cpp @@ -4,19 +4,20 @@ struct InputCarbon : Input { InputCarbon() : _keyboard(*this) { initialize(); } ~InputCarbon() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "Carbon"; } + auto ready() -> bool override { return _ready; } - auto acquired() -> bool { return false; } - auto acquire() -> bool { return false; } - auto release() -> bool { return false; } + auto acquired() -> bool override { return false; } + auto acquire() -> bool override { return false; } + auto release() -> bool override { return false; } - auto poll() -> vector> { + auto poll() -> vector> override { vector> devices; _keyboard.poll(devices); return devices; } - auto rumble(uint64 id, bool enable) -> bool { + auto rumble(uint64_t id, bool enable) -> bool override { return false; } diff --git a/ruby/input/quartz.cpp b/ruby/input/quartz.cpp index e189b2cd..6014f127 100644 --- a/ruby/input/quartz.cpp +++ b/ruby/input/quartz.cpp @@ -4,22 +4,24 @@ struct InputQuartz : Input { InputQuartz() : _keyboard(*this) { initialize(); } ~InputQuartz() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "Quartz"; } + auto ready() -> bool override { return _ready; } - auto acquired() -> bool { return false; } - auto acquire() -> bool { return false; } - auto release() -> bool { return false; } + auto acquired() -> bool override { return false; } + auto acquire() -> bool override { return false; } + auto release() -> bool override { return false; } - auto poll() -> vector> { + auto poll() -> vector> override { vector> devices; _keyboard.poll(devices); return devices; } - auto rumble(uint64 id, bool enable) -> bool { + auto rumble(uint64_t id, bool enable) -> bool override { return false; } +private: auto initialize() -> bool { terminate(); if(!_keyboard.initialize()) return false; diff --git a/ruby/input/sdl.cpp b/ruby/input/sdl.cpp index 1919999f..21547f17 100644 --- a/ruby/input/sdl.cpp +++ b/ruby/input/sdl.cpp @@ -16,7 +16,7 @@ struct InputSDL : Input { auto hasContext() -> bool override { return true; } auto setContext(uintptr context) -> bool override { - if(context == this->context()) return true; + if(context == Input::context()) return true; if(!Input::setContext(context)) return false; return initialize(); } diff --git a/ruby/input/udev.cpp b/ruby/input/udev.cpp index b1842301..139e3d0f 100644 --- a/ruby/input/udev.cpp +++ b/ruby/input/udev.cpp @@ -16,29 +16,30 @@ struct InputUdev : Input { InputUdev() : _keyboard(*this), _mouse(*this), _joypad(*this) { initialize(); } ~InputUdev() { terminate(); } + auto driver() -> string override { return "udev"; } auto ready() -> bool { return _ready; } - auto context() -> uintptr { return _context; } + auto hasContext() -> bool override { return true; } - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Input::context()) return true; + if(!Input::setContext(context)) return false; return initialize(); } - auto acquired() -> bool { + auto acquired() -> bool override { return _mouse.acquired(); } - auto acquire() -> bool { + auto acquire() -> bool override { return _mouse.acquire(); } - auto release() -> bool { + auto release() -> bool override { return _mouse.release(); } - auto poll() -> vector> { + auto poll() -> vector> override { vector> devices; _keyboard.poll(devices); _mouse.poll(devices); @@ -46,7 +47,7 @@ struct InputUdev : Input { return devices; } - auto rumble(uint64_t id, bool enable) -> bool { + auto rumble(uint64_t id, bool enable) -> bool override { return _joypad.rumble(id, enable); } @@ -68,7 +69,6 @@ private: } bool _ready = false; - uintptr _context = 0; InputKeyboardXlib _keyboard; InputMouseXlib _mouse; diff --git a/ruby/input/windows.cpp b/ruby/input/windows.cpp index 63d18945..475270e0 100644 --- a/ruby/input/windows.cpp +++ b/ruby/input/windows.cpp @@ -12,29 +12,30 @@ struct InputWindows : Input { InputWindows() : _keyboard(*this), _mouse(*this), _joypadXInput(*this), _joypadDirectInput(*this) { initialize(); } ~InputWindows() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "Windows"; } + auto ready() -> bool override { return _ready; } - auto context() -> uintptr { return _context; } + auto hasContext() -> bool override { return true; } - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Input::context()) return true; + if(!Input::setContext(context)) return false; return initialize(); } - auto acquired() -> bool { + auto acquired() -> bool override { return _mouse.acquired(); } - auto acquire() -> bool { + auto acquire() -> bool override { return _mouse.acquire(); } - auto release() -> bool { + auto release() -> bool override { return _mouse.release(); } - auto poll() -> vector> { + auto poll() -> vector> override { vector> devices; _keyboard.poll(devices); _mouse.poll(devices); @@ -43,7 +44,7 @@ struct InputWindows : Input { return devices; } - auto rumble(uint64_t id, bool enable) -> bool { + auto rumble(uint64_t id, bool enable) -> bool override { if(_joypadXInput.rumble(id, enable)) return true; if(_joypadDirectInput.rumble(id, enable)) return true; return false; @@ -91,7 +92,6 @@ private: } bool _ready = false; - uintptr _context = 0; InputKeyboardRawInput _keyboard; InputMouseRawInput _mouse; diff --git a/ruby/input/xlib.cpp b/ruby/input/xlib.cpp index a2bd8804..b88d4df9 100644 --- a/ruby/input/xlib.cpp +++ b/ruby/input/xlib.cpp @@ -17,7 +17,7 @@ struct InputXlib : Input { auto hasContext() -> bool override { return true; } auto setContext(uintptr context) -> bool override { - if(context == this->context()) return true; + if(context == Input::context()) return true; if(!Input::setContext(context)) return false; return initialize(); } diff --git a/ruby/ruby.hpp b/ruby/ruby.hpp index 3bf0cee6..d9699078 100644 --- a/ruby/ruby.hpp +++ b/ruby/ruby.hpp @@ -13,6 +13,7 @@ #include #include #include +#include using nall::function; using nall::shared_pointer; diff --git a/ruby/video.cpp b/ruby/video.cpp index a5845510..020a0fb4 100644 --- a/ruby/video.cpp +++ b/ruby/video.cpp @@ -124,6 +124,15 @@ auto Video::create(string driver) -> Video* { #endif if(!video) video = new Video; + + video->_exclusive = video->exclusive(); + video->_context = video->context(); + video->_blocking = video->blocking(); + video->_flush = video->flush(); + video->_format = video->defaultFormat(); + video->_smooth = video->smooth(); + video->_shader = video->shader(); + return video; } diff --git a/ruby/video.hpp b/ruby/video.hpp index 601106e6..f71a1c9f 100644 --- a/ruby/video.hpp +++ b/ruby/video.hpp @@ -9,8 +9,6 @@ struct Video { virtual auto driver() -> string { return "None"; } virtual auto ready() -> bool { return true; } - virtual auto availableFormats() -> vector { return {"Default"}; } - virtual auto hasExclusive() -> bool { return false; } virtual auto hasContext() -> bool { return false; } virtual auto hasBlocking() -> bool { return false; } @@ -19,6 +17,10 @@ struct Video { virtual auto hasSmooth() -> bool { return false; } virtual auto hasShader() -> bool { return false; } + virtual auto availableFormats() -> vector { return {"Default"}; } + + virtual auto defaultFormat() -> string { return availableFormats().first(); } + virtual auto exclusive() -> bool { return _exclusive; } virtual auto context() -> uintptr { return _context; } virtual auto blocking() -> bool { return _blocking; } @@ -36,8 +38,8 @@ struct Video { virtual auto setShader(string shader) -> bool; virtual auto clear() -> void {} - virtual auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { return false; } - virtual auto unlock() -> void {} + virtual auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { return false; } + virtual auto release() -> void {} virtual auto output() -> void {} virtual auto poll() -> void {} diff --git a/ruby/video/cgl.cpp b/ruby/video/cgl.cpp index d7f705b7..7e39655d 100644 --- a/ruby/video/cgl.cpp +++ b/ruby/video/cgl.cpp @@ -15,22 +15,24 @@ struct VideoCGL : Video, OpenGL { VideoCGL() { initialize(); } ~VideoCGL() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "OpenGL"; } + auto ready() -> bool override { return _ready; } - auto context() -> uintptr { return (uintptr)_context; } - auto blocking() -> bool { return _blocking; } - auto smooth() -> bool { return _smooth; } - auto shader() -> string { return _shader; } + auto hasContext() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasFlush() -> bool override { return true; } + auto hasSmooth() -> bool override { return true; } + auto hasShader() -> bool override { return true; } - auto setContext(uintptr context) -> bool { - if(_context == (NSView*)context) return true; - _context = (NSView*)context; + auto setContext(uintptr context) -> bool override { + if(context == Video::context()) return true; + if(!Video::setContext(context)) return false; return initialize(); } - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Video::blocking()) return true; + if(!Video::setBlocking(blocking)) return false; if(!view) return true; @autoreleasepool { [[view openGLContext] makeCurrentContext]; @@ -40,21 +42,28 @@ struct VideoCGL : Video, OpenGL { return true; } - auto setSmooth(bool smooth) -> bool { - if(_smooth == smooth) return true; - _smooth = smooth; - if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST; + auto setFlush(bool flush) -> bool override { + if(flush == Video::flush()) return true; + if(!Video::setFlush(flush)) return false; return true; } - auto setShader(string shader) -> bool { - if(_shader == shader) return true; - OpenGL::shader(_shader = shader); - if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST; + auto setSmooth(bool smooth) -> bool override { + if(smooth == Video::smooth()) return true; + if(!Video::setSmooth(smooth)) return false; + if(!shader()) OpenGL::filter = smooth ? GL_LINEAR : GL_NEAREST; return true; } - auto clear() -> void { + auto setShader(string shader) -> bool override { + if(shader == Video::shader()) return true; + if(!Video::setShader(shader)) return false; + OpenGL::setShader(shader); + if(!shader) OpenGL::filter = smooth() ? GL_LINEAR : GL_NEAREST; + return true; + } + + auto clear() -> void override { if(!ready()) return; @autoreleasepool { [view lockFocus]; @@ -64,17 +73,17 @@ struct VideoCGL : Video, OpenGL { } } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; OpenGL::size(width, height); return OpenGL::lock(data, pitch); } - auto unlock() -> void { + auto release() -> void override { if(!ready()) return; } - auto output() -> void { + auto output() -> void override { if(!ready()) return; @autoreleasepool { if([view lockFocusIfCanDraw]) { @@ -83,6 +92,7 @@ struct VideoCGL : Video, OpenGL { OpenGL::outputHeight = area.size.height; OpenGL::output(); [[view openGLContext] flushBuffer]; + if(flush()) glFinish(); [view unlockFocus]; } } @@ -102,17 +112,18 @@ private: 0 }; - auto size = [_context frame].size; + auto context = (NSView*)_context; + auto size = [context frame].size; auto format = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributeList] autorelease]; - auto context = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease]; + auto openGLContext = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease]; view = [[RubyVideoCGL alloc] initWith:this pixelFormat:format]; - [view setOpenGLContext:context]; + [view setOpenGLContext:openGLContext]; [view setFrame:NSMakeRect(0, 0, size.width, size.height)]; [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [view setWantsBestResolutionOpenGLSurface:YES]; - [_context addSubview:view]; - [context setView:view]; + [context addSubview:view]; + [openGLContext setView:view]; [view lockFocus]; @@ -143,10 +154,6 @@ private: RubyVideoCGL* view = nullptr; bool _ready = false; - NSView* _context = nullptr; - bool _blocking = false; - bool _smooth = true; - string _shader; }; @implementation RubyVideoCGL : NSOpenGLView diff --git a/ruby/video/direct3d.cpp b/ruby/video/direct3d.cpp index 8f637f6b..a357fb26 100644 --- a/ruby/video/direct3d.cpp +++ b/ruby/video/direct3d.cpp @@ -11,37 +11,40 @@ struct VideoDirect3D : Video { VideoDirect3D() { initialize(); } ~VideoDirect3D() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "Direct3D"; } + auto ready() -> bool override { return _ready; } - auto exclusive() -> bool { return _exclusive; } - auto context() -> uintptr { return _context; } - auto blocking() -> bool { return _blocking; } - auto smooth() -> bool { return _smooth; } + auto hasExclusive() -> bool override { return true; } + auto hasContext() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasSmooth() -> bool override { return true; } - auto setExclusive(bool exclusive) -> bool { - if(_exclusive == exclusive) return true; - _exclusive = exclusive; + auto setExclusive(bool exclusive) -> bool override { + if(exclusive == Video::exclusive()) return true; + if(!Video::setExclusive(exclusive)) return false; return initialize(); } - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Video::context()) return true; + if(!Video::setContext(context)) return false; return initialize(); } - auto setBlocking(bool blocking) -> bool { - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Video::blocking()) return true; + if(!Video::setBlocking(blocking)) return false; return true; } - auto setSmooth(bool smooth) -> bool { - _smooth = smooth; - if(_ready) updateFilter(); + auto setSmooth(bool smooth) -> bool override { + if(smooth == Video::smooth()) return true; + if(!Video::setSmooth(smooth)) return false; + if(ready()) updateFilter(); return true; } - auto clear() -> void { + auto clear() -> void override { if(!ready()) return; if(_lost && !recover()) return; @@ -62,7 +65,7 @@ struct VideoDirect3D : Video { } } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; if(_lost && !recover()) return false; @@ -86,14 +89,14 @@ struct VideoDirect3D : Video { return data = (uint32_t*)lockedRectangle.pBits; } - auto unlock() -> void { + auto release() -> void override { if(!ready()) return; _surface->UnlockRect(); _surface->Release(); _surface = nullptr; } - auto output() -> void { + auto output() -> void override { if(!ready()) return; if(_lost && !recover()) return; @@ -327,12 +330,7 @@ private: float u, v; //texture coordinates }; - bool _exclusive = false; bool _ready = false; - uintptr _context = 0; - bool _blocking = false; - bool _smooth = true; - uintptr _exclusiveContext = 0; LPDIRECT3D9 _instance = nullptr; diff --git a/ruby/video/directdraw.cpp b/ruby/video/directdraw.cpp index fd40efce..48261cf6 100644 --- a/ruby/video/directdraw.cpp +++ b/ruby/video/directdraw.cpp @@ -5,24 +5,25 @@ struct VideoDirectDraw : Video { VideoDirectDraw() { initialize(); } ~VideoDirectDraw() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "DirectDraw"; } + auto ready() -> bool override { return _ready; } - auto context() -> uintptr { return _context; } - auto blocking() -> bool { return _blocking; } + auto hasContext() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Video::context()) return true; + if(!Video::setContext(context)) return false; return initialize(); } - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; + auto setBlocking(bool blocking) -> bool override { + if(blocking == Video::blocking()) return true; + if(!Video::setBlocking(blocking)) return false; return true; } - auto clear() -> void { + auto clear() -> void override { if(!ready()) return; DDBLTFX fx = {}; fx.dwSize = sizeof(DDBLTFX); @@ -31,7 +32,7 @@ struct VideoDirectDraw : Video { _raster->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; if(width != _width || height != _height) resize(_width = width, _height = height); DDSURFACEDESC2 description = {}; @@ -44,12 +45,12 @@ struct VideoDirectDraw : Video { return data = (uint32_t*)description.lpSurface; } - auto unlock() -> void { + auto release() -> void override { if(!ready()) return; _raster->Unlock(0); } - auto output() -> void { + auto output() -> void override { if(!ready()) return; if(_blocking) while(true) { BOOL vblank; @@ -152,8 +153,6 @@ private: } bool _ready = false; - uintptr _context = 0; - bool _blocking = false; uint _width = 0; uint _height = 0; diff --git a/ruby/video/gdi.cpp b/ruby/video/gdi.cpp index c1b96cc3..7731f1fd 100644 --- a/ruby/video/gdi.cpp +++ b/ruby/video/gdi.cpp @@ -2,21 +2,22 @@ struct VideoGDI : Video { VideoGDI() { initialize(); } ~VideoGDI() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "GDI"; } + auto ready() -> bool override { return _ready; } - auto context() -> uintptr { return _context; } + auto hasContext() -> bool override { return true; } - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Video::context()) return true; + if(!Video::setContext(context)) return false; return initialize(); } - auto clear() -> void { + auto clear() -> void override { if(!ready()) return; } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; if(!_buffer || _width != width || _height != height) { @@ -48,11 +49,11 @@ struct VideoGDI : Video { return data = _buffer; } - auto unlock() -> void { + auto release() -> void override { if(!ready()) return; } - auto output() -> void { + auto output() -> void override { if(!ready()) return; RECT rc; @@ -82,7 +83,6 @@ private: } bool _ready = false; - uintptr _context = 0; uint32_t* _buffer = nullptr; uint _width = 0; diff --git a/ruby/video/glx.cpp b/ruby/video/glx.cpp index 3699d26a..4b5bf714 100644 --- a/ruby/video/glx.cpp +++ b/ruby/video/glx.cpp @@ -14,10 +14,6 @@ struct VideoGLX : Video, OpenGL { auto driver() -> string override { return "OpenGL"; } auto ready() -> bool override { return _ready; } - auto availableFormats() -> vector override { - return {"R8G8B8", "R10G10B10"}; - } - auto hasContext() -> bool override { return true; } auto hasBlocking() -> bool override { return true; } auto hasFlush() -> bool override { return true; } @@ -25,6 +21,10 @@ struct VideoGLX : Video, OpenGL { auto hasSmooth() -> bool override { return true; } auto hasShader() -> bool override { return true; } + auto availableFormats() -> vector override { + return {"RGB24", "RGB30"}; + } + auto setContext(uintptr context) -> bool override { if(context == Video::context()) return true; if(!Video::setContext(context)) return false; @@ -34,7 +34,7 @@ struct VideoGLX : Video, OpenGL { auto setBlocking(bool blocking) -> bool override { if(blocking == Video::blocking()) return true; if(!Video::setBlocking(blocking)) return false; - if(glXSwapInterval) glXSwapInterval(_blocking); + if(glXSwapInterval) glXSwapInterval(blocking); return true; } @@ -48,12 +48,12 @@ struct VideoGLX : Video, OpenGL { if(format == Video::format()) return true; if(!Video::setFormat(format)) return false; - if(format == "R8G8B8") { + if(format == "RGB24") { OpenGL::inputFormat = GL_RGBA8; return true; } - if(format == "R10G10B10") { + if(format == "RGB30") { OpenGL::inputFormat = GL_RGB10_A2; return true; } @@ -82,13 +82,13 @@ struct VideoGLX : Video, OpenGL { if(_doubleBuffer) glXSwapBuffers(_display, _glXWindow); } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; OpenGL::size(width, height); return OpenGL::lock(data, pitch); } - auto unlock() -> void override { + auto release() -> void override { if(!ready()) return; } @@ -140,9 +140,9 @@ private: XWindowAttributes windowAttributes; XGetWindowAttributes(_display, (Window)_context, &windowAttributes); - int redDepth = Video::format() == "R10G10B10" ? 10 : 8; - int greenDepth = Video::format() == "R10G10B10" ? 10 : 8; - int blueDepth = Video::format() == "R10G10B10" ? 10 : 8; + int redDepth = Video::format() == "RGB30" ? 10 : 8; + int greenDepth = Video::format() == "RGB30" ? 10 : 8; + int blueDepth = Video::format() == "RGB30" ? 10 : 8; //let GLX determine the best Visual to use for GL output; provide a few hints //note: some video drivers will override double buffering attribute diff --git a/ruby/video/glx2.cpp b/ruby/video/glx2.cpp index f5a6b5ac..37a2246f 100644 --- a/ruby/video/glx2.cpp +++ b/ruby/video/glx2.cpp @@ -31,29 +31,51 @@ struct VideoGLX2 : Video { auto hasContext() -> bool override { return true; } auto hasBlocking() -> bool override { return true; } auto hasFlush() -> bool override { return true; } + auto hasFormat() -> bool override { return true; } auto hasSmooth() -> bool override { return true; } + auto availableFormats() -> vector override { + return {"RGB24", "RGB30"}; + } + auto setContext(uintptr context) -> bool override { - if(context == this->context()) return true; + if(context == Video::context()) return true; if(!Video::setContext(context)) return false; return initialize(); } auto setBlocking(bool blocking) -> bool override { - if(blocking == this->blocking()) return true; + if(blocking == Video::blocking()) return true; if(!Video::setBlocking(blocking)) return false; - if(ready() && glXSwapInterval) glXSwapInterval(_blocking); + if(glXSwapInterval) glXSwapInterval(blocking); return true; } auto setFlush(bool flush) -> bool override { - if(flush == this->flush()) return true; + if(flush == Video::flush()) return true; if(!Video::setFlush(flush)) return false; return true; } + auto setFormat(string format) -> bool override { + if(format == Video::format()) return true; + if(!Video::setFormat(format)) return false; + + if(format == "RGB24") { + _glFormat = GL_UNSIGNED_INT_8_8_8_8_REV; + return initialize(); + } + + if(format == "RGB30") { + _glFormat = GL_UNSIGNED_INT_2_10_10_10_REV; + return initialize(); + } + + return false; + } + auto setSmooth(bool smooth) -> bool override { - if(smooth == this->smooth()) return true; + if(smooth == Video::smooth()) return true; if(!Video::setSmooth(smooth)) return false; return true; } @@ -67,14 +89,14 @@ struct VideoGLX2 : Video { if(_isDoubleBuffered) glXSwapBuffers(_display, _glXWindow); } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; if(width != _width || height != _height) resize(width, height); pitch = _glWidth * sizeof(uint32_t); return data = _glBuffer; } - auto unlock() -> void override { + auto release() -> void override { if(!ready()) return; } @@ -101,7 +123,7 @@ struct VideoGLX2 : Video { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPixelStorei(GL_UNPACK_ROW_LENGTH, _glWidth); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _width, _height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _glBuffer); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _width, _height, GL_BGRA, _glFormat, _glBuffer); double w = (double)_width / (double)_glWidth; double h = (double)_height / (double)_glHeight; @@ -147,13 +169,17 @@ private: XWindowAttributes windowAttributes; XGetWindowAttributes(_display, (Window)_context, &windowAttributes); + int redDepth = Video::format() == "RGB30" ? 10 : 8; + int greenDepth = Video::format() == "RGB30" ? 10 : 8; + int blueDepth = Video::format() == "RGB30" ? 10 : 8; + int attributeList[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DOUBLEBUFFER, True, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, + GLX_RED_SIZE, redDepth, + GLX_GREEN_SIZE, greenDepth, + GLX_BLUE_SIZE, blueDepth, None }; @@ -253,7 +279,7 @@ private: glBindTexture(GL_TEXTURE_2D, _glTexture); glPixelStorei(GL_UNPACK_ROW_LENGTH, _glWidth); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _glWidth, _glHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _glBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _glWidth, _glHeight, 0, GL_BGRA, _glFormat, _glBuffer); } auto (*glXSwapInterval)(int) -> int = nullptr; @@ -277,4 +303,5 @@ private: uint32_t* _glBuffer = nullptr; uint _glWidth = 0; uint _glHeight = 0; + uint _glFormat = GL_UNSIGNED_INT_8_8_8_8_REV; }; diff --git a/ruby/video/wgl.cpp b/ruby/video/wgl.cpp index 2a85c5ab..9da15220 100644 --- a/ruby/video/wgl.cpp +++ b/ruby/video/wgl.cpp @@ -7,57 +7,66 @@ struct VideoWGL : Video, OpenGL { VideoWGL() { initialize(); } ~VideoWGL() { terminate(); } - auto ready() -> bool { return _ready; } + auto driver() -> string override { return "OpenGL"; } + auto ready() -> bool override { return _ready; } - auto context() -> uintptr { return _context; } - auto blocking() -> bool { return _blocking; } - auto smooth() -> bool { return _smooth; } - auto shader() -> string { return _shader; } + auto hasContext() -> bool override { return true; } + auto hasBlocking() -> bool override { return true; } + auto hasFlush() -> bool override { return true; } + auto hasSmooth() -> bool override { return true; } + auto hasShader() -> bool override { return true; } - auto setContext(uintptr context) -> bool { - if(_context == context) return true; - _context = context; + auto setContext(uintptr context) -> bool override { + if(context == Video::context()) return true; + if(!Video::setContext(context)) return false; return initialize(); } - auto setBlocking(bool blocking) -> bool { - if(_blocking == blocking) return true; - _blocking = blocking; - if(wglSwapInterval) wglSwapInterval(_blocking); + auto setBlocking(bool blocking) -> bool override { + if(blocking == Video::blocking()) return true; + if(!Video::setBlocking(blocking)) return false; + if(wglSwapInterval) wglSwapInterval(blocking); return true; } - auto setSmooth(bool smooth) -> bool { - if(_smooth == smooth) return true; - _smooth = smooth; - if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST; + auto setFlush(bool flush) -> bool override { + if(flush == Video::flush()) return true; + if(!Video::setFlush(flush)) return false; return true; } - auto setShader(string shader) -> bool { - if(_shader == shader) return true; - OpenGL::shader(_shader = shader); - if(!_shader) OpenGL::filter = _smooth ? GL_LINEAR : GL_NEAREST; + auto setSmooth(bool smooth) -> bool override { + if(smooth == Video::smooth()) return true; + if(!Video::setSmooth(smooth)) return false; + if(!shader()) OpenGL::filter = smooth ? GL_LINEAR : GL_NEAREST; return true; } - auto clear() -> void { + auto setShader(string shader) -> bool override { + if(shader == Video::shader()) return true; + if(!Video::setShader(shader)) return false; + OpenGL::setShader(shader); + if(!shader) OpenGL::filter = smooth() ? GL_LINEAR : GL_NEAREST; + return true; + } + + auto clear() -> void override { if(!ready()) return; OpenGL::clear(); SwapBuffers(_display); } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; OpenGL::size(width, height); return OpenGL::lock(data, pitch); } - auto unlock() -> void { + auto release() -> void override { if(!ready()) return; } - auto output() -> void { + auto output() -> void override { if(!ready()) return; RECT rectangle; GetClientRect((HWND)_context, &rectangle); @@ -65,6 +74,7 @@ struct VideoWGL : Video, OpenGL { OpenGL::outputHeight = rectangle.bottom - rectangle.top; OpenGL::output(); SwapBuffers(_display); + if(flush()) glFinish(); } private: @@ -120,10 +130,6 @@ private: auto (APIENTRY* wglSwapInterval)(int) -> BOOL = nullptr; bool _ready = false; - uintptr _context = 0; - bool _blocking = false; - bool _smooth = true; - string _shader; HDC _display = nullptr; HGLRC _wglContext = nullptr; diff --git a/ruby/video/xshm.cpp b/ruby/video/xshm.cpp index a0087b34..9f8b59e4 100644 --- a/ruby/video/xshm.cpp +++ b/ruby/video/xshm.cpp @@ -18,6 +18,14 @@ struct VideoXShm : Video { auto hasContext() -> bool override { return true; } auto hasSmooth() -> bool override { return true; } + auto availableFormats() -> vector { return {"RGB24"}; } + + auto exclusive() -> bool override { return false; } + auto blocking() -> bool override { return false; } + auto flush() -> bool override { return false; } + auto format() -> string override { return "RGB24"; } + auto shader() -> string override { return ""; } + auto setContext(uintptr context) -> bool override { if(context == this->context()) return true; if(!Video::setContext(context)) return false; @@ -38,7 +46,7 @@ struct VideoXShm : Video { output(); } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; if(!_inputBuffer || _inputWidth != width || _inputHeight != height) { if(_inputBuffer) delete[] _inputBuffer; @@ -52,7 +60,7 @@ struct VideoXShm : Video { return true; } - auto unlock() -> void override { + auto release() -> void override { if(!ready()) return; } diff --git a/ruby/video/xvideo.cpp b/ruby/video/xvideo.cpp index 25053a65..2b80bf8c 100644 --- a/ruby/video/xvideo.cpp +++ b/ruby/video/xvideo.cpp @@ -13,14 +13,14 @@ struct VideoXVideo : Video { auto driver() -> string override { return "XVideo"; } auto ready() -> bool override { return _ready; } - auto availableFormats() -> vector override { - return _formatNames; - } - auto hasContext() -> bool override { return true; } auto hasBlocking() -> bool override { return true; } auto hasFormat() -> bool override { return true; } + auto availableFormats() -> vector override { + return _formatNames; + } + auto setContext(uintptr context) -> bool override { if(context == Video::context()) return true; if(!Video::setContext(context)) return false; @@ -56,14 +56,14 @@ struct VideoXVideo : Video { output(); } - auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { + auto acquire(uint32_t*& data, uint& pitch, uint width, uint height) -> bool override { if(!ready()) return false; if(width != _width || height != _height) resize(_width = width, _height = height); pitch = _bufferWidth * 4; return data = _buffer; } - auto unlock() -> void override { + auto release() -> void override { if(!ready()) return; } @@ -87,14 +87,14 @@ struct VideoXVideo : Video { XGetWindowAttributes(_display, _window, &target); auto& name = _formatName; - if(name == "RGB32") renderRGB32(_width, _height); - if(name == "RGB24") renderRGB24(_width, _height); - if(name == "RGB16") renderRGB16(_width, _height); - if(name == "RGB15") renderRGB15(_width, _height); - if(name == "UYVY" ) renderUYVY (_width, _height); - if(name == "YUY2" ) renderYUY2 (_width, _height); - if(name == "YV12" ) renderYV12 (_width, _height); - if(name == "I420" ) renderI420 (_width, _height); + if(name == "RGB24" ) renderRGB24 (_width, _height); + if(name == "RGB24P") renderRGB24P(_width, _height); + if(name == "RGB16" ) renderRGB16 (_width, _height); + if(name == "RGB15" ) renderRGB15 (_width, _height); + if(name == "UYVY" ) renderUYVY (_width, _height); + if(name == "YUY2" ) renderYUY2 (_width, _height); + if(name == "YV12" ) renderYV12 (_width, _height); + if(name == "I420" ) renderI420 (_width, _height); XvShmPutImage(_display, _port, _window, _gc, _image, 0, 0, _width, _height, @@ -275,8 +275,8 @@ private: for(uint n : range(4)) if(char c = order[n]) components.append(c); if(type == XvRGB) { - if(sort == 0 && depth == 32) ids.append(id), names.append("RGB32"); - if(sort == 1 && depth == 24) ids.append(id), names.append("RGB24"); + if(sort == 0 && depth == 32) ids.append(id), names.append("RGB24"); + if(sort == 1 && depth == 24) ids.append(id), names.append("RGB24P"); if(sort == 2 && depth <= 16 && redMask == 0xf800) ids.append(id), names.append("RGB16"); if(sort == 3 && depth <= 16 && redMask == 0x7c00) ids.append(id), names.append("RGB15"); } @@ -326,7 +326,7 @@ private: _buffer = new uint32_t[_bufferWidth * _bufferHeight]; } - auto renderRGB32(uint width, uint height) -> void { + auto renderRGB24(uint width, uint height) -> void { for(uint y : range(height)) { auto input = (const uint32_t*)_buffer + y * width; auto output = (uint32_t*)_image->data + y * (_image->pitches[0] >> 2); @@ -338,7 +338,7 @@ private: } } - auto renderRGB24(uint width, uint height) -> void { + auto renderRGB24P(uint width, uint height) -> void { for(uint y : range(height)) { auto input = (const uint32_t*)_buffer + y * width; auto output = (uint8_t*)_image->data + y * _image->pitches[0];