mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
0253db8685
commit
702b657e75
|
@ -7,7 +7,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "095.17";
|
static const string Version = "095.18";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct Interface {
|
||||||
uint id;
|
uint id;
|
||||||
uint type; //0 = digital, 1 = analog (relative), 2 = rumble
|
uint type; //0 = digital, 1 = analog (relative), 2 = rumble
|
||||||
string name;
|
string name;
|
||||||
uintptr_t guid; //user data field
|
uintptr guid; //user data field
|
||||||
};
|
};
|
||||||
vector<Input> input;
|
vector<Input> input;
|
||||||
vector<uint> order;
|
vector<uint> order;
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct file : file_system_object, varint {
|
struct file : file_system_object, varint {
|
||||||
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
enum class mode : uint { read, write, modify, append, readwrite = modify, writeread = append };
|
||||||
enum class index : unsigned { absolute, relative };
|
enum class index : uint { absolute, relative };
|
||||||
|
|
||||||
static auto copy(const string& sourcename, const string& targetname) -> bool {
|
static auto copy(const string& sourcename, const string& targetname) -> bool {
|
||||||
file rd, wr;
|
file rd, wr;
|
||||||
if(rd.open(sourcename, mode::read) == false) return false;
|
if(rd.open(sourcename, mode::read) == false) return false;
|
||||||
if(wr.open(targetname, mode::write) == 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ struct file : file_system_object, varint {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto truncate(const string& filename, unsigned size) -> bool {
|
static auto truncate(const string& filename, uint size) -> bool {
|
||||||
#if defined(API_POSIX)
|
#if defined(API_POSIX)
|
||||||
return truncate(filename, size) == 0;
|
return truncate(filename, size) == 0;
|
||||||
#elif defined(API_WINDOWS)
|
#elif defined(API_WINDOWS)
|
||||||
|
@ -61,7 +61,7 @@ struct file : file_system_object, varint {
|
||||||
return !(data.st_mode & S_IFDIR);
|
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)
|
#if defined(API_POSIX)
|
||||||
struct stat data;
|
struct stat data;
|
||||||
stat(filename, &data);
|
stat(filename, &data);
|
||||||
|
@ -72,8 +72,8 @@ struct file : file_system_object, varint {
|
||||||
return S_ISREG(data.st_mode) ? data.st_size : 0u;
|
return S_ISREG(data.st_mode) ? data.st_size : 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto read(const string& filename) -> vector<uint8_t> {
|
static auto read(const string& filename) -> vector<uint8> {
|
||||||
vector<uint8_t> memory;
|
vector<uint8> memory;
|
||||||
file fp;
|
file fp;
|
||||||
if(fp.open(filename, mode::read)) {
|
if(fp.open(filename, mode::read)) {
|
||||||
memory.resize(fp.size());
|
memory.resize(fp.size());
|
||||||
|
@ -82,7 +82,7 @@ struct file : file_system_object, varint {
|
||||||
return memory;
|
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;
|
file fp;
|
||||||
if(fp.open(filename, mode::read) == false) return false;
|
if(fp.open(filename, mode::read) == false) return false;
|
||||||
fp.read(data, size);
|
fp.read(data, size);
|
||||||
|
@ -91,14 +91,14 @@ struct file : file_system_object, varint {
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto write(const string& filename, const string& text) -> bool {
|
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());
|
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;
|
file fp;
|
||||||
if(fp.open(filename, mode::write) == false) return false;
|
if(fp.open(filename, mode::write) == false) return false;
|
||||||
fp.write(data, size);
|
fp.write(data, size);
|
||||||
|
@ -119,7 +119,7 @@ struct file : file_system_object, varint {
|
||||||
return Hash::SHA256(buffer.data(), buffer.size()).digest();
|
return Hash::SHA256(buffer.data(), buffer.size()).digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto read() -> uint8_t {
|
auto read() -> uint8 {
|
||||||
if(!fp) return 0xff; //file not open
|
if(!fp) return 0xff; //file not open
|
||||||
if(file_mode == mode::write) return 0xff; //reads not permitted
|
if(file_mode == mode::write) return 0xff; //reads not permitted
|
||||||
if(file_offset >= file_size) return 0xff; //cannot read past end of file
|
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];
|
return buffer[(file_offset++) & buffer_mask];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto readl(unsigned length = 1) -> uintmax_t {
|
auto readl(uint length = 1) -> uintmax {
|
||||||
uintmax_t data = 0;
|
uintmax data = 0;
|
||||||
for(int i = 0; i < length; i++) {
|
for(int i = 0; i < length; i++) {
|
||||||
data |= (uintmax_t)read() << (i << 3);
|
data |= (uintmax)read() << (i << 3);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto readm(unsigned length = 1) -> uintmax_t {
|
auto readm(uint length = 1) -> uintmax {
|
||||||
uintmax_t data = 0;
|
uintmax data = 0;
|
||||||
while(length--) {
|
while(length--) {
|
||||||
data <<= 8;
|
data <<= 8;
|
||||||
data |= read();
|
data |= read();
|
||||||
|
@ -144,18 +144,18 @@ struct file : file_system_object, varint {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto reads(unsigned length) -> string {
|
auto reads(uint length) -> string {
|
||||||
string result;
|
string result;
|
||||||
result.resize(length);
|
result.resize(length);
|
||||||
for(auto& byte : result) byte = read();
|
for(auto& byte : result) byte = read();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto read(uint8_t* buffer, unsigned length) -> void {
|
auto read(uint8* buffer, uint length) -> void {
|
||||||
while(length--) *buffer++ = read();
|
while(length--) *buffer++ = read();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto write(uint8_t data) -> void {
|
auto write(uint8 data) -> void {
|
||||||
if(!fp) return; //file not open
|
if(!fp) return; //file not open
|
||||||
if(file_mode == mode::read) return; //writes not permitted
|
if(file_mode == mode::read) return; //writes not permitted
|
||||||
buffer_sync();
|
buffer_sync();
|
||||||
|
@ -164,14 +164,14 @@ struct file : file_system_object, varint {
|
||||||
if(file_offset > file_size) file_size = file_offset;
|
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--) {
|
while(length--) {
|
||||||
write(data);
|
write(data);
|
||||||
data >>= 8;
|
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--) {
|
for(int i = length - 1; i >= 0; i--) {
|
||||||
write(data >> (i << 3));
|
write(data >> (i << 3));
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ struct file : file_system_object, varint {
|
||||||
for(auto byte : s) write(byte);
|
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++);
|
while(length--) write(*buffer++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,11 +196,11 @@ struct file : file_system_object, varint {
|
||||||
fflush(fp);
|
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
|
if(!fp) return; //file not open
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
|
|
||||||
intmax_t req_offset = file_offset;
|
intmax req_offset = file_offset;
|
||||||
switch(index_) {
|
switch(index_) {
|
||||||
case index::absolute: req_offset = offset; break;
|
case index::absolute: req_offset = offset; break;
|
||||||
case index::relative: 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;
|
file_offset = req_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto offset() const -> unsigned {
|
auto offset() const -> uint {
|
||||||
if(!fp) return 0; //file not open
|
if(!fp) return 0; //file not open
|
||||||
return file_offset;
|
return file_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size() const -> unsigned {
|
auto size() const -> uint {
|
||||||
if(!fp) return 0; //file not open
|
if(!fp) return 0; //file not open
|
||||||
return file_size;
|
return file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto truncate(unsigned size) -> bool {
|
auto truncate(uint size) -> bool {
|
||||||
if(!fp) return false; //file not open
|
if(!fp) return false; //file not open
|
||||||
#if defined(API_POSIX)
|
#if defined(API_POSIX)
|
||||||
return ftruncate(fileno(fp), size) == 0;
|
return ftruncate(fileno(fp), size) == 0;
|
||||||
|
@ -301,8 +301,8 @@ private:
|
||||||
int buffer_offset = -1; //invalidate buffer
|
int buffer_offset = -1; //invalidate buffer
|
||||||
bool buffer_dirty = false;
|
bool buffer_dirty = false;
|
||||||
FILE* fp = nullptr;
|
FILE* fp = nullptr;
|
||||||
unsigned file_offset = 0;
|
uint file_offset = 0;
|
||||||
unsigned file_size = 0;
|
uint file_size = 0;
|
||||||
mode file_mode = mode::read;
|
mode file_mode = mode::read;
|
||||||
|
|
||||||
auto buffer_sync() -> void {
|
auto buffer_sync() -> void {
|
||||||
|
@ -311,8 +311,8 @@ private:
|
||||||
buffer_flush();
|
buffer_flush();
|
||||||
buffer_offset = file_offset & ~buffer_mask;
|
buffer_offset = file_offset & ~buffer_mask;
|
||||||
fseek(fp, buffer_offset, SEEK_SET);
|
fseek(fp, buffer_offset, SEEK_SET);
|
||||||
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
uint length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||||
if(length) unsigned unused = fread(buffer, 1, length, fp);
|
if(length) auto unused = fread(buffer, 1, length, fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,8 +322,8 @@ private:
|
||||||
if(buffer_offset < 0) return; //buffer unused
|
if(buffer_offset < 0) return; //buffer unused
|
||||||
if(buffer_dirty == false) return; //buffer unmodified since read
|
if(buffer_dirty == false) return; //buffer unmodified since read
|
||||||
fseek(fp, buffer_offset, SEEK_SET);
|
fseek(fp, buffer_offset, SEEK_SET);
|
||||||
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
uint length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||||
if(length) unsigned unused = fwrite(buffer, 1, length, fp);
|
if(length) auto unused = fwrite(buffer, 1, length, fp);
|
||||||
buffer_offset = -1; //invalidate buffer
|
buffer_offset = -1; //invalidate buffer
|
||||||
buffer_dirty = false;
|
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/image.hpp>
|
||||||
#include <nall/interpolation.hpp>
|
#include <nall/interpolation.hpp>
|
||||||
#include <nall/intrinsics.hpp>
|
#include <nall/intrinsics.hpp>
|
||||||
#include <nall/invoke.hpp>
|
|
||||||
#include <nall/map.hpp>
|
#include <nall/map.hpp>
|
||||||
#include <nall/matrix.hpp>
|
#include <nall/matrix.hpp>
|
||||||
#include <nall/maybe.hpp>
|
#include <nall/maybe.hpp>
|
||||||
|
@ -41,6 +40,7 @@
|
||||||
#include <nall/property.hpp>
|
#include <nall/property.hpp>
|
||||||
#include <nall/random.hpp>
|
#include <nall/random.hpp>
|
||||||
#include <nall/range.hpp>
|
#include <nall/range.hpp>
|
||||||
|
#include <nall/run.hpp>
|
||||||
#include <nall/serializer.hpp>
|
#include <nall/serializer.hpp>
|
||||||
#include <nall/set.hpp>
|
#include <nall/set.hpp>
|
||||||
#include <nall/shared-pointer.hpp>
|
#include <nall/shared-pointer.hpp>
|
||||||
|
|
|
@ -49,6 +49,7 @@ namespace Math {
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
|
@ -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
|
|
@ -5,9 +5,9 @@ InputManager* inputManager = nullptr;
|
||||||
auto InputMapping::bind() -> void {
|
auto InputMapping::bind() -> void {
|
||||||
auto token = assignment.split("/");
|
auto token = assignment.split("/");
|
||||||
if(token.size() < 3) return unbind();
|
if(token.size() < 3) return unbind();
|
||||||
uint64_t id = token[0].natural();
|
uint64 id = token[0].natural();
|
||||||
unsigned group = token[1].natural();
|
uint group = token[1].natural();
|
||||||
unsigned input = token[2].natural();
|
uint input = token[2].natural();
|
||||||
string qualifier = token(3, "None");
|
string qualifier = token(3, "None");
|
||||||
|
|
||||||
for(auto& device : inputManager->devices) {
|
for(auto& device : inputManager->devices) {
|
||||||
|
@ -26,7 +26,7 @@ auto InputMapping::bind() -> void {
|
||||||
settings[path].setValue(assignment);
|
settings[path].setValue(assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputMapping::bind(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool {
|
auto InputMapping::bind(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> bool {
|
||||||
if(device->isNull() || (device->isKeyboard() && device->group(group).input(input).name() == "Escape")) {
|
if(device->isNull() || (device->isKeyboard() && device->group(group).input(input).name() == "Escape")) {
|
||||||
return unbind(), true;
|
return unbind(), true;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ auto InputManager::poll() -> void {
|
||||||
if(presentation && presentation->focused()) pollHotkeys();
|
if(presentation && presentation->focused()) pollHotkeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputManager::onChange(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void {
|
auto InputManager::onChange(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> void {
|
||||||
if(settingsManager->focused()) {
|
if(settingsManager->focused()) {
|
||||||
settingsManager->input.inputEvent(device, group, input, oldValue, newValue);
|
settingsManager->input.inputEvent(device, group, input, oldValue, newValue);
|
||||||
settingsManager->hotkeys.inputEvent(device, group, input, oldValue, newValue);
|
settingsManager->hotkeys.inputEvent(device, group, input, oldValue, newValue);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
struct InputMapping {
|
struct InputMapping {
|
||||||
auto bind() -> void;
|
auto bind() -> void;
|
||||||
auto bind(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> bool;
|
auto bind(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> bool;
|
||||||
auto poll() -> int16;
|
auto poll() -> int16;
|
||||||
auto rumble(bool enable) -> void;
|
auto rumble(bool enable) -> void;
|
||||||
auto unbind() -> void;
|
auto unbind() -> void;
|
||||||
|
@ -17,14 +17,14 @@ struct InputMapping {
|
||||||
string assignment = "None";
|
string assignment = "None";
|
||||||
Emulator::Interface::Device::Input* link = nullptr;
|
Emulator::Interface::Device::Input* link = nullptr;
|
||||||
shared_pointer<HID::Device> device;
|
shared_pointer<HID::Device> device;
|
||||||
unsigned group = 0;
|
uint group = 0;
|
||||||
unsigned input = 0;
|
uint input = 0;
|
||||||
enum class Qualifier : unsigned { None, Lo, Hi, Rumble } qualifier = Qualifier::None;
|
enum class Qualifier : uint { None, Lo, Hi, Rumble } qualifier = Qualifier::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputHotkey : InputMapping {
|
struct InputHotkey : InputMapping {
|
||||||
function<void ()> press;
|
function<auto () -> void> press;
|
||||||
function<void ()> release;
|
function<auto () -> void> release;
|
||||||
|
|
||||||
int16 state = 0;
|
int16 state = 0;
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,7 @@ struct InputManager {
|
||||||
InputManager();
|
InputManager();
|
||||||
auto bind() -> void;
|
auto bind() -> void;
|
||||||
auto poll() -> void;
|
auto poll() -> void;
|
||||||
auto onChange(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void;
|
auto onChange(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> void;
|
||||||
auto quit() -> void;
|
auto quit() -> void;
|
||||||
|
|
||||||
auto findMouse() -> shared_pointer<HID::Device>;
|
auto findMouse() -> shared_pointer<HID::Device>;
|
||||||
|
|
|
@ -156,20 +156,20 @@ auto Presentation::updateEmulator() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Presentation::resizeViewport() -> void {
|
auto Presentation::resizeViewport() -> void {
|
||||||
signed width = emulator ? emulator->information.width : 256;
|
int width = emulator ? emulator->information.width : 256;
|
||||||
signed height = emulator ? emulator->information.height : 240;
|
int height = emulator ? emulator->information.height : 240;
|
||||||
double stretch = emulator ? emulator->information.aspectRatio : 1.0;
|
double stretch = emulator ? emulator->information.aspectRatio : 1.0;
|
||||||
if(stretch != 1.0) {
|
if(stretch != 1.0) {
|
||||||
//aspect correction is always enabled in fullscreen mode
|
//aspect correction is always enabled in fullscreen mode
|
||||||
if(!fullScreen() && !settings["Video/AspectCorrection"].boolean()) stretch = 1.0;
|
if(!fullScreen() && !settings["Video/AspectCorrection"].boolean()) stretch = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
signed scale = 2;
|
int scale = 2;
|
||||||
if(settings["Video/Scale"].text() == "Small" ) scale = 2;
|
if(settings["Video/Scale"].text() == "Small" ) scale = 2;
|
||||||
if(settings["Video/Scale"].text() == "Medium") scale = 3;
|
if(settings["Video/Scale"].text() == "Medium") scale = 3;
|
||||||
if(settings["Video/Scale"].text() == "Large" ) scale = 4;
|
if(settings["Video/Scale"].text() == "Large" ) scale = 4;
|
||||||
|
|
||||||
signed windowWidth = 0, windowHeight = 0;
|
int windowWidth = 0, windowHeight = 0;
|
||||||
if(!fullScreen()) {
|
if(!fullScreen()) {
|
||||||
windowWidth = 256 * scale * (settings["Video/AspectCorrection"].boolean() ? 8.0 / 7.0 : 1.0);
|
windowWidth = 256 * scale * (settings["Video/AspectCorrection"].boolean() ? 8.0 / 7.0 : 1.0);
|
||||||
windowHeight = 240 * scale;
|
windowHeight = 240 * scale;
|
||||||
|
@ -178,7 +178,7 @@ auto Presentation::resizeViewport() -> void {
|
||||||
windowHeight = geometry().height();
|
windowHeight = geometry().height();
|
||||||
}
|
}
|
||||||
|
|
||||||
signed multiplier = min(windowWidth / (signed)(width * stretch), windowHeight / height);
|
int multiplier = min(windowWidth / (int)(width * stretch), windowHeight / height);
|
||||||
width = width * multiplier * stretch;
|
width = width * multiplier * stretch;
|
||||||
height = height * multiplier;
|
height = height * multiplier;
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ auto Presentation::toggleFullScreen() -> void {
|
||||||
auto Presentation::drawSplashScreen() -> void {
|
auto Presentation::drawSplashScreen() -> void {
|
||||||
if(!video) return;
|
if(!video) return;
|
||||||
uint32* output;
|
uint32* output;
|
||||||
unsigned length;
|
uint length;
|
||||||
if(video->lock(output, length, 256, 240)) {
|
if(video->lock(output, length, 256, 240)) {
|
||||||
for(auto y : range(240)) {
|
for(auto y : range(240)) {
|
||||||
uint32* dp = output + y * (length >> 2);
|
uint32* dp = output + y * (length >> 2);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//request from emulation core to load non-volatile media folder
|
//request from emulation core to load non-volatile media folder
|
||||||
auto Program::loadRequest(unsigned id, string name, string type, bool required) -> void {
|
auto Program::loadRequest(uint id, string name, string type, bool required) -> void {
|
||||||
string location = BrowserDialog()
|
string location = BrowserDialog()
|
||||||
.setTitle({"Load ", name})
|
.setTitle({"Load ", name})
|
||||||
.setPath({settings["Library/Location"].text(), name})
|
.setPath({settings["Library/Location"].text(), name})
|
||||||
|
@ -13,22 +13,13 @@ auto Program::loadRequest(unsigned id, string name, string type, bool required)
|
||||||
}
|
}
|
||||||
|
|
||||||
//request from emulation core to load non-volatile media file
|
//request from emulation core to load non-volatile media file
|
||||||
auto Program::loadRequest(unsigned id, string filename, bool required) -> void {
|
auto Program::loadRequest(uint id, string filename, bool required) -> void {
|
||||||
string pathname = mediaPaths(emulator->group(id));
|
string pathname = mediaPaths(emulator->group(id));
|
||||||
string location = {pathname, filename};
|
string location = {pathname, filename};
|
||||||
|
|
||||||
if(filename == "manifest.bml" && !pathname.find(".sys/")) {
|
if(filename == "manifest.bml" && !pathname.find(".sys/")) {
|
||||||
if(!file::exists(location) || settings["Library/IgnoreManifests"].boolean()) {
|
if(!file::exists(location) || settings["Library/IgnoreManifests"].boolean()) {
|
||||||
string manifest;
|
if(auto manifest = execute("icarus", "-m", pathname)) {
|
||||||
if(auto fp = popen(string{"icarus -m \"", pathname, "\""}, "r")) {
|
|
||||||
while(true) {
|
|
||||||
auto byte = fgetc(fp);
|
|
||||||
if(byte == EOF) break;
|
|
||||||
manifest.append((char)byte);
|
|
||||||
}
|
|
||||||
pclose(fp);
|
|
||||||
}
|
|
||||||
if(manifest) {
|
|
||||||
memorystream stream{(const uint8*)manifest.data(), manifest.size()};
|
memorystream stream{(const uint8*)manifest.data(), manifest.size()};
|
||||||
return emulator->load(id, stream);
|
return emulator->load(id, stream);
|
||||||
}
|
}
|
||||||
|
@ -47,14 +38,14 @@ auto Program::loadRequest(unsigned id, string filename, bool required) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
//request from emulation core to save non-volatile media file
|
//request from emulation core to save non-volatile media file
|
||||||
auto Program::saveRequest(unsigned id, string filename) -> void {
|
auto Program::saveRequest(uint id, string filename) -> void {
|
||||||
string pathname = mediaPaths(emulator->group(id));
|
string pathname = mediaPaths(emulator->group(id));
|
||||||
string location = {pathname, filename};
|
string location = {pathname, filename};
|
||||||
filestream stream{location, file::mode::write};
|
filestream stream{location, file::mode::write};
|
||||||
return emulator->save(id, stream);
|
return emulator->save(id, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::videoColor(unsigned source, uint16 a, uint16 r, uint16 g, uint16 b) -> uint32 {
|
auto Program::videoColor(uint source, uint16 a, uint16 r, uint16 g, uint16 b) -> uint32 {
|
||||||
if(settings["Video/Saturation"].natural() != 100) {
|
if(settings["Video/Saturation"].natural() != 100) {
|
||||||
uint16 grayscale = uclamp<16>((r + g + b) / 3);
|
uint16 grayscale = uclamp<16>((r + g + b) / 3);
|
||||||
double saturation = settings["Video/Saturation"].natural() * 0.01;
|
double saturation = settings["Video/Saturation"].natural() * 0.01;
|
||||||
|
@ -86,9 +77,9 @@ auto Program::videoColor(unsigned source, uint16 a, uint16 r, uint16 g, uint16 b
|
||||||
return a << 24 | r << 16 | g << 8 | b << 0;
|
return a << 24 | r << 16 | g << 8 | b << 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned pitch, unsigned width, unsigned height) -> void {
|
auto Program::videoRefresh(const uint32* palette, const uint32* data, uint pitch, uint width, uint height) -> void {
|
||||||
uint32* output;
|
uint32* output;
|
||||||
unsigned length;
|
uint length;
|
||||||
|
|
||||||
if(video->lock(output, length, width, height)) {
|
if(video->lock(output, length, width, height)) {
|
||||||
pitch >>= 2, length >>= 2;
|
pitch >>= 2, length >>= 2;
|
||||||
|
@ -120,7 +111,7 @@ auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned p
|
||||||
video->refresh();
|
video->refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned frameCounter = 0;
|
static uint frameCounter = 0;
|
||||||
static time_t previous, current;
|
static time_t previous, current;
|
||||||
frameCounter++;
|
frameCounter++;
|
||||||
|
|
||||||
|
@ -133,7 +124,7 @@ auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned p
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::audioSample(int16 lsample, int16 rsample) -> void {
|
auto Program::audioSample(int16 lsample, int16 rsample) -> void {
|
||||||
signed samples[] = {lsample, rsample};
|
int samples[] = {lsample, rsample};
|
||||||
dsp.sample(samples);
|
dsp.sample(samples);
|
||||||
while(dsp.pending()) {
|
while(dsp.pending()) {
|
||||||
dsp.read(samples);
|
dsp.read(samples);
|
||||||
|
@ -141,7 +132,7 @@ auto Program::audioSample(int16 lsample, int16 rsample) -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::inputPoll(unsigned port, unsigned device, unsigned input) -> int16 {
|
auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
|
||||||
if(presentation->focused()) {
|
if(presentation->focused()) {
|
||||||
auto guid = emulator->port[port].device[device].input[input].guid;
|
auto guid = emulator->port[port].device[device].input[input].guid;
|
||||||
auto mapping = (InputMapping*)guid;
|
auto mapping = (InputMapping*)guid;
|
||||||
|
@ -150,7 +141,7 @@ auto Program::inputPoll(unsigned port, unsigned device, unsigned input) -> int16
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void {
|
auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void {
|
||||||
if(presentation->focused() || !enable) {
|
if(presentation->focused() || !enable) {
|
||||||
auto guid = emulator->port[port].device[device].input[input].guid;
|
auto guid = emulator->port[port].device[device].input[input].guid;
|
||||||
auto mapping = (InputMapping*)guid;
|
auto mapping = (InputMapping*)guid;
|
||||||
|
@ -158,10 +149,10 @@ auto Program::inputRumble(unsigned port, unsigned device, unsigned input, bool e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::dipSettings(const Markup::Node& node) -> unsigned {
|
auto Program::dipSettings(const Markup::Node& node) -> uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::path(unsigned group) -> string {
|
auto Program::path(uint group) -> string {
|
||||||
return mediaPaths(group);
|
return mediaPaths(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,16 @@ struct Program : Emulator::Interface::Bind {
|
||||||
auto quit() -> void;
|
auto quit() -> void;
|
||||||
|
|
||||||
//interface.cpp
|
//interface.cpp
|
||||||
auto loadRequest(unsigned id, string name, string type, bool required) -> void override;
|
auto loadRequest(uint id, string name, string type, bool required) -> void override;
|
||||||
auto loadRequest(unsigned id, string path, bool required) -> void override;
|
auto loadRequest(uint id, string path, bool required) -> void override;
|
||||||
auto saveRequest(unsigned id, string path) -> void override;
|
auto saveRequest(uint id, string path) -> void override;
|
||||||
auto videoColor(unsigned source, uint16 alpha, uint16 red, uint16 green, uint16 blue) -> uint32 override;
|
auto videoColor(uint source, uint16 alpha, uint16 red, uint16 green, uint16 blue) -> uint32 override;
|
||||||
auto videoRefresh(const uint32* palette, const uint32* data, unsigned pitch, unsigned width, unsigned height) -> void override;
|
auto videoRefresh(const uint32* palette, const uint32* data, uint pitch, uint width, uint height) -> void override;
|
||||||
auto audioSample(int16 lsample, int16 rsample) -> void override;
|
auto audioSample(int16 lsample, int16 rsample) -> void override;
|
||||||
auto inputPoll(unsigned port, unsigned device, unsigned input) -> int16 override;
|
auto inputPoll(uint port, uint device, uint input) -> int16 override;
|
||||||
auto inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void override;
|
auto inputRumble(uint port, uint device, uint input, bool enable) -> void override;
|
||||||
auto dipSettings(const Markup::Node& node) -> unsigned override;
|
auto dipSettings(const Markup::Node& node) -> uint override;
|
||||||
auto path(unsigned group) -> string override;
|
auto path(uint group) -> string override;
|
||||||
auto notify(string text) -> void override;
|
auto notify(string text) -> void override;
|
||||||
|
|
||||||
//media.cpp
|
//media.cpp
|
||||||
|
@ -23,9 +23,9 @@ struct Program : Emulator::Interface::Bind {
|
||||||
auto unloadMedia() -> void;
|
auto unloadMedia() -> void;
|
||||||
|
|
||||||
//state.cpp
|
//state.cpp
|
||||||
auto stateName(unsigned slot, bool manager = false) -> string;
|
auto stateName(uint slot, bool manager = false) -> string;
|
||||||
auto loadState(unsigned slot, bool manager = false) -> bool;
|
auto loadState(uint slot, bool manager = false) -> bool;
|
||||||
auto saveState(unsigned slot, bool manager = false) -> bool;
|
auto saveState(uint slot, bool manager = false) -> bool;
|
||||||
|
|
||||||
//utility.cpp
|
//utility.cpp
|
||||||
auto powerCycle() -> void;
|
auto powerCycle() -> void;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
auto Program::stateName(unsigned slot, bool manager) -> string {
|
auto Program::stateName(uint slot, bool manager) -> string {
|
||||||
return {
|
return {
|
||||||
folderPaths[0], "higan/states/",
|
folderPaths[0], "higan/states/",
|
||||||
manager ? "managed/" : "quick/",
|
manager ? "managed/" : "quick/",
|
||||||
|
@ -6,7 +6,7 @@ auto Program::stateName(unsigned slot, bool manager) -> string {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::loadState(unsigned slot, bool manager) -> bool {
|
auto Program::loadState(uint slot, bool manager) -> bool {
|
||||||
if(!emulator) return false;
|
if(!emulator) return false;
|
||||||
auto location = stateName(slot, manager);
|
auto location = stateName(slot, manager);
|
||||||
auto memory = file::read(location);
|
auto memory = file::read(location);
|
||||||
|
@ -16,7 +16,7 @@ auto Program::loadState(unsigned slot, bool manager) -> bool {
|
||||||
return showMessage({"Loaded from slot ", slot}), true;
|
return showMessage({"Loaded from slot ", slot}), true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::saveState(unsigned slot, bool manager) -> bool {
|
auto Program::saveState(uint slot, bool manager) -> bool {
|
||||||
if(!emulator) return false;
|
if(!emulator) return false;
|
||||||
auto location = stateName(slot, manager);
|
auto location = stateName(slot, manager);
|
||||||
serializer s = emulator->serialize();
|
serializer s = emulator->serialize();
|
||||||
|
|
|
@ -42,7 +42,7 @@ auto HotkeySettings::reloadMappings() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HotkeySettings::refreshMappings() -> void {
|
auto HotkeySettings::refreshMappings() -> void {
|
||||||
unsigned position = 0;
|
uint position = 0;
|
||||||
for(auto& hotkey : inputManager->hotkeys) {
|
for(auto& hotkey : inputManager->hotkeys) {
|
||||||
mappingList.item(position)->cell(1)->setText(hotkey->assignmentName());
|
mappingList.item(position)->cell(1)->setText(hotkey->assignmentName());
|
||||||
mappingList.item(position)->cell(2)->setText(hotkey->deviceName());
|
mappingList.item(position)->cell(2)->setText(hotkey->deviceName());
|
||||||
|
@ -61,7 +61,7 @@ auto HotkeySettings::assignMapping() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto HotkeySettings::inputEvent(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void {
|
auto HotkeySettings::inputEvent(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> void {
|
||||||
if(!activeMapping) return;
|
if(!activeMapping) return;
|
||||||
if(device->isMouse()) return;
|
if(device->isMouse()) return;
|
||||||
|
|
||||||
|
|
|
@ -51,15 +51,16 @@ auto InputSettings::updateControls() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::activeEmulator() -> InputEmulator& {
|
auto InputSettings::activeEmulator() -> InputEmulator& {
|
||||||
return inputManager->emulators[emulatorList.selected()->offset()];
|
return inputManager->emulators[emulatorList.selected().offset()];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::activePort() -> InputPort& {
|
auto InputSettings::activePort() -> InputPort& {
|
||||||
return activeEmulator().ports[portList.selected()->offset()];
|
return activeEmulator().ports[portList.selected().offset()];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::activeDevice() -> InputDevice& {
|
auto InputSettings::activeDevice() -> InputDevice& {
|
||||||
return activePort().devices[deviceList.selected()->offset()];
|
auto index = deviceList.selected().property("index").natural();
|
||||||
|
return activePort().devices[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::reloadPorts() -> void {
|
auto InputSettings::reloadPorts() -> void {
|
||||||
|
@ -72,8 +73,10 @@ auto InputSettings::reloadPorts() -> void {
|
||||||
|
|
||||||
auto InputSettings::reloadDevices() -> void {
|
auto InputSettings::reloadDevices() -> void {
|
||||||
deviceList.reset();
|
deviceList.reset();
|
||||||
for(auto& device : activePort().devices) {
|
for(auto n : range(activePort().devices)) {
|
||||||
deviceList.append(ComboButtonItem().setText(device.name));
|
auto& device = activePort().devices[n];
|
||||||
|
if(!device.mappings) continue; //do not display devices that have no configurable inputs
|
||||||
|
deviceList.append(ComboButtonItem().setText(device.name).setProperty("index", n));
|
||||||
}
|
}
|
||||||
reloadMappings();
|
reloadMappings();
|
||||||
}
|
}
|
||||||
|
@ -97,7 +100,7 @@ auto InputSettings::reloadMappings() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::refreshMappings() -> void {
|
auto InputSettings::refreshMappings() -> void {
|
||||||
unsigned position = 0;
|
uint position = 0;
|
||||||
for(auto& mapping : activeDevice().mappings) {
|
for(auto& mapping : activeDevice().mappings) {
|
||||||
mappingList.item(position)->cell(1)->setText(mapping->assignmentName());
|
mappingList.item(position)->cell(1)->setText(mapping->assignmentName());
|
||||||
mappingList.item(position)->cell(2)->setText(mapping->deviceName());
|
mappingList.item(position)->cell(2)->setText(mapping->deviceName());
|
||||||
|
@ -116,7 +119,7 @@ auto InputSettings::assignMapping() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::assignMouseInput(unsigned id) -> void {
|
auto InputSettings::assignMouseInput(uint id) -> void {
|
||||||
if(auto mouse = inputManager->findMouse()) {
|
if(auto mouse = inputManager->findMouse()) {
|
||||||
if(auto mapping = mappingList.selected()) {
|
if(auto mapping = mappingList.selected()) {
|
||||||
activeMapping = activeDevice().mappings[mapping->offset()];
|
activeMapping = activeDevice().mappings[mapping->offset()];
|
||||||
|
@ -130,7 +133,7 @@ auto InputSettings::assignMouseInput(unsigned id) -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto InputSettings::inputEvent(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue, bool allowMouseInput) -> void {
|
auto InputSettings::inputEvent(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue, bool allowMouseInput) -> void {
|
||||||
if(!activeMapping) return;
|
if(!activeMapping) return;
|
||||||
if(device->isMouse() && !allowMouseInput) return;
|
if(device->isMouse() && !allowMouseInput) return;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ auto SettingsManager::setVisible(bool visible) -> SettingsManager& {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SettingsManager::show(unsigned setting) -> void {
|
auto SettingsManager::show(uint setting) -> void {
|
||||||
panel.item(setting)->setSelected();
|
panel.item(setting)->setSelected();
|
||||||
setVisible();
|
setVisible();
|
||||||
setFocused();
|
setFocused();
|
||||||
|
|
|
@ -59,8 +59,8 @@ struct InputSettings : TabFrameItem {
|
||||||
auto reloadMappings() -> void;
|
auto reloadMappings() -> void;
|
||||||
auto refreshMappings() -> void;
|
auto refreshMappings() -> void;
|
||||||
auto assignMapping() -> void;
|
auto assignMapping() -> void;
|
||||||
auto assignMouseInput(unsigned id) -> void;
|
auto assignMouseInput(uint id) -> void;
|
||||||
auto inputEvent(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue, bool allowMouseInput = false) -> void;
|
auto inputEvent(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue, bool allowMouseInput = false) -> void;
|
||||||
|
|
||||||
InputMapping* activeMapping = nullptr;
|
InputMapping* activeMapping = nullptr;
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ struct HotkeySettings : TabFrameItem {
|
||||||
auto reloadMappings() -> void;
|
auto reloadMappings() -> void;
|
||||||
auto refreshMappings() -> void;
|
auto refreshMappings() -> void;
|
||||||
auto assignMapping() -> void;
|
auto assignMapping() -> void;
|
||||||
auto inputEvent(shared_pointer<HID::Device> device, unsigned group, unsigned input, int16 oldValue, int16 newValue) -> void;
|
auto inputEvent(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> void;
|
||||||
|
|
||||||
InputMapping* activeMapping = nullptr;
|
InputMapping* activeMapping = nullptr;
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ struct AdvancedSettings : TabFrameItem {
|
||||||
struct SettingsManager : Window {
|
struct SettingsManager : Window {
|
||||||
SettingsManager();
|
SettingsManager();
|
||||||
auto setVisible(bool visible = true) -> SettingsManager&;
|
auto setVisible(bool visible = true) -> SettingsManager&;
|
||||||
auto show(unsigned setting) -> void;
|
auto show(uint setting) -> void;
|
||||||
|
|
||||||
VerticalLayout layout{this};
|
VerticalLayout layout{this};
|
||||||
TabFrame panel{&layout, Size{~0, ~0}};
|
TabFrame panel{&layout, Size{~0, ~0}};
|
||||||
|
|
|
@ -140,7 +140,7 @@ auto CheatEditor::loadCheats() -> void {
|
||||||
auto CheatEditor::saveCheats() -> void {
|
auto CheatEditor::saveCheats() -> void {
|
||||||
if(!emulator) return;
|
if(!emulator) return;
|
||||||
string document = {"cartridge sha256:", emulator->sha256(), "\n"};
|
string document = {"cartridge sha256:", emulator->sha256(), "\n"};
|
||||||
unsigned count = 0;
|
uint count = 0;
|
||||||
for(auto& cheat : cheats) {
|
for(auto& cheat : cheats) {
|
||||||
if(!cheat.code && !cheat.description) continue;
|
if(!cheat.code && !cheat.description) continue;
|
||||||
document.append(" cheat", cheat.enabled ? " enabled" : "", "\n");
|
document.append(" cheat", cheat.enabled ? " enabled" : "", "\n");
|
||||||
|
|
|
@ -22,7 +22,7 @@ ToolsManager::ToolsManager() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ToolsManager::show(unsigned tool) -> void {
|
auto ToolsManager::show(uint tool) -> void {
|
||||||
panel.item(tool)->setSelected();
|
panel.item(tool)->setSelected();
|
||||||
setVisible();
|
setVisible();
|
||||||
setFocused();
|
setFocused();
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct CheatDatabase : Window {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CheatEditor : TabFrameItem {
|
struct CheatEditor : TabFrameItem {
|
||||||
enum : unsigned { Slots = 128 };
|
enum : uint { Slots = 128 };
|
||||||
|
|
||||||
CheatEditor(TabFrame*);
|
CheatEditor(TabFrame*);
|
||||||
auto doChangeSelected() -> void;
|
auto doChangeSelected() -> void;
|
||||||
|
@ -51,7 +51,7 @@ struct CheatEditor : TabFrameItem {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StateManager : TabFrameItem {
|
struct StateManager : TabFrameItem {
|
||||||
enum : unsigned { Slots = 32 };
|
enum : uint { Slots = 32 };
|
||||||
|
|
||||||
StateManager(TabFrame*);
|
StateManager(TabFrame*);
|
||||||
auto doChangeSelected() -> void;
|
auto doChangeSelected() -> void;
|
||||||
|
@ -86,7 +86,7 @@ struct ManifestViewer : TabFrameItem {
|
||||||
|
|
||||||
struct ToolsManager : Window {
|
struct ToolsManager : Window {
|
||||||
ToolsManager();
|
ToolsManager();
|
||||||
auto show(unsigned tool) -> void;
|
auto show(uint tool) -> void;
|
||||||
|
|
||||||
VerticalLayout layout{this};
|
VerticalLayout layout{this};
|
||||||
TabFrame panel{&layout, Size{~0, ~0}};
|
TabFrame panel{&layout, Size{~0, ~0}};
|
||||||
|
|
Loading…
Reference in New Issue