mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-03 12:52:55 +02:00
Update to v095r18 release.
byuu says: Changelog: - replaced popen() with execvp() / CreateProcess() - suppressed (hid) controllers with no mappable inputs from the input settings panel This gets rid of the window flashing when loading games with higan+icarus. And hiding of empty devices should be a huge usability improvement, especially since "None" was appearing at the top of the list before for the SNES.
This commit is contained in:
@@ -13,14 +13,14 @@
|
||||
namespace nall {
|
||||
|
||||
struct file : file_system_object, varint {
|
||||
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
||||
enum class index : unsigned { absolute, relative };
|
||||
enum class mode : uint { read, write, modify, append, readwrite = modify, writeread = append };
|
||||
enum class index : uint { absolute, relative };
|
||||
|
||||
static auto copy(const string& sourcename, const string& targetname) -> bool {
|
||||
file rd, wr;
|
||||
if(rd.open(sourcename, mode::read) == false) return false;
|
||||
if(wr.open(targetname, mode::write) == false) return false;
|
||||
for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read());
|
||||
for(uint n = 0; n < rd.size(); n++) wr.write(rd.read());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ struct file : file_system_object, varint {
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto truncate(const string& filename, unsigned size) -> bool {
|
||||
static auto truncate(const string& filename, uint size) -> bool {
|
||||
#if defined(API_POSIX)
|
||||
return truncate(filename, size) == 0;
|
||||
#elif defined(API_WINDOWS)
|
||||
@@ -61,7 +61,7 @@ struct file : file_system_object, varint {
|
||||
return !(data.st_mode & S_IFDIR);
|
||||
}
|
||||
|
||||
static auto size(const string& filename) -> uintmax_t {
|
||||
static auto size(const string& filename) -> uintmax {
|
||||
#if defined(API_POSIX)
|
||||
struct stat data;
|
||||
stat(filename, &data);
|
||||
@@ -72,8 +72,8 @@ struct file : file_system_object, varint {
|
||||
return S_ISREG(data.st_mode) ? data.st_size : 0u;
|
||||
}
|
||||
|
||||
static auto read(const string& filename) -> vector<uint8_t> {
|
||||
vector<uint8_t> memory;
|
||||
static auto read(const string& filename) -> vector<uint8> {
|
||||
vector<uint8> memory;
|
||||
file fp;
|
||||
if(fp.open(filename, mode::read)) {
|
||||
memory.resize(fp.size());
|
||||
@@ -82,7 +82,7 @@ struct file : file_system_object, varint {
|
||||
return memory;
|
||||
}
|
||||
|
||||
static auto read(const string& filename, uint8_t* data, unsigned size) -> bool {
|
||||
static auto read(const string& filename, uint8* data, uint size) -> bool {
|
||||
file fp;
|
||||
if(fp.open(filename, mode::read) == false) return false;
|
||||
fp.read(data, size);
|
||||
@@ -91,14 +91,14 @@ struct file : file_system_object, varint {
|
||||
}
|
||||
|
||||
static auto write(const string& filename, const string& text) -> bool {
|
||||
return write(filename, (const uint8_t*)text.data(), text.size());
|
||||
return write(filename, (const uint8*)text.data(), text.size());
|
||||
}
|
||||
|
||||
static auto write(const string& filename, const vector<uint8_t>& buffer) -> bool {
|
||||
static auto write(const string& filename, const vector<uint8>& buffer) -> bool {
|
||||
return write(filename, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
static auto write(const string& filename, const uint8_t* data, unsigned size) -> bool {
|
||||
static auto write(const string& filename, const uint8* data, uint size) -> bool {
|
||||
file fp;
|
||||
if(fp.open(filename, mode::write) == false) return false;
|
||||
fp.write(data, size);
|
||||
@@ -119,7 +119,7 @@ struct file : file_system_object, varint {
|
||||
return Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||
}
|
||||
|
||||
auto read() -> uint8_t {
|
||||
auto read() -> uint8 {
|
||||
if(!fp) return 0xff; //file not open
|
||||
if(file_mode == mode::write) return 0xff; //reads not permitted
|
||||
if(file_offset >= file_size) return 0xff; //cannot read past end of file
|
||||
@@ -127,16 +127,16 @@ struct file : file_system_object, varint {
|
||||
return buffer[(file_offset++) & buffer_mask];
|
||||
}
|
||||
|
||||
auto readl(unsigned length = 1) -> uintmax_t {
|
||||
uintmax_t data = 0;
|
||||
auto readl(uint length = 1) -> uintmax {
|
||||
uintmax data = 0;
|
||||
for(int i = 0; i < length; i++) {
|
||||
data |= (uintmax_t)read() << (i << 3);
|
||||
data |= (uintmax)read() << (i << 3);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
auto readm(unsigned length = 1) -> uintmax_t {
|
||||
uintmax_t data = 0;
|
||||
auto readm(uint length = 1) -> uintmax {
|
||||
uintmax data = 0;
|
||||
while(length--) {
|
||||
data <<= 8;
|
||||
data |= read();
|
||||
@@ -144,18 +144,18 @@ struct file : file_system_object, varint {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto reads(unsigned length) -> string {
|
||||
auto reads(uint length) -> string {
|
||||
string result;
|
||||
result.resize(length);
|
||||
for(auto& byte : result) byte = read();
|
||||
return result;
|
||||
}
|
||||
|
||||
auto read(uint8_t* buffer, unsigned length) -> void {
|
||||
auto read(uint8* buffer, uint length) -> void {
|
||||
while(length--) *buffer++ = read();
|
||||
}
|
||||
|
||||
auto write(uint8_t data) -> void {
|
||||
auto write(uint8 data) -> void {
|
||||
if(!fp) return; //file not open
|
||||
if(file_mode == mode::read) return; //writes not permitted
|
||||
buffer_sync();
|
||||
@@ -164,14 +164,14 @@ struct file : file_system_object, varint {
|
||||
if(file_offset > file_size) file_size = file_offset;
|
||||
}
|
||||
|
||||
auto writel(uintmax_t data, unsigned length = 1) -> void {
|
||||
auto writel(uintmax data, uint length = 1) -> void {
|
||||
while(length--) {
|
||||
write(data);
|
||||
data >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
auto writem(uintmax_t data, unsigned length = 1) -> void {
|
||||
auto writem(uintmax data, uint length = 1) -> void {
|
||||
for(int i = length - 1; i >= 0; i--) {
|
||||
write(data >> (i << 3));
|
||||
}
|
||||
@@ -181,7 +181,7 @@ struct file : file_system_object, varint {
|
||||
for(auto byte : s) write(byte);
|
||||
}
|
||||
|
||||
auto write(const uint8_t* buffer, unsigned length) -> void {
|
||||
auto write(const uint8* buffer, uint length) -> void {
|
||||
while(length--) write(*buffer++);
|
||||
}
|
||||
|
||||
@@ -196,11 +196,11 @@ struct file : file_system_object, varint {
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
auto seek(signed offset, index index_ = index::absolute) -> void {
|
||||
auto seek(int offset, index index_ = index::absolute) -> void {
|
||||
if(!fp) return; //file not open
|
||||
buffer_flush();
|
||||
|
||||
intmax_t req_offset = file_offset;
|
||||
intmax req_offset = file_offset;
|
||||
switch(index_) {
|
||||
case index::absolute: req_offset = offset; break;
|
||||
case index::relative: req_offset += offset; break;
|
||||
@@ -219,17 +219,17 @@ struct file : file_system_object, varint {
|
||||
file_offset = req_offset;
|
||||
}
|
||||
|
||||
auto offset() const -> unsigned {
|
||||
auto offset() const -> uint {
|
||||
if(!fp) return 0; //file not open
|
||||
return file_offset;
|
||||
}
|
||||
|
||||
auto size() const -> unsigned {
|
||||
auto size() const -> uint {
|
||||
if(!fp) return 0; //file not open
|
||||
return file_size;
|
||||
}
|
||||
|
||||
auto truncate(unsigned size) -> bool {
|
||||
auto truncate(uint size) -> bool {
|
||||
if(!fp) return false; //file not open
|
||||
#if defined(API_POSIX)
|
||||
return ftruncate(fileno(fp), size) == 0;
|
||||
@@ -301,8 +301,8 @@ private:
|
||||
int buffer_offset = -1; //invalidate buffer
|
||||
bool buffer_dirty = false;
|
||||
FILE* fp = nullptr;
|
||||
unsigned file_offset = 0;
|
||||
unsigned file_size = 0;
|
||||
uint file_offset = 0;
|
||||
uint file_size = 0;
|
||||
mode file_mode = mode::read;
|
||||
|
||||
auto buffer_sync() -> void {
|
||||
@@ -311,8 +311,8 @@ private:
|
||||
buffer_flush();
|
||||
buffer_offset = file_offset & ~buffer_mask;
|
||||
fseek(fp, buffer_offset, SEEK_SET);
|
||||
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||
if(length) unsigned unused = fread(buffer, 1, length, fp);
|
||||
uint length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||
if(length) auto unused = fread(buffer, 1, length, fp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,8 +322,8 @@ private:
|
||||
if(buffer_offset < 0) return; //buffer unused
|
||||
if(buffer_dirty == false) return; //buffer unmodified since read
|
||||
fseek(fp, buffer_offset, SEEK_SET);
|
||||
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||
if(length) unsigned unused = fwrite(buffer, 1, length, fp);
|
||||
uint length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||
if(length) auto unused = fwrite(buffer, 1, length, fp);
|
||||
buffer_offset = -1; //invalidate buffer
|
||||
buffer_dirty = false;
|
||||
}
|
||||
|
@@ -1,58 +0,0 @@
|
||||
#ifndef NALL_INVOKE_HPP
|
||||
#define NALL_INVOKE_HPP
|
||||
|
||||
//auto invoke(const string &name, const string& args...) -> void;
|
||||
//if a program is specified, it is executed with the arguments provided
|
||||
//if a file is specified, the file is opened using the program associated with said file type
|
||||
//if a folder is specified, the folder is opened using the associated file explorer
|
||||
//if a URL is specified, the default web browser is opened and pointed at the URL requested
|
||||
//path environment variable is always consulted
|
||||
//execution is asynchronous (non-blocking); use system() for synchronous execution
|
||||
|
||||
#include <nall/intrinsics.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
#include <nall/windows/utf8.hpp>
|
||||
#endif
|
||||
|
||||
namespace nall {
|
||||
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
|
||||
template<typename... Args> inline auto invoke(const string& name, Args&&... args) -> void {
|
||||
lstring argl(std::forward<Args>(args)...);
|
||||
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
|
||||
string arguments = argl.merge(" ");
|
||||
ShellExecuteW(NULL, NULL, utf16_t(name), utf16_t(arguments), NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
|
||||
|
||||
template<typename... Args> inline auto invoke(const string& name, Args&&... args) -> void {
|
||||
pid_t pid = fork();
|
||||
if(pid == 0) {
|
||||
const char* argv[1 + sizeof...(args) + 1];
|
||||
const char** argp = argv;
|
||||
lstring argl(std::forward<Args>(args)...);
|
||||
*argp++ = (const char*)name;
|
||||
for(auto& arg : argl) *argp++ = (const char*)arg;
|
||||
*argp++ = nullptr;
|
||||
|
||||
if(execvp(name, (char* const*)argv) < 0) {
|
||||
execlp("xdg-open", "xdg-open", (const char*)name, nullptr);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename... Args> inline auto invoke(const string& name, Args&&... args) -> void {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -32,7 +32,6 @@
|
||||
#include <nall/image.hpp>
|
||||
#include <nall/interpolation.hpp>
|
||||
#include <nall/intrinsics.hpp>
|
||||
#include <nall/invoke.hpp>
|
||||
#include <nall/map.hpp>
|
||||
#include <nall/matrix.hpp>
|
||||
#include <nall/maybe.hpp>
|
||||
@@ -41,6 +40,7 @@
|
||||
#include <nall/property.hpp>
|
||||
#include <nall/random.hpp>
|
||||
#include <nall/range.hpp>
|
||||
#include <nall/run.hpp>
|
||||
#include <nall/serializer.hpp>
|
||||
#include <nall/set.hpp>
|
||||
#include <nall/shared-pointer.hpp>
|
||||
|
@@ -49,6 +49,7 @@ namespace Math {
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
|
162
nall/run.hpp
Normal file
162
nall/run.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#ifndef NALL_RUN_HPP
|
||||
#define NALL_RUN_HPP
|
||||
|
||||
//auto execute(const string& name, const string& args...) -> string;
|
||||
//[[synchronous]]
|
||||
//executes program, waits for completion, and returns data written to stdout
|
||||
|
||||
//auto invoke(const string& name, const string& args...) -> void;
|
||||
//[[asynchronous]]
|
||||
//if a program is specified, it is executed with the arguments provided
|
||||
//if a file is specified, the file is opened using the program associated with said file type
|
||||
//if a folder is specified, the folder is opened using the associated file explorer
|
||||
//if a URL is specified, the default web browser is opened and pointed at the URL requested
|
||||
|
||||
#include <nall/intrinsics.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
|
||||
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> string {
|
||||
int fd[2];
|
||||
if(pipe(fd) == -1) return "";
|
||||
|
||||
pid_t pid = fork();
|
||||
if(pid == 0) {
|
||||
const char* argv[1 + sizeof...(p) + 1];
|
||||
const char** argp = argv;
|
||||
lstring argl(forward<P>(p)...);
|
||||
*argp++ = (const char*)name;
|
||||
for(auto& arg : argl) *argp++ = (const char*)arg;
|
||||
*argp++ = nullptr;
|
||||
|
||||
dup2(fd[1], STDOUT_FILENO);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
execvp(name, (char* const*)argv);
|
||||
exit(0);
|
||||
} else {
|
||||
close(fd[1]);
|
||||
|
||||
string result;
|
||||
while(true) {
|
||||
char buffer[256];
|
||||
auto size = read(fd[0], buffer, sizeof(buffer));
|
||||
if(size <= 0) break;
|
||||
|
||||
auto offset = result.size();
|
||||
result.resize(offset + size);
|
||||
memory::copy(result.get() + offset, buffer, size);
|
||||
}
|
||||
|
||||
close(fd[0]);
|
||||
wait(nullptr);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... P> inline auto invoke(const string& name, P&&... p) -> void {
|
||||
pid_t pid = fork();
|
||||
if(pid == 0) {
|
||||
const char* argv[1 + sizeof...(p) + 1];
|
||||
const char** argp = argv;
|
||||
lstring argl(forward<P>(p)...);
|
||||
*argp++ = (const char*)name;
|
||||
for(auto& arg : argl) *argp++ = (const char*)arg;
|
||||
*argp++ = nullptr;
|
||||
|
||||
if(execvp(name, (char* const*)argv) < 0) {
|
||||
execlp("xdg-open", "xdg-open", (const char*)name, nullptr);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(PLATFORM_WINDOWS)
|
||||
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> string {
|
||||
lstring argl(name, forward<P>(p)...);
|
||||
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
|
||||
string arguments = argl.merge(" ");
|
||||
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = true;
|
||||
sa.lpSecurityDescriptor = nullptr;
|
||||
|
||||
HANDLE stdoutRead;
|
||||
HANDLE stdoutWrite;
|
||||
if(!CreatePipe(&stdoutRead, &stdoutWrite, &sa, 0)) return "";
|
||||
if(!SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0)) return "";
|
||||
|
||||
HANDLE stdinRead;
|
||||
HANDLE stdinWrite;
|
||||
if(!CreatePipe(&stdinRead, &stdinWrite, &sa, 0)) return "";
|
||||
if(!SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0)) return "";
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.hStdError = stdoutWrite;
|
||||
si.hStdOutput = stdoutWrite;
|
||||
si.hStdInput = stdinRead;
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
if(!CreateProcess(
|
||||
nullptr, utf16_t(arguments),
|
||||
nullptr, nullptr, true, CREATE_NO_WINDOW,
|
||||
nullptr, nullptr, &si, &pi
|
||||
)) return "";
|
||||
|
||||
while(true) {
|
||||
DWORD exitCode;
|
||||
GetExitCodeProcess(pi.hProcess, &exitCode);
|
||||
if(exitCode != STILL_ACTIVE) break;
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
string result;
|
||||
while(true) {
|
||||
char buffer[256];
|
||||
DWORD read, available, remaining;
|
||||
if(!PeekNamedPipe(stdoutRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break;
|
||||
if(read == 0) break;
|
||||
|
||||
if(!ReadFile(stdoutRead, buffer, sizeof(buffer), &read, nullptr)) break;
|
||||
if(read == 0) break;
|
||||
|
||||
auto offset = result.size();
|
||||
result.resize(offset + read);
|
||||
memory::copy(result.get() + offset, buffer, read);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename... P> inline auto invoke(const string& name, P&&... p) -> void {
|
||||
lstring argl(forward<P>(p)...);
|
||||
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
|
||||
string arguments = argl.merge(" ");
|
||||
ShellExecute(nullptr, nullptr, utf16_t(name), utf16_t(arguments), nullptr, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> string {
|
||||
return "";
|
||||
}
|
||||
|
||||
template<typename... P> inline auto invoke(const string& name, P&&... p) -> void {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user