diff --git a/Configurable/Configurable.hpp b/Configurable/Configurable.hpp index 1c4ac8f1c..833989951 100644 --- a/Configurable/Configurable.hpp +++ b/Configurable/Configurable.hpp @@ -69,7 +69,7 @@ struct BooleanSelection: public Selection { struct ListSelection: public Selection { std::string value; - + ListSelection *list_selection(); BooleanSelection *boolean_selection(); ListSelection(const std::string value) : value(value) {} diff --git a/Machines/Electron/Video.cpp b/Machines/Electron/Video.cpp index 445b2f4aa..2d7b316af 100644 --- a/Machines/Electron/Video.cpp +++ b/Machines/Electron/Video.cpp @@ -404,7 +404,7 @@ unsigned int VideoOutput::get_cycles_until_next_ram_availability(int from_time) if(current_line >= output_position_line) { // Get the number of lines since then if still in the same frame. int lines_since_output_position = current_line - output_position_line; - + // Therefore get the character row at the proposed time, modulo 10. implied_row = (current_character_row_ + lines_since_output_position) % 10; } else { diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index c08d4507c..e1a608e97 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -7,11 +7,13 @@ // #include +#include #include #include #include #include #include +#include #include @@ -234,7 +236,7 @@ ParsedArguments parse_arguments(int argc, char *argv[]) { // --flag sets a Boolean option to true. // --flag=value sets the value for a list option. // name sets the file name to load. - + // Anything starting with a dash always makes a selection; otherwise it's a file name. if(arg[0] == '-') { while(*arg == '-') arg++; @@ -266,7 +268,7 @@ std::string final_path_component(const std::string &path) { // Find the last slash... auto final_slash = path.find_last_of("/\\"); - + // If no slash was found at all, return the whole path. if(final_slash == std::string::npos) { return path; @@ -281,6 +283,22 @@ std::string final_path_component(const std::string &path) { return path.substr(final_slash+1, path.size() - final_slash - 1); } +/*! + Executes @c command and returns its STDOUT. +*/ +std::string system_get(const char *command) { + std::unique_ptr pipe(popen(command, "r"), pclose); + if(!pipe) return ""; + + std::string result; + while(!feof(pipe.get())) { + std::array buffer; + if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + result += buffer.data(); + } + return result; +} + } int main(int argc, char *argv[]) { @@ -303,7 +321,7 @@ int main(int argc, char *argv[]) { std::cout << machine_options.first << ":" << std::endl; for(const auto &option: machine_options.second) { std::cout << '\t' << "--" << option->short_name; - + Configurable::ListOption *list_option = dynamic_cast(option.get()); if(list_option) { std::cout << "={"; @@ -482,7 +500,7 @@ int main(int argc, char *argv[]) { if(configurable_device) { // Establish user-friendly options by default. configurable_device->set_selections(configurable_device->get_user_friendly_selections()); - + // Consider transcoding any list selections that map to Boolean options. for(const auto &option: configurable_device->get_options()) { // Check for a corresponding selection. @@ -617,12 +635,21 @@ int main(int argc, char *argv[]) { memcpy(&pixels[(window_height - 1 - y)*proportional_width*4], swap_buffer.data(), swap_buffer.size()); } + // Pick the directory for images. Try `xdg-user-dir PICTURES` first. + std::string target_directory = system_get("xdg-user-dir PICTURES"); + + // Make sure there are no newlines. + target_directory.erase(std::remove(target_directory.begin(), target_directory.end(), '\n'), target_directory.end()); + target_directory.erase(std::remove(target_directory.begin(), target_directory.end(), '\r'), target_directory.end()); + + // Fall back on the HOME directory if necessary. + if(target_directory.empty()) target_directory = getenv("HOME"); + // Find the first available name of the form ~/clk-screenshot-.bmp. size_t index = 0; - const std::string home = getenv("HOME"); std::string target; while(true) { - target = home + "/clk-screenshot-" + std::to_string(index) + ".bmp"; + target = target_directory + "/clk-screenshot-" + std::to_string(index) + ".bmp"; struct stat file_stats; if(stat(target.c_str(), &file_stats)) diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index adbc35e71..b0c554eff 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -164,7 +164,7 @@ class OpenGLOutputBuilder { if(!composite_output_buffer_is_full()) composite_src_output_y_++; } - + void set_target_framebuffer(GLint); void draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty); void set_openGL_context_will_change(bool should_delete_resources); diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp index 9fda6eb47..ff8316893 100644 --- a/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp +++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp @@ -19,7 +19,7 @@ namespace OpenGL { class IntermediateShader: public Shader { public: using Shader::Shader; - + enum class Input { /// Contains the 2d start position of this run's input data. InputStart,