mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-09 04:06:40 +02:00
Update to v085r02 release.
byuu says: Fixed NSS XML crashing issue. Improved folder-loading support. NES can now load game.fc/game.fc, or game.fc/game.prg+game.chr. Both types should have no iNES header at all. And both types require an XML file (until we have a built-in database.)
This commit is contained in:
@@ -45,8 +45,8 @@ void Cartridge::load(System::Revision revision, const string &markup, const uint
|
|||||||
info.rtc = document["cartridge"]["rtc"].data == "true";
|
info.rtc = document["cartridge"]["rtc"].data == "true";
|
||||||
info.rumble = document["cartridge"]["rumble"].data == "true";
|
info.rumble = document["cartridge"]["rumble"].data == "true";
|
||||||
|
|
||||||
info.romsize = hex(document["cartridge"]["rom"]["size"].data);
|
info.romsize = numeral(document["cartridge"]["rom"]["size"].data);
|
||||||
info.ramsize = hex(document["cartridge"]["ram"]["size"].data);
|
info.ramsize = numeral(document["cartridge"]["ram"]["size"].data);
|
||||||
info.battery = document["cartridge"]["ram"]["battery"].data == "true";
|
info.battery = document["cartridge"]["ram"]["battery"].data == "true";
|
||||||
|
|
||||||
switch(info.mapper) { default:
|
switch(info.mapper) { default:
|
||||||
|
@@ -2,17 +2,15 @@
|
|||||||
#define NALL_ANY_HPP
|
#define NALL_ANY_HPP
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <type_traits>
|
#include <nall/type_traits.hpp>
|
||||||
#include <nall/static.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
class any {
|
struct any {
|
||||||
public:
|
|
||||||
bool empty() const { return container; }
|
bool empty() const { return container; }
|
||||||
const std::type_info& type() const { return container ? container->type() : typeid(void); }
|
const std::type_info& type() const { return container ? container->type() : typeid(void); }
|
||||||
|
|
||||||
template<typename T> any& operator=(const T& value_) {
|
template<typename T> any& operator=(const T& value_) {
|
||||||
typedef typename static_if<
|
typedef typename type_if<
|
||||||
std::is_array<T>::value,
|
std::is_array<T>::value,
|
||||||
typename std::remove_extent<typename std::add_const<T>::type>::type*,
|
typename std::remove_extent<typename std::add_const<T>::type>::type*,
|
||||||
T
|
T
|
||||||
|
@@ -4,143 +4,286 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
|
#include <nall/sort.hpp>
|
||||||
|
#include <nall/type_traits.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
//dynamic vector array
|
|
||||||
//neither constructor nor destructor is ever invoked;
|
|
||||||
//thus, this should only be used for POD objects.
|
|
||||||
template<typename T> class array {
|
|
||||||
protected:
|
|
||||||
T *pool;
|
|
||||||
unsigned poolsize, buffersize;
|
|
||||||
|
|
||||||
public:
|
template<typename T, typename Enable = void> struct array;
|
||||||
unsigned size() const { return buffersize; }
|
|
||||||
unsigned capacity() const { return poolsize; }
|
|
||||||
|
|
||||||
void reset() {
|
//non-reference array
|
||||||
if(pool) free(pool);
|
//===================
|
||||||
pool = nullptr;
|
|
||||||
poolsize = 0;
|
template<typename T> struct array<T, typename std::enable_if<!std::is_reference<T>::value>::type> {
|
||||||
buffersize = 0;
|
struct exception_out_of_bounds{};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T *pool;
|
||||||
|
unsigned poolsize, objectsize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned size() const { return objectsize; }
|
||||||
|
unsigned capacity() const { return poolsize; }
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if(pool) free(pool);
|
||||||
|
pool = nullptr;
|
||||||
|
poolsize = 0;
|
||||||
|
objectsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(unsigned newsize) {
|
||||||
|
if(newsize == poolsize) return;
|
||||||
|
|
||||||
|
pool = (T*)realloc(pool, newsize * sizeof(T));
|
||||||
|
poolsize = newsize;
|
||||||
|
objectsize = min(objectsize, newsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(unsigned newsize) {
|
||||||
|
if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2
|
||||||
|
objectsize = newsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get(unsigned minsize = 0) {
|
||||||
|
if(minsize > objectsize) resize(minsize);
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const T data) {
|
||||||
|
operator()(objectsize) = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const T data[], unsigned length) {
|
||||||
|
for(unsigned n = 0; n < length; n++) operator()(objectsize) = data[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove() {
|
||||||
|
if(size > 0) resize(size - 1); //remove last element only
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(unsigned index, unsigned count = 1) {
|
||||||
|
for(unsigned i = index; count + i < objectsize; i++) {
|
||||||
|
pool[i] = pool[count + i];
|
||||||
}
|
}
|
||||||
|
if(count + index >= objectsize) resize(index); //every element >= index was removed
|
||||||
|
else resize(objectsize - count);
|
||||||
|
}
|
||||||
|
|
||||||
void reserve(unsigned newsize) {
|
void sort() {
|
||||||
if(newsize == poolsize) return;
|
nall::sort(pool, objectsize);
|
||||||
|
}
|
||||||
|
|
||||||
pool = (T*)realloc(pool, newsize * sizeof(T));
|
template<typename Comparator> void sort(const Comparator &lessthan) {
|
||||||
poolsize = newsize;
|
nall::sort(pool, objectsize, lessthan);
|
||||||
buffersize = min(buffersize, newsize);
|
}
|
||||||
|
|
||||||
|
optional<unsigned> find(const T data) {
|
||||||
|
for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return { true, n };
|
||||||
|
return { false, 0u };
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
memset(pool, 0, objectsize * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
array() : pool(nullptr), poolsize(0), objectsize(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
array(std::initializer_list<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
|
||||||
|
for(auto &data : list) append(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
~array() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//copy
|
||||||
|
array& operator=(const array &source) {
|
||||||
|
if(pool) free(pool);
|
||||||
|
objectsize = source.objectsize;
|
||||||
|
poolsize = source.poolsize;
|
||||||
|
pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size,
|
||||||
|
memcpy(pool, source.pool, sizeof(T) * objectsize); //... but only copy used pool objects
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
array(const array &source) : pool(nullptr), poolsize(0), objectsize(0) {
|
||||||
|
operator=(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
//move
|
||||||
|
array& operator=(array &&source) {
|
||||||
|
if(pool) free(pool);
|
||||||
|
pool = source.pool;
|
||||||
|
poolsize = source.poolsize;
|
||||||
|
objectsize = source.objectsize;
|
||||||
|
source.pool = nullptr;
|
||||||
|
source.reset();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
array(array &&source) : pool(nullptr), poolsize(0), objectsize(0) {
|
||||||
|
operator=(std::move(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
//access
|
||||||
|
inline T& operator[](unsigned position) {
|
||||||
|
if(position >= objectsize) throw exception_out_of_bounds();
|
||||||
|
return pool[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const T& operator[](unsigned position) const {
|
||||||
|
if(position >= objectsize) throw exception_out_of_bounds();
|
||||||
|
return pool[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T& operator()(unsigned position) {
|
||||||
|
if(position >= objectsize) resize(position + 1);
|
||||||
|
return pool[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const T& operator()(unsigned position, const T& data) {
|
||||||
|
if(position >= objectsize) return data;
|
||||||
|
return pool[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
//iteration
|
||||||
|
T* begin() { return &pool[0]; }
|
||||||
|
T* end() { return &pool[objectsize]; }
|
||||||
|
const T* begin() const { return &pool[0]; }
|
||||||
|
const T* end() const { return &pool[objectsize]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//reference array
|
||||||
|
//===============
|
||||||
|
|
||||||
|
template<typename TR> struct array<TR, typename std::enable_if<std::is_reference<TR>::value>::type> {
|
||||||
|
struct exception_out_of_bounds{};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef typename std::remove_reference<TR>::type T;
|
||||||
|
T **pool;
|
||||||
|
unsigned poolsize, objectsize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned size() const { return objectsize; }
|
||||||
|
unsigned capacity() const { return poolsize; }
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if(pool) free(pool);
|
||||||
|
pool = nullptr;
|
||||||
|
poolsize = 0;
|
||||||
|
objectsize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(unsigned newsize) {
|
||||||
|
if(newsize == poolsize) return;
|
||||||
|
|
||||||
|
pool = (T**)realloc(pool, sizeof(T*) * newsize);
|
||||||
|
poolsize = newsize;
|
||||||
|
objectsize = min(objectsize, newsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(unsigned newsize) {
|
||||||
|
if(newsize > poolsize) reserve(bit::round(newsize));
|
||||||
|
objectsize = newsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool append(T& data, Args&&... args) {
|
||||||
|
bool result = append(data);
|
||||||
|
append(std::forward<Args>(args)...);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool append(T& data) {
|
||||||
|
if(find(data)) return false;
|
||||||
|
unsigned offset = objectsize++;
|
||||||
|
if(offset >= poolsize) resize(offset + 1);
|
||||||
|
pool[offset] = &data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(T& data) {
|
||||||
|
if(auto position = find(data)) {
|
||||||
|
for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1];
|
||||||
|
resize(objectsize - 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void resize(unsigned newsize) {
|
optional<unsigned> find(const T& data) {
|
||||||
if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2
|
for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return { true, n };
|
||||||
buffersize = newsize;
|
return { false, 0u };
|
||||||
}
|
}
|
||||||
|
|
||||||
T* get(unsigned minsize = 0) {
|
template<typename... Args> array(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) {
|
||||||
if(minsize > buffersize) resize(minsize);
|
construct(std::forward<Args>(args)...);
|
||||||
if(minsize > buffersize) throw "array[] out of bounds";
|
}
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const T data) {
|
~array() {
|
||||||
operator[](buffersize) = data;
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const T data[], unsigned length) {
|
array& operator=(const array &source) {
|
||||||
for(unsigned n = 0; n < length; n++) operator[](buffersize) = data[n];
|
if(pool) free(pool);
|
||||||
}
|
objectsize = source.objectsize;
|
||||||
|
poolsize = source.poolsize;
|
||||||
|
pool = (T**)malloc(sizeof(T*) * poolsize);
|
||||||
|
memcpy(pool, source.pool, sizeof(T*) * objectsize);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void remove() {
|
array& operator=(const array &&source) {
|
||||||
if(size > 0) resize(size - 1); //remove last element only
|
if(pool) free(pool);
|
||||||
}
|
pool = source.pool;
|
||||||
|
poolsize = source.poolsize;
|
||||||
|
objectsize = source.objectsize;
|
||||||
|
source.pool = nullptr;
|
||||||
|
source.reset();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void remove(unsigned index, unsigned count = 1) {
|
T& operator[](unsigned position) const {
|
||||||
for(unsigned i = index; count + i < buffersize; i++) {
|
if(position >= objectsize) throw exception_out_of_bounds();
|
||||||
pool[i] = pool[count + i];
|
return *pool[position];
|
||||||
}
|
}
|
||||||
if(count + index >= buffersize) resize(index); //every element >= index was removed
|
|
||||||
else resize(buffersize - count);
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<unsigned> find(const T data) {
|
//iteration
|
||||||
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return { true, i };
|
struct iterator {
|
||||||
return { false, 0 };
|
bool operator!=(const iterator &source) const { return position != source.position; }
|
||||||
}
|
T& operator*() { return source.operator[](position); }
|
||||||
|
iterator& operator++() { position++; return *this; }
|
||||||
void clear() {
|
iterator(const array &source, unsigned position) : source(source), position(position) {}
|
||||||
memset(pool, 0, buffersize * sizeof(T));
|
private:
|
||||||
}
|
const array &source;
|
||||||
|
unsigned position;
|
||||||
array() : pool(nullptr), poolsize(0), buffersize(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
array(std::initializer_list<T> list) : pool(nullptr), poolsize(0), buffersize(0) {
|
|
||||||
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
|
|
||||||
}
|
|
||||||
|
|
||||||
~array() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy
|
|
||||||
array& operator=(const array &source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
buffersize = source.buffersize;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size,
|
|
||||||
memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
array(const array &source) : pool(nullptr), poolsize(0), buffersize(0) {
|
|
||||||
operator=(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
//move
|
|
||||||
array& operator=(array &&source) {
|
|
||||||
if(pool) free(pool);
|
|
||||||
pool = source.pool;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
buffersize = source.buffersize;
|
|
||||||
source.pool = nullptr;
|
|
||||||
source.reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
array(array &&source) : pool(nullptr), poolsize(0), buffersize(0) {
|
|
||||||
operator=(std::move(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
//access
|
|
||||||
inline T& operator[](unsigned position) {
|
|
||||||
if(position >= buffersize) resize(position + 1);
|
|
||||||
if(position >= buffersize) throw "array[] out of bounds";
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T& operator[](unsigned position) const {
|
|
||||||
if(position >= buffersize) throw "array[] out of bounds";
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const T& operator()(unsigned position, const T& data) {
|
|
||||||
if(position >= buffersize) return data;
|
|
||||||
return pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
//iteration
|
|
||||||
T* begin() { return &pool[0]; }
|
|
||||||
T* end() { return &pool[buffersize]; }
|
|
||||||
const T* begin() const { return &pool[0]; }
|
|
||||||
const T* end() const { return &pool[buffersize]; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
iterator begin() { return iterator(*this, 0); }
|
||||||
|
iterator end() { return iterator(*this, objectsize); }
|
||||||
|
const iterator begin() const { return iterator(*this, 0); }
|
||||||
|
const iterator end() const { return iterator(*this, objectsize); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void construct(const array& source) { operator=(source); }
|
||||||
|
void construct(const array&& source) { operator=(std::move(source)); }
|
||||||
|
|
||||||
|
template<typename... Args> void construct(T& data, Args&&... args) {
|
||||||
|
append(data);
|
||||||
|
construct(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -79,6 +79,19 @@ constexpr inline uintmax_t hex(const char *s) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr inline intmax_t numeral(const char *s) {
|
||||||
|
return (
|
||||||
|
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
||||||
|
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
||||||
|
*s == '0' && *(s + 1) == 'B' ? binary_(s + 2) :
|
||||||
|
*s == '0' && *(s + 1) == 'b' ? binary_(s + 2) :
|
||||||
|
*s == '0' ? octal_(s + 1) :
|
||||||
|
*s == '+' ? +decimal_(s + 1) :
|
||||||
|
*s == '-' ? -decimal_(s + 1) :
|
||||||
|
decimal_(s)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
inline double fp(const char *s) {
|
inline double fp(const char *s) {
|
||||||
return atof(s);
|
return atof(s);
|
||||||
}
|
}
|
||||||
|
@@ -53,21 +53,18 @@ namespace nall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
linear_vector<item_t> list;
|
vector<item_t> list;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void append(T &data, const char *name, const char *desc = "") {
|
inline void append(T &data, const char *name, const char *desc = "") {
|
||||||
unsigned n = list.size();
|
item_t item = { (uintptr_t)&data, name, desc };
|
||||||
list[n].data = (uintptr_t)&data;
|
if(configuration_traits::is_boolean<T>::value) item.type = boolean_t;
|
||||||
list[n].name = name;
|
else if(configuration_traits::is_signed<T>::value) item.type = signed_t;
|
||||||
list[n].desc = desc;
|
else if(configuration_traits::is_unsigned<T>::value) item.type = unsigned_t;
|
||||||
|
else if(configuration_traits::is_double<T>::value) item.type = double_t;
|
||||||
if(configuration_traits::is_boolean<T>::value) list[n].type = boolean_t;
|
else if(configuration_traits::is_string<T>::value) item.type = string_t;
|
||||||
else if(configuration_traits::is_signed<T>::value) list[n].type = signed_t;
|
else item.type = unknown_t;
|
||||||
else if(configuration_traits::is_unsigned<T>::value) list[n].type = unsigned_t;
|
list.append(item);
|
||||||
else if(configuration_traits::is_double<T>::value) list[n].type = double_t;
|
|
||||||
else if(configuration_traits::is_string<T>::value) list[n].type = string_t;
|
|
||||||
else list[n].type = unknown_t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//deprecated
|
//deprecated
|
||||||
|
@@ -56,7 +56,7 @@ struct directory {
|
|||||||
}
|
}
|
||||||
FindClose(handle);
|
FindClose(handle);
|
||||||
}
|
}
|
||||||
if(list.size() > 0) sort(&list[0], list.size());
|
if(list.size() > 0) list.sort();
|
||||||
for(auto &name : list) name.append("/"); //must append after sorting
|
for(auto &name : list) name.append("/"); //must append after sorting
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ struct directory {
|
|||||||
}
|
}
|
||||||
FindClose(handle);
|
FindClose(handle);
|
||||||
}
|
}
|
||||||
if(list.size() > 0) sort(&list[0], list.size());
|
if(list.size() > 0) list.sort();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ struct directory {
|
|||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
if(list.size() > 0) sort(&list[0], list.size());
|
if(list.size() > 0) list.sort();
|
||||||
for(auto &name : list) name.append("/"); //must append after sorting
|
for(auto &name : list) name.append("/"); //must append after sorting
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ struct directory {
|
|||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
if(list.size() > 0) sort(&list[0], list.size());
|
if(list.size() > 0) list.sort();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ struct image {
|
|||||||
inline image(const image &source);
|
inline image(const image &source);
|
||||||
inline image(image &&source);
|
inline image(image &&source);
|
||||||
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
||||||
|
inline image();
|
||||||
inline ~image();
|
inline ~image();
|
||||||
|
|
||||||
inline uint64_t read(const uint8_t *data) const;
|
inline uint64_t read(const uint8_t *data) const;
|
||||||
@@ -142,6 +143,20 @@ image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask,
|
|||||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image::image() : data(nullptr) {
|
||||||
|
width = 0, height = 0, pitch = 0;
|
||||||
|
|
||||||
|
this->endian = 0;
|
||||||
|
this->depth = 32;
|
||||||
|
this->stride = 4;
|
||||||
|
|
||||||
|
alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
|
||||||
|
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
||||||
|
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
||||||
|
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
||||||
|
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
||||||
|
}
|
||||||
|
|
||||||
image::~image() {
|
image::~image() {
|
||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
|
@@ -12,51 +12,74 @@ struct map {
|
|||||||
RHS data;
|
RHS data;
|
||||||
};
|
};
|
||||||
|
|
||||||
void reset() {
|
inline void reset() {
|
||||||
list.reset();
|
list.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned size() const {
|
inline unsigned size() const {
|
||||||
return list.size();
|
return list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
//O(n)
|
//O(log n) find
|
||||||
void append(const LHS &name, const RHS &data) {
|
inline optional<unsigned> find(const LHS &name) const {
|
||||||
|
signed first = 0, last = size() - 1;
|
||||||
|
while(first <= last) {
|
||||||
|
signed middle = (first + last) / 2;
|
||||||
|
if(name < list[middle].name) last = middle - 1; //search lower half
|
||||||
|
else if(list[middle].name < name) first = middle + 1; //search upper half
|
||||||
|
else return { true, middle }; //match found
|
||||||
|
}
|
||||||
|
return { false, 0u };
|
||||||
|
}
|
||||||
|
|
||||||
|
//O(n) insert + O(log n) find
|
||||||
|
inline RHS& insert(const LHS &name, const RHS &data) {
|
||||||
|
if(auto position = find(name)) {
|
||||||
|
list[position()].data = data;
|
||||||
|
return list[position()].data;
|
||||||
|
}
|
||||||
signed offset = size();
|
signed offset = size();
|
||||||
for(unsigned n = 0; n < size(); n++) {
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
if(name < list[n].name) { offset = n; break; }
|
if(name < list[n].name) { offset = n; break; }
|
||||||
}
|
}
|
||||||
list.insert(offset, { name, data });
|
list.insert(offset, { name, data });
|
||||||
|
return list[offset].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//O(log n)
|
//O(log n) find
|
||||||
RHS& operator[](const LHS &name) {
|
inline void modify(const LHS &name, const RHS &data) {
|
||||||
signed first = 0, last = size() - 1;
|
if(auto position = find(name)) list[position()].data = data;
|
||||||
while(first <= last) {
|
}
|
||||||
signed middle = (first + last) / 2;
|
|
||||||
if(name < list[middle].name) last = middle - 1; //search lower half
|
//O(n) remove + O(log n) find
|
||||||
else if(name > list[middle].name) first = middle + 1; //search upper half
|
inline void remove(const LHS &name) {
|
||||||
else return list[middle].data; //match found
|
if(auto position = find(name)) list.remove(position());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//O(log n) find
|
||||||
|
inline RHS& operator[](const LHS &name) {
|
||||||
|
if(auto position = find(name)) return list[position()].data;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
//O(log n) nothrow
|
inline const RHS& operator[](const LHS &name) const {
|
||||||
const RHS& operator()(const LHS &name, const RHS &data) {
|
if(auto position = find(name)) return list[position()].data;
|
||||||
signed first = 0, last = size() - 1;
|
throw;
|
||||||
while(first <= last) {
|
}
|
||||||
signed middle = (first + last) / 2;
|
|
||||||
if(name < list[middle].name) last = middle - 1; //search lower half
|
inline RHS& operator()(const LHS &name) {
|
||||||
else if(name > list[middle].name) first = middle + 1; //search upper half
|
return insert(name, RHS());
|
||||||
else return list[middle].data; //match found
|
}
|
||||||
}
|
|
||||||
|
inline const RHS& operator()(const LHS &name, const RHS &data) const {
|
||||||
|
if(auto position = find(name)) return list[position()].data;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair* begin() { return list.begin(); }
|
inline pair* begin() { return list.begin(); }
|
||||||
pair* end() { return list.end(); }
|
inline pair* end() { return list.end(); }
|
||||||
const pair* begin() const { return list.begin(); }
|
inline const pair* begin() const { return list.begin(); }
|
||||||
const pair* end() const { return list.end(); }
|
inline const pair* end() const { return list.end(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
vector<pair> list;
|
vector<pair> list;
|
||||||
@@ -64,22 +87,28 @@ protected:
|
|||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename LHS, typename RHS>
|
||||||
struct bidirectional_map {
|
struct bidirectional_map {
|
||||||
map<LHS, RHS> lhs;
|
const map<LHS, RHS> &lhs;
|
||||||
map<RHS, LHS> rhs;
|
const map<RHS, LHS> &rhs;
|
||||||
|
|
||||||
void reset() {
|
inline void reset() {
|
||||||
lhs.reset();
|
llist.reset();
|
||||||
rhs.reset();
|
rlist.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned size() const {
|
inline unsigned size() const {
|
||||||
return lhs.size();
|
return llist.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const LHS &ldata, const RHS &rdata) {
|
inline void insert(const LHS &ldata, const RHS &rdata) {
|
||||||
lhs.append(ldata, rdata);
|
llist.insert(ldata, rdata);
|
||||||
rhs.append(rdata, ldata);
|
rlist.insert(rdata, ldata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bidirectional_map() : lhs(llist), rhs(rlist) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
map<LHS, RHS> llist;
|
||||||
|
map<RHS, LHS> rlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,61 +0,0 @@
|
|||||||
#ifndef NALL_RESOURCE_HPP
|
|
||||||
#define NALL_RESOURCE_HPP
|
|
||||||
|
|
||||||
#include <nall/file.hpp>
|
|
||||||
#include <nall/zip.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct resource {
|
|
||||||
//create resource with "zip -9 resource.zip resource"
|
|
||||||
static bool encode(const char *outputFilename, const char *inputFilename) {
|
|
||||||
file fp;
|
|
||||||
if(fp.open(inputFilename, file::mode::read) == false) return false;
|
|
||||||
unsigned size = fp.size();
|
|
||||||
uint8_t *data = new uint8_t[size];
|
|
||||||
fp.read(data, size);
|
|
||||||
fp.close();
|
|
||||||
|
|
||||||
fp.open(outputFilename, file::mode::write);
|
|
||||||
fp.print("static const uint8_t data[", size, "] = {\n");
|
|
||||||
uint8_t *p = data;
|
|
||||||
while(size) {
|
|
||||||
fp.print(" ");
|
|
||||||
for(unsigned n = 0; n < 32 && size; n++, size--) {
|
|
||||||
fp.print((unsigned)*p++, ",");
|
|
||||||
}
|
|
||||||
fp.print("\n");
|
|
||||||
}
|
|
||||||
fp.print("};\n");
|
|
||||||
fp.close();
|
|
||||||
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *data;
|
|
||||||
unsigned size;
|
|
||||||
|
|
||||||
//extract first file from ZIP archive
|
|
||||||
bool decode(const uint8_t *cdata, unsigned csize) {
|
|
||||||
if(data) delete[] data;
|
|
||||||
|
|
||||||
zip archive;
|
|
||||||
if(archive.open(cdata, csize) == false) return false;
|
|
||||||
if(archive.file.size() == 0) return false;
|
|
||||||
bool result = archive.extract(archive.file[0], data, size);
|
|
||||||
archive.close();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
resource() : data(0), size(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~resource() {
|
|
||||||
if(data) delete[] data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -11,53 +11,67 @@
|
|||||||
//stack: O(log n)
|
//stack: O(log n)
|
||||||
//stable?: yes
|
//stable?: yes
|
||||||
|
|
||||||
//notes:
|
//note: merge sort was chosen over quick sort, because:
|
||||||
//there are two primary reasons for choosing merge sort
|
//* it is a stable sort
|
||||||
//over the (usually) faster quick sort*:
|
//* it lacks O(n^2) worst-case overhead
|
||||||
//1: it is a stable sort.
|
|
||||||
//2: it lacks O(n^2) worst-case overhead.
|
#define NALL_SORT_INSERTION
|
||||||
//(* which is also O(n log n) in the average case.)
|
//#define NALL_SORT_SELECTION
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T>
|
template<typename T, typename Comparator>
|
||||||
void sort(T list[], unsigned length) {
|
void sort(T list[], unsigned size, const Comparator &lessthan) {
|
||||||
if(length <= 1) return; //nothing to sort
|
if(size <= 1) return; //nothing to sort
|
||||||
|
|
||||||
//use insertion sort to quickly sort smaller blocks
|
//use insertion sort to quickly sort smaller blocks
|
||||||
if(length < 64) {
|
if(size < 64) {
|
||||||
for(unsigned i = 0; i < length; i++) {
|
#if defined(NALL_SORT_INSERTION)
|
||||||
|
for(signed i = 1, j; i < size; i++) {
|
||||||
|
T copy = std::move(list[i]);
|
||||||
|
for(j = i - 1; j >= 0; j--) {
|
||||||
|
if(lessthan(list[j], copy)) break;
|
||||||
|
list[j + 1] = std::move(list[j]);
|
||||||
|
}
|
||||||
|
list[j + 1] = std::move(copy);
|
||||||
|
}
|
||||||
|
#elif defined(NALL_SORT_SELECTION)
|
||||||
|
for(unsigned i = 0; i < size; i++) {
|
||||||
unsigned min = i;
|
unsigned min = i;
|
||||||
for(unsigned j = i + 1; j < length; j++) {
|
for(unsigned j = i + 1; j < size; j++) {
|
||||||
if(list[j] < list[min]) min = j;
|
if(lessthan(list[j], list[min])) min = j;
|
||||||
}
|
}
|
||||||
if(min != i) std::swap(list[i], list[min]);
|
if(min != i) std::swap(list[i], list[min]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//split list in half and recursively sort both
|
//split list in half and recursively sort both
|
||||||
unsigned middle = length / 2;
|
unsigned middle = size / 2;
|
||||||
sort(list, middle);
|
sort(list, middle, lessthan);
|
||||||
sort(list + middle, length - middle);
|
sort(list + middle, size - middle, lessthan);
|
||||||
|
|
||||||
//left and right are sorted here; perform merge sort
|
//left and right are sorted here; perform merge sort
|
||||||
T *buffer = new T[length];
|
T *buffer = new T[size];
|
||||||
unsigned offset = 0;
|
unsigned offset = 0, left = 0, right = middle;
|
||||||
unsigned left = 0;
|
while(left < middle && right < size) {
|
||||||
unsigned right = middle;
|
if(lessthan(list[left], list[right])) {
|
||||||
while(left < middle && right < length) {
|
buffer[offset++] = std::move(list[left++]);
|
||||||
if(list[left] < list[right]) {
|
|
||||||
buffer[offset++] = list[left++];
|
|
||||||
} else {
|
} else {
|
||||||
buffer[offset++] = list[right++];
|
buffer[offset++] = std::move(list[right++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(left < middle) buffer[offset++] = list[left++];
|
while(left < middle) buffer[offset++] = std::move(list[left++]);
|
||||||
while(right < length) buffer[offset++] = list[right++];
|
while(right < size) buffer[offset++] = std::move(list[right++]);
|
||||||
|
|
||||||
for(unsigned i = 0; i < length; i++) list[i] = buffer[i];
|
for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]);
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void sort(T list[], unsigned size) {
|
||||||
|
return sort(list, size, [](const T &l, const T &r) { return l < r; });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
#ifndef NALL_STACK_HPP
|
|
||||||
#define NALL_STACK_HPP
|
|
||||||
|
|
||||||
#include <nall/vector.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
template<typename T> struct stack : public linear_vector<T> {
|
|
||||||
void push(const T &value) {
|
|
||||||
linear_vector<T>::append(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
T pull() {
|
|
||||||
if(linear_vector<T>::size() == 0) throw;
|
|
||||||
T value = linear_vector<T>::operator[](linear_vector<T>::size() - 1);
|
|
||||||
linear_vector<T>::remove(linear_vector<T>::size() - 1);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator()() {
|
|
||||||
if(linear_vector<T>::size() == 0) throw;
|
|
||||||
return linear_vector<T>::operator[](linear_vector<T>::size() - 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,20 +0,0 @@
|
|||||||
#ifndef NALL_STATIC_HPP
|
|
||||||
#define NALL_STATIC_HPP
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
template<bool C, typename T, typename F> struct static_if { typedef T type; };
|
|
||||||
template<typename T, typename F> struct static_if<false, T, F> { typedef F type; };
|
|
||||||
template<typename C, typename T, typename F> struct mp_static_if { typedef typename static_if<C::type, T, F>::type type; };
|
|
||||||
|
|
||||||
template<bool A, bool B> struct static_and { enum { value = false }; };
|
|
||||||
template<> struct static_and<true, true> { enum { value = true }; };
|
|
||||||
template<typename A, typename B> struct mp_static_and { enum { value = static_and<A::value, B::value>::value }; };
|
|
||||||
|
|
||||||
template<bool A, bool B> struct static_or { enum { value = false }; };
|
|
||||||
template<> struct static_or<false, true> { enum { value = true }; };
|
|
||||||
template<> struct static_or<true, false> { enum { value = true }; };
|
|
||||||
template<> struct static_or<true, true> { enum { value = true }; };
|
|
||||||
template<typename A, typename B> struct mp_static_or { enum { value = static_or<A::value, B::value>::value }; };
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,8 +1,6 @@
|
|||||||
#ifndef NALL_STDINT_HPP
|
#ifndef NALL_STDINT_HPP
|
||||||
#define NALL_STDINT_HPP
|
#define NALL_STDINT_HPP
|
||||||
|
|
||||||
#include <nall/static.hpp>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
typedef signed char int8_t;
|
typedef signed char int8_t;
|
||||||
typedef signed short int16_t;
|
typedef signed short int16_t;
|
||||||
|
@@ -45,7 +45,6 @@
|
|||||||
#include <nall/string/wildcard.hpp>
|
#include <nall/string/wildcard.hpp>
|
||||||
#include <nall/string/wrapper.hpp>
|
#include <nall/string/wrapper.hpp>
|
||||||
#include <nall/string/xml.hpp>
|
#include <nall/string/xml.hpp>
|
||||||
#include <nall/string/xml-legacy.hpp>
|
|
||||||
#undef NALL_STRING_INTERNAL_HPP
|
#undef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -20,7 +20,7 @@ struct Node {
|
|||||||
cstring value;
|
cstring value;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
linear_vector<Node> children;
|
vector<Node> children;
|
||||||
|
|
||||||
inline bool valid(char p) const { //A-Za-z0-9-.
|
inline bool valid(char p) const { //A-Za-z0-9-.
|
||||||
return p - 'A' < 26u | p - 'a' < 26u | p - '0' < 10u | p - '-' < 2u;
|
return p - 'A' < 26u | p - 'a' < 26u | p - '0' < 10u | p - '-' < 2u;
|
||||||
|
33
bsnes/nall/type_traits.hpp
Executable file
33
bsnes/nall/type_traits.hpp
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef NALL_STATIC_HPP
|
||||||
|
#define NALL_STATIC_HPP
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
template<typename T> class has_default_constructor {
|
||||||
|
template<signed> class receive_size{};
|
||||||
|
template<typename U> static signed sfinae(receive_size<sizeof U()>*);
|
||||||
|
template<typename U> static char sfinae(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum : bool { value = sizeof(sfinae<T>(0)) == sizeof(signed) };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<bool C, typename T = bool> struct enable_if { typedef T type; };
|
||||||
|
template<typename T> struct enable_if<false, T> {};
|
||||||
|
|
||||||
|
template<bool C, typename T, typename F> struct type_if { typedef T type; };
|
||||||
|
template<typename T, typename F> struct type_if<false, T, F> { typedef F type; };
|
||||||
|
|
||||||
|
template<bool A, bool B> struct static_and { enum { value = false }; };
|
||||||
|
template<> struct static_and<true, true> { enum { value = true }; };
|
||||||
|
|
||||||
|
template<bool A, bool B> struct static_or { enum { value = false }; };
|
||||||
|
template<> struct static_or<false, true> { enum { value = true }; };
|
||||||
|
template<> struct static_or<true, false> { enum { value = true }; };
|
||||||
|
template<> struct static_or<true, true> { enum { value = true }; };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -5,10 +5,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<bool C, typename T = bool> struct enable_if { typedef T type; };
|
|
||||||
template<typename T> struct enable_if<false, T> {};
|
|
||||||
template<typename C, typename T = bool> struct mp_enable_if : enable_if<C::value, T> {};
|
|
||||||
|
|
||||||
template<typename T> struct base_from_member {
|
template<typename T> struct base_from_member {
|
||||||
T value;
|
T value;
|
||||||
base_from_member(T value_) : value(value_) {}
|
base_from_member(T value_) : value(value_) {}
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
#ifndef NALL_VARINT_HPP
|
#ifndef NALL_VARINT_HPP
|
||||||
#define NALL_VARINT_HPP
|
#define NALL_VARINT_HPP
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
#include <nall/static.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<unsigned bits> class uint_t {
|
template<unsigned bits> class uint_t {
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
|
#include <nall/sort.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
@@ -70,6 +71,19 @@ namespace nall {
|
|||||||
objectsize = (count + index >= objectsize) ? index : objectsize - count;
|
objectsize = (count + index >= objectsize) ? index : objectsize - count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sort() {
|
||||||
|
nall::sort(pool, objectsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Comparator> void sort(const Comparator &lessthan) {
|
||||||
|
nall::sort(pool, objectsize, lessthan);
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<unsigned> find(const T& data) {
|
||||||
|
for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return { true, n };
|
||||||
|
return { false, 0u };
|
||||||
|
}
|
||||||
|
|
||||||
//access
|
//access
|
||||||
inline T& operator[](unsigned position) {
|
inline T& operator[](unsigned position) {
|
||||||
if(position >= objectsize) throw exception_out_of_bounds();
|
if(position >= objectsize) throw exception_out_of_bounds();
|
||||||
@@ -81,6 +95,12 @@ namespace nall {
|
|||||||
return pool[position];
|
return pool[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline T& operator()(unsigned position) {
|
||||||
|
if(position >= poolsize) reserve(position + 1);
|
||||||
|
while(position >= objectsize) append(T());
|
||||||
|
return pool[position];
|
||||||
|
}
|
||||||
|
|
||||||
inline const T& operator()(unsigned position, const T& data) const {
|
inline const T& operator()(unsigned position, const T& data) const {
|
||||||
if(position >= objectsize) return data;
|
if(position >= objectsize) return data;
|
||||||
return pool[position];
|
return pool[position];
|
||||||
@@ -141,6 +161,8 @@ namespace nall {
|
|||||||
//if objects hold memory address references to themselves (introspection), a
|
//if objects hold memory address references to themselves (introspection), a
|
||||||
//valid copy constructor will be needed to keep pointers valid.
|
//valid copy constructor will be needed to keep pointers valid.
|
||||||
|
|
||||||
|
#define NALL_DEPRECATED
|
||||||
|
#if defined(NALL_DEPRECATED)
|
||||||
template<typename T> struct linear_vector {
|
template<typename T> struct linear_vector {
|
||||||
protected:
|
protected:
|
||||||
T *pool;
|
T *pool;
|
||||||
@@ -412,6 +434,7 @@ namespace nall {
|
|||||||
const iterator begin() const { return iterator(*this, 0); }
|
const iterator begin() const { return iterator(*this, 0); }
|
||||||
const iterator end() const { return iterator(*this, objectsize); }
|
const iterator end() const { return iterator(*this, objectsize); }
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -116,7 +116,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
linear_vector<File> file;
|
vector<File> file;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -90,10 +90,10 @@ Board::Board(XML::Node &board, const uint8_t *data, unsigned size) {
|
|||||||
information.type = board["type"].data;
|
information.type = board["type"].data;
|
||||||
information.battery = board["prg"]["battery"].data == "true";
|
information.battery = board["prg"]["battery"].data == "true";
|
||||||
|
|
||||||
prgrom.size = hex(board["prg"]["rom"].data);
|
prgrom.size = numeral(board["prg"]["rom"].data);
|
||||||
prgram.size = hex(board["prg"]["ram"].data);
|
prgram.size = numeral(board["prg"]["ram"].data);
|
||||||
chrrom.size = hex(board["chr"]["rom"].data);
|
chrrom.size = numeral(board["chr"]["rom"].data);
|
||||||
chrram.size = hex(board["chr"]["ram"].data);
|
chrram.size = numeral(board["chr"]["ram"].data);
|
||||||
|
|
||||||
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
||||||
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
||||||
|
@@ -23,7 +23,7 @@ void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
|
|||||||
//unsigned crc32 = crc32_calculate(data + 16, size - 16);
|
//unsigned crc32 = crc32_calculate(data + 16, size - 16);
|
||||||
//print(hex<8>(crc32), "\n");
|
//print(hex<8>(crc32), "\n");
|
||||||
sha256 = nall::sha256(data + 16, size - 16);
|
sha256 = nall::sha256(data + 16, size - 16);
|
||||||
board = Board::load(markup != "" ? markup : iNES(data, size), data + 16, size - 16);
|
board = Board::load(!markup.empty() ? markup : iNES(data, size), data + 16, size - 16);
|
||||||
}
|
}
|
||||||
if(board == nullptr) return;
|
if(board == nullptr) return;
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ static string iNES(const uint8_t *data, unsigned size) {
|
|||||||
unsigned prgram = 0;
|
unsigned prgram = 0;
|
||||||
unsigned chrram = chrrom == 0 ? 8192 : 0;
|
unsigned chrram = chrrom == 0 ? 8192 : 0;
|
||||||
|
|
||||||
//print("iNES mapper: ", mapper, "\n");
|
print("iNES mapper: ", mapper, "\n");
|
||||||
|
|
||||||
output.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
output.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||||
output.append("<cartridge>\n");
|
output.append("<cartridge>\n");
|
||||||
@@ -151,7 +151,7 @@ static string iNES(const uint8_t *data, unsigned size) {
|
|||||||
"</cartridge>\n"
|
"</cartridge>\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
//print(output, "\n");
|
print(output, "\n");
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@@ -412,7 +412,7 @@ Action::~Action() {
|
|||||||
//Menu
|
//Menu
|
||||||
//====
|
//====
|
||||||
|
|
||||||
void Menu::append(const reference_array<Action&> &list) {
|
void Menu::append(const array<Action&> &list) {
|
||||||
for(auto &action : list) {
|
for(auto &action : list) {
|
||||||
if(state.action.append(action)) {
|
if(state.action.append(action)) {
|
||||||
action.state.menu = this;
|
action.state.menu = this;
|
||||||
@@ -421,7 +421,7 @@ void Menu::append(const reference_array<Action&> &list) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::remove(const reference_array<Action&> &list) {
|
void Menu::remove(const array<Action&> &list) {
|
||||||
for(auto &action : list) {
|
for(auto &action : list) {
|
||||||
if(state.action.remove(action)) {
|
if(state.action.remove(action)) {
|
||||||
action.state.menu = 0;
|
action.state.menu = 0;
|
||||||
@@ -430,6 +430,11 @@ void Menu::remove(const reference_array<Action&> &list) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::setImage(const image &image) {
|
||||||
|
state.image = image;
|
||||||
|
return p.setImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
void Menu::setText(const string &text) {
|
void Menu::setText(const string &text) {
|
||||||
state.text = text;
|
state.text = text;
|
||||||
return p.setText(text);
|
return p.setText(text);
|
||||||
@@ -521,7 +526,7 @@ CheckItem::~CheckItem() {
|
|||||||
//RadioItem
|
//RadioItem
|
||||||
//=========
|
//=========
|
||||||
|
|
||||||
void RadioItem::group(const reference_array<RadioItem&> &list) {
|
void RadioItem::group(const array<RadioItem&> &list) {
|
||||||
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
||||||
if(list.size()) list[0].setChecked();
|
if(list.size()) list[0].setChecked();
|
||||||
}
|
}
|
||||||
@@ -1105,7 +1110,7 @@ ProgressBar::~ProgressBar() {
|
|||||||
//RadioBox
|
//RadioBox
|
||||||
//========
|
//========
|
||||||
|
|
||||||
void RadioBox::group(const reference_array<RadioBox&> &list) {
|
void RadioBox::group(const array<RadioBox&> &list) {
|
||||||
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
for(auto &item : list) item.p.setGroup(item.state.group = list);
|
||||||
if(list.size()) list[0].setChecked();
|
if(list.size()) list[0].setChecked();
|
||||||
}
|
}
|
||||||
|
@@ -231,8 +231,9 @@ struct Menu : private nall::base_from_member<pMenu&>, Action {
|
|||||||
template<typename... Args> void append(Args&... args) { append({ args... }); }
|
template<typename... Args> void append(Args&... args) { append({ args... }); }
|
||||||
template<typename... Args> void remove(Args&... args) { remove({ args... }); }
|
template<typename... Args> void remove(Args&... args) { remove({ args... }); }
|
||||||
|
|
||||||
void append(const nall::reference_array<Action&> &list);
|
void append(const nall::array<Action&> &list);
|
||||||
void remove(const nall::reference_array<Action&> &list);
|
void remove(const nall::array<Action&> &list);
|
||||||
|
void setImage(const nall::image &image);
|
||||||
void setText(const nall::string &text);
|
void setText(const nall::string &text);
|
||||||
|
|
||||||
Menu();
|
Menu();
|
||||||
@@ -277,7 +278,7 @@ struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
|
|||||||
|
|
||||||
struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
|
struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
|
||||||
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
||||||
static void group(const nall::reference_array<RadioItem&> &list);
|
static void group(const nall::array<RadioItem&> &list);
|
||||||
|
|
||||||
nall::function<void ()> onActivate;
|
nall::function<void ()> onActivate;
|
||||||
|
|
||||||
@@ -357,6 +358,11 @@ struct Button : private nall::base_from_member<pButton&>, Widget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
||||||
|
nall::function<void ()> onMouseLeave;
|
||||||
|
nall::function<void (Position)> onMouseMove;
|
||||||
|
nall::function<void (Mouse::Button)> onMousePress;
|
||||||
|
nall::function<void (Mouse::Button)> onMouseRelease;
|
||||||
|
|
||||||
uint32_t* data();
|
uint32_t* data();
|
||||||
bool setImage(const nall::image &image);
|
bool setImage(const nall::image &image);
|
||||||
void setSize(const Size &size);
|
void setSize(const Size &size);
|
||||||
@@ -515,7 +521,7 @@ struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget {
|
|||||||
|
|
||||||
struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
|
struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
|
||||||
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
||||||
static void group(const nall::reference_array<RadioBox&> &list);
|
static void group(const nall::array<RadioBox&> &list);
|
||||||
|
|
||||||
nall::function<void ()> onActivate;
|
nall::function<void ()> onActivate;
|
||||||
|
|
||||||
@@ -577,6 +583,11 @@ struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Viewport : private nall::base_from_member<pViewport&>, Widget {
|
struct Viewport : private nall::base_from_member<pViewport&>, Widget {
|
||||||
|
nall::function<void ()> onMouseLeave;
|
||||||
|
nall::function<void (Position)> onMouseMove;
|
||||||
|
nall::function<void (Mouse::Button)> onMousePress;
|
||||||
|
nall::function<void (Mouse::Button)> onMouseRelease;
|
||||||
|
|
||||||
uintptr_t handle();
|
uintptr_t handle();
|
||||||
|
|
||||||
Viewport();
|
Viewport();
|
||||||
|
@@ -14,8 +14,8 @@ struct Window::State {
|
|||||||
bool fullScreen;
|
bool fullScreen;
|
||||||
Geometry geometry;
|
Geometry geometry;
|
||||||
bool ignore;
|
bool ignore;
|
||||||
reference_array<Layout&> layout;
|
array<Layout&> layout;
|
||||||
reference_array<Menu&> menu;
|
array<Menu&> menu;
|
||||||
string menuFont;
|
string menuFont;
|
||||||
bool menuVisible;
|
bool menuVisible;
|
||||||
bool resizable;
|
bool resizable;
|
||||||
@@ -24,7 +24,7 @@ struct Window::State {
|
|||||||
bool statusVisible;
|
bool statusVisible;
|
||||||
string title;
|
string title;
|
||||||
bool visible;
|
bool visible;
|
||||||
reference_array<Widget&> widget;
|
array<Widget&> widget;
|
||||||
string widgetFont;
|
string widgetFont;
|
||||||
|
|
||||||
State() {
|
State() {
|
||||||
@@ -55,8 +55,12 @@ struct Action::State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Menu::State {
|
struct Menu::State {
|
||||||
reference_array<Action&> action;
|
array<Action&> action;
|
||||||
|
nall::image image;
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
|
State() : image(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0) {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Item::State {
|
struct Item::State {
|
||||||
@@ -78,7 +82,7 @@ struct CheckItem::State {
|
|||||||
|
|
||||||
struct RadioItem::State {
|
struct RadioItem::State {
|
||||||
bool checked;
|
bool checked;
|
||||||
reference_array<RadioItem&> group;
|
array<RadioItem&> group;
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
State() {
|
State() {
|
||||||
@@ -229,7 +233,7 @@ struct ProgressBar::State {
|
|||||||
|
|
||||||
struct RadioBox::State {
|
struct RadioBox::State {
|
||||||
bool checked;
|
bool checked;
|
||||||
reference_array<RadioBox&> group;
|
array<RadioBox&> group;
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
State() {
|
State() {
|
||||||
|
@@ -13,13 +13,18 @@ void pMenu::remove(Action &action) {
|
|||||||
action.state.window = 0;
|
action.state.window = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pMenu::setImage(const image &image) {
|
||||||
|
GtkImage *gtkImage = CreateImage(image, /* menuIcon = */ true);
|
||||||
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
||||||
|
}
|
||||||
|
|
||||||
void pMenu::setText(const string &text) {
|
void pMenu::setText(const string &text) {
|
||||||
gtk_menu_item_set_label(GTK_MENU_ITEM(widget), text);
|
gtk_menu_item_set_label(GTK_MENU_ITEM(widget), text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenu::constructor() {
|
void pMenu::constructor() {
|
||||||
gtkMenu = gtk_menu_new();
|
gtkMenu = gtk_menu_new();
|
||||||
widget = gtk_menu_item_new_with_label(menu.state.text);
|
widget = gtk_image_menu_item_new_with_label(menu.state.text);
|
||||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), gtkMenu);
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), gtkMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ void pRadioItem::setChecked() {
|
|||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setGroup(const reference_array<RadioItem&> &group) {
|
void pRadioItem::setGroup(const array<RadioItem&> &group) {
|
||||||
for(unsigned n = 0; n < group.size(); n++) {
|
for(unsigned n = 0; n < group.size(); n++) {
|
||||||
if(n == 0) continue;
|
if(n == 0) continue;
|
||||||
GSList *currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(group[0].p.widget));
|
GSList *currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(group[0].p.widget));
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
|
|
||||||
|
|
||||||
void pKeyboard::initialize() {
|
void pKeyboard::initialize() {
|
||||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||||
keymap.append(scancode, XKeysymToKeycode(pOS::display, keysym));
|
settings->keymap.insert(scancode, XKeysymToKeycode(pOS::display, keysym));
|
||||||
};
|
};
|
||||||
|
|
||||||
append(Keyboard::Scancode::Escape, XK_Escape);
|
append(Keyboard::Scancode::Escape, XK_Escape);
|
||||||
@@ -123,18 +121,18 @@ void pKeyboard::initialize() {
|
|||||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||||
char state[256];
|
char state[256];
|
||||||
XQueryKeymap(pOS::display, state);
|
XQueryKeymap(pOS::display, state);
|
||||||
unsigned id = keymap.lhs[scancode];
|
unsigned id = settings->keymap.lhs[scancode];
|
||||||
return state[id >> 3] & (1 << (id & 7));
|
return state[id >> 3] & (1 << (id & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
array<bool> pKeyboard::state() {
|
array<bool> pKeyboard::state() {
|
||||||
array<bool> output;
|
array<bool> output;
|
||||||
output.reserve((unsigned)Keyboard::Scancode::Limit);
|
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||||
for(auto &n : output) n = false;
|
for(auto &n : output) n = false;
|
||||||
|
|
||||||
char state[256];
|
char state[256];
|
||||||
XQueryKeymap(pOS::display, state);
|
XQueryKeymap(pOS::display, state);
|
||||||
for(auto &n : keymap.rhs) {
|
for(auto &n : settings->keymap.rhs) {
|
||||||
if(state[n.name >> 3] & (1 << (n.name & 7))) {
|
if(state[n.name >> 3] & (1 << (n.name & 7))) {
|
||||||
output[(unsigned)n.data] = true;
|
output[(unsigned)n.data] = true;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "utility.cpp"
|
#include "utility.cpp"
|
||||||
|
#include "settings.cpp"
|
||||||
|
|
||||||
#include "desktop.cpp"
|
#include "desktop.cpp"
|
||||||
#include "keyboard.cpp"
|
#include "keyboard.cpp"
|
||||||
@@ -7,7 +8,6 @@
|
|||||||
#include "dialog-window.cpp"
|
#include "dialog-window.cpp"
|
||||||
#include "message-window.cpp"
|
#include "message-window.cpp"
|
||||||
|
|
||||||
#include "settings.cpp"
|
|
||||||
#include "font.cpp"
|
#include "font.cpp"
|
||||||
#include "timer.cpp"
|
#include "timer.cpp"
|
||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
struct Settings : public configuration {
|
struct Settings : public configuration {
|
||||||
|
bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
||||||
|
|
||||||
unsigned frameGeometryX;
|
unsigned frameGeometryX;
|
||||||
unsigned frameGeometryY;
|
unsigned frameGeometryY;
|
||||||
unsigned frameGeometryWidth;
|
unsigned frameGeometryWidth;
|
||||||
@@ -32,8 +34,6 @@ struct pDesktop {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pKeyboard {
|
struct pKeyboard {
|
||||||
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
|
||||||
|
|
||||||
static bool pressed(Keyboard::Scancode scancode);
|
static bool pressed(Keyboard::Scancode scancode);
|
||||||
static array<bool> state();
|
static array<bool> state();
|
||||||
|
|
||||||
@@ -150,6 +150,7 @@ struct pMenu : public pAction {
|
|||||||
|
|
||||||
void append(Action &action);
|
void append(Action &action);
|
||||||
void remove(Action &action);
|
void remove(Action &action);
|
||||||
|
void setImage(const image &image);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
||||||
@@ -198,7 +199,7 @@ struct pRadioItem : public pAction {
|
|||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioItem&> &group);
|
void setGroup(const array<RadioItem&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||||
@@ -424,7 +425,7 @@ struct pRadioBox : public pWidget {
|
|||||||
bool checked();
|
bool checked();
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioBox&> &group);
|
void setGroup(const array<RadioBox&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
||||||
|
@@ -6,6 +6,34 @@ static gboolean Canvas_expose(GtkWidget *widget, GdkEvent *event, pCanvas *self)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean Canvas_mouseLeave(GtkWidget *widget, GdkEventButton *event, pCanvas *self) {
|
||||||
|
if(self->canvas.onMouseLeave) self->canvas.onMouseLeave();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean Canvas_mouseMove(GtkWidget *widget, GdkEventButton *event, pCanvas *self) {
|
||||||
|
if(self->canvas.onMouseMove) self->canvas.onMouseMove({ (signed)event->x, (signed)event->y });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean Canvas_mousePress(GtkWidget *widget, GdkEventButton *event, pCanvas *self) {
|
||||||
|
if(self->canvas.onMousePress) switch(event->button) {
|
||||||
|
case 1: self->canvas.onMousePress(Mouse::Button::Left); break;
|
||||||
|
case 2: self->canvas.onMousePress(Mouse::Button::Middle); break;
|
||||||
|
case 3: self->canvas.onMousePress(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean Canvas_mouseRelease(GtkWidget *widget, GdkEventButton *event, pCanvas *self) {
|
||||||
|
if(self->canvas.onMouseRelease) switch(event->button) {
|
||||||
|
case 1: self->canvas.onMouseRelease(Mouse::Button::Left); break;
|
||||||
|
case 2: self->canvas.onMouseRelease(Mouse::Button::Middle); break;
|
||||||
|
case 3: self->canvas.onMouseRelease(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void pCanvas::setSize(const Size &size) {
|
void pCanvas::setSize(const Size &size) {
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
|
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
|
||||||
@@ -22,8 +50,13 @@ void pCanvas::constructor() {
|
|||||||
memcpy(cairo_image_surface_get_data(surface), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
|
memcpy(cairo_image_surface_get_data(surface), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
|
||||||
gtkWidget = gtk_drawing_area_new();
|
gtkWidget = gtk_drawing_area_new();
|
||||||
gtk_widget_set_double_buffered(gtkWidget, false);
|
gtk_widget_set_double_buffered(gtkWidget, false);
|
||||||
gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK);
|
gtk_widget_add_events(gtkWidget,
|
||||||
|
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Canvas_mousePress), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Canvas_mouseRelease), (gpointer)this);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "leave_notify_event", G_CALLBACK(Canvas_mouseLeave), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "motion_notify_event", G_CALLBACK(Canvas_mouseMove), (gpointer)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::destructor() {
|
void pCanvas::destructor() {
|
||||||
|
@@ -19,7 +19,7 @@ void pRadioBox::setChecked() {
|
|||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setGroup(const reference_array<RadioBox&> &group) {
|
void pRadioBox::setGroup(const array<RadioBox&> &group) {
|
||||||
for(unsigned n = 0; n < group.size(); n++) {
|
for(unsigned n = 0; n < group.size(); n++) {
|
||||||
if(n == 0) continue;
|
if(n == 0) continue;
|
||||||
GSList *currentGroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(group[0].p.gtkWidget));
|
GSList *currentGroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(group[0].p.gtkWidget));
|
||||||
|
@@ -1,3 +1,31 @@
|
|||||||
|
static gboolean Viewport_mouseLeave(GtkWidget *widget, GdkEventButton *event, pViewport *self) {
|
||||||
|
if(self->viewport.onMouseLeave) self->viewport.onMouseLeave();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean Viewport_mouseMove(GtkWidget *widget, GdkEventButton *event, pViewport *self) {
|
||||||
|
if(self->viewport.onMouseMove) self->viewport.onMouseMove({ (signed)event->x, (signed)event->y });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean Viewport_mousePress(GtkWidget *widget, GdkEventButton *event, pViewport *self) {
|
||||||
|
if(self->viewport.onMousePress) switch(event->button) {
|
||||||
|
case 1: self->viewport.onMousePress(Mouse::Button::Left); break;
|
||||||
|
case 2: self->viewport.onMousePress(Mouse::Button::Middle); break;
|
||||||
|
case 3: self->viewport.onMousePress(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean Viewport_mouseRelease(GtkWidget *widget, GdkEventButton *event, pViewport *self) {
|
||||||
|
if(self->viewport.onMouseRelease) switch(event->button) {
|
||||||
|
case 1: self->viewport.onMouseRelease(Mouse::Button::Left); break;
|
||||||
|
case 2: self->viewport.onMouseRelease(Mouse::Button::Middle); break;
|
||||||
|
case 3: self->viewport.onMouseRelease(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t pViewport::handle() {
|
uintptr_t pViewport::handle() {
|
||||||
return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget));
|
return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget));
|
||||||
}
|
}
|
||||||
@@ -5,6 +33,12 @@ uintptr_t pViewport::handle() {
|
|||||||
void pViewport::constructor() {
|
void pViewport::constructor() {
|
||||||
gtkWidget = gtk_drawing_area_new();
|
gtkWidget = gtk_drawing_area_new();
|
||||||
//gtk_widget_set_double_buffered(gtkWidget, false);
|
//gtk_widget_set_double_buffered(gtkWidget, false);
|
||||||
|
gtk_widget_add_events(gtkWidget,
|
||||||
|
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Viewport_mousePress), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "leave_notify_event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "motion_notify_event", G_CALLBACK(Viewport_mouseMove), (gpointer)this);
|
||||||
|
|
||||||
GdkColor color;
|
GdkColor color;
|
||||||
color.pixel = 0;
|
color.pixel = 0;
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/image.hpp>
|
#include <nall/image.hpp>
|
||||||
#include <nall/map.hpp>
|
#include <nall/map.hpp>
|
||||||
#include <nall/reference_array.hpp>
|
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
@@ -33,6 +33,15 @@ void pMenu::setFont(const string &font) {
|
|||||||
for(auto &item : menu.state.action) item.p.setFont(font);
|
for(auto &item : menu.state.action) item.p.setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pMenu::setImage(const image &image) {
|
||||||
|
nall::image qtBuffer = image;
|
||||||
|
qtBuffer.transform(0, 32u, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||||
|
|
||||||
|
QImage qtImage(qtBuffer.data, qtBuffer.width, qtBuffer.height, QImage::Format_ARGB32);
|
||||||
|
QIcon qtIcon(QPixmap::fromImage(qtImage));
|
||||||
|
qtMenu->setIcon(qtIcon);
|
||||||
|
}
|
||||||
|
|
||||||
void pMenu::setText(const string &text) {
|
void pMenu::setText(const string &text) {
|
||||||
qtMenu->setTitle(QString::fromUtf8(text));
|
qtMenu->setTitle(QString::fromUtf8(text));
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ void pRadioItem::setChecked() {
|
|||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setGroup(const reference_array<RadioItem&> &group) {
|
void pRadioItem::setGroup(const array<RadioItem&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setText(const string &text) {
|
void pRadioItem::setText(const string &text) {
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
|
|
||||||
|
|
||||||
void pKeyboard::initialize() {
|
void pKeyboard::initialize() {
|
||||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||||
keymap.append(scancode, XKeysymToKeycode(pOS::display, keysym));
|
settings->keymap.insert(scancode, XKeysymToKeycode(pOS::display, keysym));
|
||||||
};
|
};
|
||||||
|
|
||||||
append(Keyboard::Scancode::Escape, XK_Escape);
|
append(Keyboard::Scancode::Escape, XK_Escape);
|
||||||
@@ -123,7 +121,7 @@ void pKeyboard::initialize() {
|
|||||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||||
char state[256];
|
char state[256];
|
||||||
XQueryKeymap(pOS::display, state);
|
XQueryKeymap(pOS::display, state);
|
||||||
unsigned id = keymap.lhs[scancode];
|
unsigned id = settings->keymap.lhs[scancode];
|
||||||
return state[id >> 3] & (1 << (id & 7));
|
return state[id >> 3] & (1 << (id & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +132,7 @@ array<bool> pKeyboard::state() {
|
|||||||
|
|
||||||
char state[256];
|
char state[256];
|
||||||
XQueryKeymap(pOS::display, state);
|
XQueryKeymap(pOS::display, state);
|
||||||
for(auto &n : keymap.rhs) {
|
for(auto &n : settings->keymap.rhs) {
|
||||||
if(state[n.name >> 3] & (1 << (n.name & 7))) {
|
if(state[n.name >> 3] & (1 << (n.name & 7))) {
|
||||||
output[(unsigned)n.data] = true;
|
output[(unsigned)n.data] = true;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "platform.moc.hpp"
|
#include "platform.moc.hpp"
|
||||||
#include "platform.moc"
|
#include "platform.moc"
|
||||||
#include "utility.cpp"
|
#include "utility.cpp"
|
||||||
|
#include "settings.cpp"
|
||||||
|
|
||||||
#include "desktop.cpp"
|
#include "desktop.cpp"
|
||||||
#include "keyboard.cpp"
|
#include "keyboard.cpp"
|
||||||
@@ -8,7 +9,6 @@
|
|||||||
#include "dialog-window.cpp"
|
#include "dialog-window.cpp"
|
||||||
#include "message-window.cpp"
|
#include "message-window.cpp"
|
||||||
|
|
||||||
#include "settings.cpp"
|
|
||||||
#include "font.cpp"
|
#include "font.cpp"
|
||||||
#include "timer.cpp"
|
#include "timer.cpp"
|
||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||||
**
|
**
|
||||||
** Created: Sat Jan 14 09:18:07 2012
|
** Created: Mon Jan 23 13:07:40 2012
|
||||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
static QApplication *qtApplication = 0;
|
static QApplication *qtApplication = 0;
|
||||||
|
|
||||||
struct Settings : public configuration {
|
struct Settings : public configuration {
|
||||||
|
bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
||||||
|
|
||||||
unsigned frameGeometryX;
|
unsigned frameGeometryX;
|
||||||
unsigned frameGeometryY;
|
unsigned frameGeometryY;
|
||||||
unsigned frameGeometryWidth;
|
unsigned frameGeometryWidth;
|
||||||
@@ -31,8 +33,6 @@ struct pDesktop {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pKeyboard {
|
struct pKeyboard {
|
||||||
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
|
||||||
|
|
||||||
static bool pressed(Keyboard::Scancode scancode);
|
static bool pressed(Keyboard::Scancode scancode);
|
||||||
static array<bool> state();
|
static array<bool> state();
|
||||||
|
|
||||||
@@ -166,6 +166,7 @@ struct pMenu : public pAction {
|
|||||||
void append(Action &action);
|
void append(Action &action);
|
||||||
void remove(Action &action);
|
void remove(Action &action);
|
||||||
void setFont(const string &font);
|
void setFont(const string &font);
|
||||||
|
void setImage(const image &image);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
||||||
@@ -229,7 +230,7 @@ public:
|
|||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioItem&> &group);
|
void setGroup(const array<RadioItem&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||||
@@ -304,6 +305,10 @@ public:
|
|||||||
QImage *qtImage;
|
QImage *qtImage;
|
||||||
struct QtCanvas : public QWidget {
|
struct QtCanvas : public QWidget {
|
||||||
pCanvas &self;
|
pCanvas &self;
|
||||||
|
void leaveEvent(QEvent*);
|
||||||
|
void mouseMoveEvent(QMouseEvent*);
|
||||||
|
void mousePressEvent(QMouseEvent*);
|
||||||
|
void mouseReleaseEvent(QMouseEvent*);
|
||||||
void paintEvent(QPaintEvent*);
|
void paintEvent(QPaintEvent*);
|
||||||
QtCanvas(pCanvas &self);
|
QtCanvas(pCanvas &self);
|
||||||
} *qtCanvas;
|
} *qtCanvas;
|
||||||
@@ -525,7 +530,7 @@ public:
|
|||||||
bool checked();
|
bool checked();
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioBox&> &group);
|
void setGroup(const array<RadioBox&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
||||||
@@ -603,6 +608,14 @@ public slots:
|
|||||||
|
|
||||||
struct pViewport : public pWidget {
|
struct pViewport : public pWidget {
|
||||||
Viewport &viewport;
|
Viewport &viewport;
|
||||||
|
struct QtViewport : public QWidget {
|
||||||
|
pViewport &self;
|
||||||
|
void leaveEvent(QEvent*);
|
||||||
|
void mouseMoveEvent(QMouseEvent*);
|
||||||
|
void mousePressEvent(QMouseEvent*);
|
||||||
|
void mouseReleaseEvent(QMouseEvent*);
|
||||||
|
QtViewport(pViewport &self);
|
||||||
|
} *qtViewport;
|
||||||
|
|
||||||
uintptr_t handle();
|
uintptr_t handle();
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@ void pButton::setImage(const image &image, Orientation orientation) {
|
|||||||
QIcon qtIcon(QPixmap::fromImage(qtImage));
|
QIcon qtIcon(QPixmap::fromImage(qtImage));
|
||||||
qtButton->setIconSize(QSize(qtBuffer.width, qtBuffer.height));
|
qtButton->setIconSize(QSize(qtBuffer.width, qtBuffer.height));
|
||||||
qtButton->setIcon(qtIcon);
|
qtButton->setIcon(qtIcon);
|
||||||
|
qtButton->setStyleSheet("text-align: top;");
|
||||||
switch(orientation) {
|
switch(orientation) {
|
||||||
case Orientation::Horizontal: qtButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
|
case Orientation::Horizontal: qtButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
|
||||||
case Orientation::Vertical: qtButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
|
case Orientation::Vertical: qtButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
|
||||||
|
@@ -11,6 +11,7 @@ void pCanvas::update() {
|
|||||||
|
|
||||||
void pCanvas::constructor() {
|
void pCanvas::constructor() {
|
||||||
qtWidget = qtCanvas = new QtCanvas(*this);
|
qtWidget = qtCanvas = new QtCanvas(*this);
|
||||||
|
qtCanvas->setMouseTracking(true);
|
||||||
qtImage = new QImage(canvas.state.width, canvas.state.height, QImage::Format_ARGB32);
|
qtImage = new QImage(canvas.state.width, canvas.state.height, QImage::Format_ARGB32);
|
||||||
memcpy(qtImage->bits(), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
|
memcpy(qtImage->bits(), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
|
||||||
|
|
||||||
@@ -30,6 +31,32 @@ void pCanvas::orphan() {
|
|||||||
constructor();
|
constructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pCanvas::QtCanvas::leaveEvent(QEvent *event) {
|
||||||
|
if(self.canvas.onMouseLeave) self.canvas.onMouseLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pCanvas::QtCanvas::mouseMoveEvent(QMouseEvent *event) {
|
||||||
|
if(self.canvas.onMouseMove) self.canvas.onMouseMove({ event->pos().x(), event->pos().y() });
|
||||||
|
}
|
||||||
|
|
||||||
|
void pCanvas::QtCanvas::mousePressEvent(QMouseEvent *event) {
|
||||||
|
if(self.canvas.onMousePress == false) return;
|
||||||
|
switch(event->button()) {
|
||||||
|
case Qt::LeftButton: self.canvas.onMousePress(Mouse::Button::Left); break;
|
||||||
|
case Qt::MidButton: self.canvas.onMousePress(Mouse::Button::Middle); break;
|
||||||
|
case Qt::RightButton: self.canvas.onMousePress(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pCanvas::QtCanvas::mouseReleaseEvent(QMouseEvent *event) {
|
||||||
|
if(self.canvas.onMouseRelease == false) return;
|
||||||
|
switch(event->button()) {
|
||||||
|
case Qt::LeftButton: self.canvas.onMouseRelease(Mouse::Button::Left); break;
|
||||||
|
case Qt::MidButton: self.canvas.onMouseRelease(Mouse::Button::Middle); break;
|
||||||
|
case Qt::RightButton: self.canvas.onMouseRelease(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) {
|
void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) {
|
||||||
QPainter painter(self.qtCanvas);
|
QPainter painter(self.qtCanvas);
|
||||||
painter.drawImage(0, 0, *self.qtImage);
|
painter.drawImage(0, 0, *self.qtImage);
|
||||||
|
@@ -17,7 +17,7 @@ void pRadioBox::setChecked() {
|
|||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setGroup(const reference_array<RadioBox&> &group) {
|
void pRadioBox::setGroup(const array<RadioBox&> &group) {
|
||||||
locked = true;
|
locked = true;
|
||||||
if(qtGroup) {
|
if(qtGroup) {
|
||||||
delete qtGroup;
|
delete qtGroup;
|
||||||
|
@@ -1,21 +1,51 @@
|
|||||||
uintptr_t pViewport::handle() {
|
uintptr_t pViewport::handle() {
|
||||||
return (uintptr_t)qtWidget->winId();
|
return (uintptr_t)qtViewport->winId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pViewport::constructor() {
|
void pViewport::constructor() {
|
||||||
qtWidget = new QWidget;
|
qtWidget = qtViewport = new QtViewport(*this);
|
||||||
qtWidget->setAttribute(Qt::WA_PaintOnScreen, true);
|
qtViewport->setMouseTracking(true);
|
||||||
qtWidget->setStyleSheet("background: #000000");
|
qtViewport->setAttribute(Qt::WA_PaintOnScreen, true);
|
||||||
|
qtViewport->setStyleSheet("background: #000000");
|
||||||
|
|
||||||
pWidget::synchronizeState();
|
pWidget::synchronizeState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pViewport::destructor() {
|
void pViewport::destructor() {
|
||||||
delete qtWidget;
|
delete qtViewport;
|
||||||
qtWidget = 0;
|
qtWidget = qtViewport = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pViewport::orphan() {
|
void pViewport::orphan() {
|
||||||
destructor();
|
destructor();
|
||||||
constructor();
|
constructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pViewport::QtViewport::leaveEvent(QEvent *event) {
|
||||||
|
if(self.viewport.onMouseLeave) self.viewport.onMouseLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pViewport::QtViewport::mouseMoveEvent(QMouseEvent *event) {
|
||||||
|
if(self.viewport.onMouseMove) self.viewport.onMouseMove({ event->pos().x(), event->pos().y() });
|
||||||
|
}
|
||||||
|
|
||||||
|
void pViewport::QtViewport::mousePressEvent(QMouseEvent *event) {
|
||||||
|
if(self.viewport.onMousePress == false) return;
|
||||||
|
switch(event->button()) {
|
||||||
|
case Qt::LeftButton: self.viewport.onMousePress(Mouse::Button::Left); break;
|
||||||
|
case Qt::MidButton: self.viewport.onMousePress(Mouse::Button::Middle); break;
|
||||||
|
case Qt::RightButton: self.viewport.onMousePress(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pViewport::QtViewport::mouseReleaseEvent(QMouseEvent *event) {
|
||||||
|
if(self.viewport.onMouseRelease == false) return;
|
||||||
|
switch(event->button()) {
|
||||||
|
case Qt::LeftButton: self.viewport.onMouseRelease(Mouse::Button::Left); break;
|
||||||
|
case Qt::MidButton: self.viewport.onMouseRelease(Mouse::Button::Middle); break;
|
||||||
|
case Qt::RightButton: self.viewport.onMouseRelease(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pViewport::QtViewport::QtViewport(pViewport &self) : self(self) {
|
||||||
|
}
|
||||||
|
@@ -4,6 +4,9 @@ void pMenu::append(Action &action) {
|
|||||||
void pMenu::remove(Action &action) {
|
void pMenu::remove(Action &action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pMenu::setImage(const image &image) {
|
||||||
|
}
|
||||||
|
|
||||||
void pMenu::setText(const string &text) {
|
void pMenu::setText(const string &text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ bool pRadioItem::checked() {
|
|||||||
void pRadioItem::setChecked() {
|
void pRadioItem::setChecked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setGroup(const reference_array<RadioItem&> &group) {
|
void pRadioItem::setGroup(const array<RadioItem&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setText(const string &text) {
|
void pRadioItem::setText(const string &text) {
|
||||||
|
@@ -112,6 +112,7 @@ struct pMenu : public pAction {
|
|||||||
|
|
||||||
void append(Action &action);
|
void append(Action &action);
|
||||||
void remove(Action &action);
|
void remove(Action &action);
|
||||||
|
void setImage(const image &image);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
||||||
@@ -155,7 +156,7 @@ struct pRadioItem : public pAction {
|
|||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioItem&> &group);
|
void setGroup(const array<RadioItem&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||||
@@ -323,7 +324,7 @@ struct pRadioBox : public pWidget {
|
|||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioBox&> &group);
|
void setGroup(const array<RadioBox&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
||||||
|
@@ -5,7 +5,7 @@ bool pRadioBox::checked() {
|
|||||||
void pRadioBox::setChecked() {
|
void pRadioBox::setChecked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setGroup(const reference_array<RadioBox&> &group) {
|
void pRadioBox::setGroup(const array<RadioBox&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setText(const string &text) {
|
void pRadioBox::setText(const string &text) {
|
||||||
|
@@ -26,4 +26,4 @@ void pItem::createBitmap() {
|
|||||||
nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
|
nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
|
||||||
hbitmap = CreateBitmap(nallImage);
|
hbitmap = CreateBitmap(nallImage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,12 +8,40 @@ void pMenu::remove(Action &action) {
|
|||||||
action.p.parentMenu = 0;
|
action.p.parentMenu = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pMenu::setImage(const image &image) {
|
||||||
|
createBitmap();
|
||||||
|
if(parentWindow) parentWindow->p.updateMenu();
|
||||||
|
}
|
||||||
|
|
||||||
void pMenu::setText(const string &text) {
|
void pMenu::setText(const string &text) {
|
||||||
if(parentWindow) parentWindow->p.updateMenu();
|
if(parentWindow) parentWindow->p.updateMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenu::constructor() {
|
void pMenu::constructor() {
|
||||||
hmenu = 0;
|
hmenu = 0;
|
||||||
|
createBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void pMenu::destructor() {
|
||||||
|
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
||||||
|
if(parentMenu) {
|
||||||
|
parentMenu->remove(menu);
|
||||||
|
} else if(parentWindow) {
|
||||||
|
//belongs to window's main menubar
|
||||||
|
parentWindow->remove(menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pMenu::createBitmap() {
|
||||||
|
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
|
||||||
|
|
||||||
|
if(menu.state.image.width && menu.state.image.height) {
|
||||||
|
nall::image nallImage = menu.state.image;
|
||||||
|
nallImage.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||||
|
nallImage.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline)
|
||||||
|
nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
|
||||||
|
hbitmap = CreateBitmap(nallImage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Windows actions lack the ability to toggle visibility.
|
//Windows actions lack the ability to toggle visibility.
|
||||||
@@ -32,11 +60,24 @@ void pMenu::update(Window &parentWindow, Menu *parentMenu) {
|
|||||||
unsigned enabled = action.state.enabled ? 0 : MF_GRAYED;
|
unsigned enabled = action.state.enabled ? 0 : MF_GRAYED;
|
||||||
if(dynamic_cast<Menu*>(&action)) {
|
if(dynamic_cast<Menu*>(&action)) {
|
||||||
Menu &item = (Menu&)action;
|
Menu &item = (Menu&)action;
|
||||||
item.p.update(parentWindow, &menu);
|
if(action.state.visible) {
|
||||||
AppendMenu(hmenu, MF_STRING | MF_POPUP | enabled, (UINT_PTR)item.p.hmenu, utf16_t(item.state.text));
|
item.p.update(parentWindow, &menu);
|
||||||
|
AppendMenu(hmenu, MF_STRING | MF_POPUP | enabled, (UINT_PTR)item.p.hmenu, utf16_t(item.state.text));
|
||||||
|
|
||||||
|
if(item.state.image.width && item.state.image.height) {
|
||||||
|
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
|
||||||
|
//Windows XP and below displays MIIM_BITMAP + hbmpItem in its own column (separate from check/radio marks)
|
||||||
|
//this causes too much spacing, so use a custom checkmark image instead
|
||||||
|
mii.fMask = MIIM_CHECKMARKS;
|
||||||
|
mii.hbmpUnchecked = item.p.hbitmap;
|
||||||
|
SetMenuItemInfo(hmenu, (UINT_PTR)item.p.hmenu, FALSE, &mii);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if(dynamic_cast<Separator*>(&action)) {
|
} else if(dynamic_cast<Separator*>(&action)) {
|
||||||
Separator &item = (Separator&)action;
|
Separator &item = (Separator&)action;
|
||||||
if(action.state.visible) AppendMenu(hmenu, MF_SEPARATOR | enabled, item.p.id, L"");
|
if(action.state.visible) {
|
||||||
|
AppendMenu(hmenu, MF_SEPARATOR | enabled, item.p.id, L"");
|
||||||
|
}
|
||||||
} else if(dynamic_cast<Item*>(&action)) {
|
} else if(dynamic_cast<Item*>(&action)) {
|
||||||
Item &item = (Item&)action;
|
Item &item = (Item&)action;
|
||||||
if(action.state.visible) {
|
if(action.state.visible) {
|
||||||
@@ -53,21 +94,16 @@ void pMenu::update(Window &parentWindow, Menu *parentMenu) {
|
|||||||
}
|
}
|
||||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||||
CheckItem &item = (CheckItem&)action;
|
CheckItem &item = (CheckItem&)action;
|
||||||
if(action.state.visible) AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
if(action.state.visible) {
|
||||||
|
AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
||||||
|
}
|
||||||
if(item.state.checked) item.setChecked();
|
if(item.state.checked) item.setChecked();
|
||||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||||
RadioItem &item = (RadioItem&)action;
|
RadioItem &item = (RadioItem&)action;
|
||||||
if(action.state.visible) AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
if(action.state.visible) {
|
||||||
|
AppendMenu(hmenu, MF_STRING | enabled, item.p.id, utf16_t(item.state.text));
|
||||||
|
}
|
||||||
if(item.state.checked) item.setChecked();
|
if(item.state.checked) item.setChecked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenu::destructor() {
|
|
||||||
if(parentMenu) {
|
|
||||||
parentMenu->remove(menu);
|
|
||||||
} else if(parentWindow) {
|
|
||||||
//belongs to window's main menubar
|
|
||||||
parentWindow->remove(menu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -11,7 +11,7 @@ void pRadioItem::setChecked() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setGroup(const reference_array<RadioItem&> &group) {
|
void pRadioItem::setGroup(const array<RadioItem&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setText(const string &text) {
|
void pRadioItem::setText(const string &text) {
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
|
|
||||||
|
|
||||||
void pKeyboard::initialize() {
|
void pKeyboard::initialize() {
|
||||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||||
keymap.append(scancode, keysym);
|
settings->keymap.insert(scancode, keysym);
|
||||||
};
|
};
|
||||||
|
|
||||||
append(Keyboard::Scancode::Escape, VK_ESCAPE);
|
append(Keyboard::Scancode::Escape, VK_ESCAPE);
|
||||||
@@ -121,7 +119,7 @@ void pKeyboard::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||||
return GetAsyncKeyState(keymap.lhs[scancode]) & 0x8000;
|
return GetAsyncKeyState(settings->keymap.lhs[scancode]) & 0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
array<bool> pKeyboard::state() {
|
array<bool> pKeyboard::state() {
|
||||||
@@ -129,7 +127,7 @@ array<bool> pKeyboard::state() {
|
|||||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||||
for(auto &n : output) n = false;
|
for(auto &n : output) n = false;
|
||||||
|
|
||||||
for(auto &n : keymap.rhs) {
|
for(auto &n : settings->keymap.rhs) {
|
||||||
if(GetAsyncKeyState(n.name) & 0x8000) {
|
if(GetAsyncKeyState(n.name) & 0x8000) {
|
||||||
output[(unsigned)n.data] = true;
|
output[(unsigned)n.data] = true;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "utility.cpp"
|
#include "utility.cpp"
|
||||||
|
#include "settings.cpp"
|
||||||
|
|
||||||
#include "desktop.cpp"
|
#include "desktop.cpp"
|
||||||
#include "keyboard.cpp"
|
#include "keyboard.cpp"
|
||||||
@@ -135,6 +136,7 @@ void pOS::initialize() {
|
|||||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
RegisterClass(&wc);
|
RegisterClass(&wc);
|
||||||
|
|
||||||
|
settings = new Settings;
|
||||||
pKeyboard::initialize();
|
pKeyboard::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
|
struct Settings {
|
||||||
|
bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
||||||
|
};
|
||||||
|
|
||||||
struct pFont;
|
struct pFont;
|
||||||
struct pWindow;
|
struct pWindow;
|
||||||
struct pMenu;
|
struct pMenu;
|
||||||
@@ -20,8 +24,6 @@ struct pDesktop {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pKeyboard {
|
struct pKeyboard {
|
||||||
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
|
|
||||||
|
|
||||||
static bool pressed(Keyboard::Scancode scancode);
|
static bool pressed(Keyboard::Scancode scancode);
|
||||||
static array<bool> state();
|
static array<bool> state();
|
||||||
|
|
||||||
@@ -134,14 +136,17 @@ struct pAction : public pObject {
|
|||||||
struct pMenu : public pAction {
|
struct pMenu : public pAction {
|
||||||
Menu &menu;
|
Menu &menu;
|
||||||
HMENU hmenu;
|
HMENU hmenu;
|
||||||
|
HBITMAP hbitmap;
|
||||||
|
|
||||||
void append(Action &action);
|
void append(Action &action);
|
||||||
void remove(Action &action);
|
void remove(Action &action);
|
||||||
|
void setImage(const image &image);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
|
pMenu(Menu &menu) : pAction(menu), menu(menu), hbitmap(0) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
void destructor();
|
void destructor();
|
||||||
|
void createBitmap();
|
||||||
void update(Window &parentWindow, Menu *parentMenu = 0);
|
void update(Window &parentWindow, Menu *parentMenu = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -183,7 +188,7 @@ struct pRadioItem : public pAction {
|
|||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioItem&> &group);
|
void setGroup(const array<RadioItem&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||||
@@ -398,7 +403,7 @@ struct pRadioBox : public pWidget {
|
|||||||
bool checked();
|
bool checked();
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const reference_array<RadioBox&> &group);
|
void setGroup(const array<RadioBox&> &group);
|
||||||
void setText(const string &text);
|
void setText(const string &text);
|
||||||
|
|
||||||
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
|
||||||
|
1
bsnes/phoenix/windows/settings.cpp
Executable file
1
bsnes/phoenix/windows/settings.cpp
Executable file
@@ -0,0 +1 @@
|
|||||||
|
static Settings *settings = nullptr;
|
@@ -1,17 +1,44 @@
|
|||||||
static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
|
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
|
if(object == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
if(!dynamic_cast<Canvas*>(object)) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
Canvas &canvas = (Canvas&)*object;
|
||||||
|
|
||||||
if(msg == WM_GETDLGCODE) {
|
if(msg == WM_GETDLGCODE) {
|
||||||
return DLGC_STATIC | DLGC_WANTCHARS;
|
return DLGC_STATIC | DLGC_WANTCHARS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(msg == WM_PAINT) {
|
if(msg == WM_PAINT) {
|
||||||
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
canvas.p.paint();
|
||||||
if(object && dynamic_cast<Canvas*>(object)) {
|
|
||||||
Canvas &canvas = (Canvas&)*object;
|
|
||||||
canvas.p.paint();
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(msg == WM_MOUSEMOVE) {
|
||||||
|
TRACKMOUSEEVENT tracker = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, hwnd };
|
||||||
|
TrackMouseEvent(&tracker);
|
||||||
|
if(canvas.onMouseMove) canvas.onMouseMove({ (int16_t)LOWORD(lparam), (int16_t)HIWORD(lparam) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_MOUSELEAVE) {
|
||||||
|
if(canvas.onMouseLeave) canvas.onMouseLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN || msg == WM_RBUTTONDOWN) {
|
||||||
|
if(canvas.onMousePress) switch(msg) {
|
||||||
|
case WM_LBUTTONDOWN: canvas.onMousePress(Mouse::Button::Left); break;
|
||||||
|
case WM_MBUTTONDOWN: canvas.onMousePress(Mouse::Button::Middle); break;
|
||||||
|
case WM_RBUTTONDOWN: canvas.onMousePress(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_LBUTTONUP || msg == WM_MBUTTONUP || msg == WM_RBUTTONUP) {
|
||||||
|
if(canvas.onMouseRelease) switch(msg) {
|
||||||
|
case WM_LBUTTONUP: canvas.onMouseRelease(Mouse::Button::Left); break;
|
||||||
|
case WM_MBUTTONUP: canvas.onMouseRelease(Mouse::Button::Middle); break;
|
||||||
|
case WM_RBUTTONUP: canvas.onMouseRelease(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@ void pRadioBox::setChecked() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setGroup(const reference_array<RadioBox&> &group) {
|
void pRadioBox::setGroup(const array<RadioBox&> &group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioBox::setText(const string &text) {
|
void pRadioBox::setText(const string &text) {
|
||||||
|
@@ -1,3 +1,42 @@
|
|||||||
|
static LRESULT CALLBACK Viewport_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
|
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
|
if(object == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
if(!dynamic_cast<Viewport*>(object)) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
Viewport &viewport = (Viewport&)*object;
|
||||||
|
|
||||||
|
if(msg == WM_GETDLGCODE) {
|
||||||
|
return DLGC_STATIC | DLGC_WANTCHARS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_MOUSEMOVE) {
|
||||||
|
TRACKMOUSEEVENT tracker = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, hwnd };
|
||||||
|
TrackMouseEvent(&tracker);
|
||||||
|
if(viewport.onMouseMove) viewport.onMouseMove({ (int16_t)LOWORD(lparam), (int16_t)HIWORD(lparam) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_MOUSELEAVE) {
|
||||||
|
if(viewport.onMouseLeave) viewport.onMouseLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN || msg == WM_RBUTTONDOWN) {
|
||||||
|
if(viewport.onMousePress) switch(msg) {
|
||||||
|
case WM_LBUTTONDOWN: viewport.onMousePress(Mouse::Button::Left); break;
|
||||||
|
case WM_MBUTTONDOWN: viewport.onMousePress(Mouse::Button::Middle); break;
|
||||||
|
case WM_RBUTTONDOWN: viewport.onMousePress(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(msg == WM_LBUTTONUP || msg == WM_MBUTTONUP || msg == WM_RBUTTONUP) {
|
||||||
|
if(viewport.onMouseRelease) switch(msg) {
|
||||||
|
case WM_LBUTTONUP: viewport.onMouseRelease(Mouse::Button::Left); break;
|
||||||
|
case WM_MBUTTONUP: viewport.onMouseRelease(Mouse::Button::Middle); break;
|
||||||
|
case WM_RBUTTONUP: viewport.onMouseRelease(Mouse::Button::Right); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t pViewport::handle() {
|
uintptr_t pViewport::handle() {
|
||||||
return (uintptr_t)hwnd;
|
return (uintptr_t)hwnd;
|
||||||
}
|
}
|
||||||
@@ -15,9 +54,4 @@ void pViewport::destructor() {
|
|||||||
void pViewport::orphan() {
|
void pViewport::orphan() {
|
||||||
destructor();
|
destructor();
|
||||||
constructor();
|
constructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK Viewport_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
||||||
if(msg == WM_GETDLGCODE) return DLGC_STATIC | DLGC_WANTCHARS;
|
|
||||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
||||||
}
|
|
@@ -91,7 +91,6 @@ struct Cartridge : property<Cartridge> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void parse_markup(const char*);
|
void parse_markup(const char*);
|
||||||
unsigned parse_markup_integer(string&);
|
|
||||||
void parse_markup_map(Mapping&, XML::Node&);
|
void parse_markup_map(Mapping&, XML::Node&);
|
||||||
|
|
||||||
void parse_markup_rom(XML::Node&);
|
void parse_markup_rom(XML::Node&);
|
||||||
|
@@ -29,14 +29,9 @@ void Cartridge::parse_markup(const char *markup) {
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
unsigned Cartridge::parse_markup_integer(string &data) {
|
|
||||||
if(strbegin(data, "0x")) return hex(data);
|
|
||||||
return decimal(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cartridge::parse_markup_map(Mapping &m, XML::Node &map) {
|
void Cartridge::parse_markup_map(Mapping &m, XML::Node &map) {
|
||||||
m.offset = parse_markup_integer(map["offset"].data);
|
m.offset = numeral(map["offset"].data);
|
||||||
m.size = parse_markup_integer(map["size"].data);
|
m.size = numeral(map["size"].data);
|
||||||
|
|
||||||
string data = map["mode"].data;
|
string data = map["mode"].data;
|
||||||
if(data == "direct") m.mode = Bus::MapMode::Direct;
|
if(data == "direct") m.mode = Bus::MapMode::Direct;
|
||||||
@@ -82,7 +77,7 @@ void Cartridge::parse_markup_rom(XML::Node &root) {
|
|||||||
|
|
||||||
void Cartridge::parse_markup_ram(XML::Node &root) {
|
void Cartridge::parse_markup_ram(XML::Node &root) {
|
||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
ram_size = parse_markup_integer(root["size"].data);
|
ram_size = numeral(root["size"].data);
|
||||||
for(auto &node : root) {
|
for(auto &node : root) {
|
||||||
Mapping m(ram);
|
Mapping m(ram);
|
||||||
parse_markup_map(m, node);
|
parse_markup_map(m, node);
|
||||||
@@ -100,11 +95,11 @@ void Cartridge::parse_markup_nss(XML::Node &root) {
|
|||||||
if(number >= 16) break; //more than 16 DIP switches is not physically possible
|
if(number >= 16) break; //more than 16 DIP switches is not physically possible
|
||||||
|
|
||||||
information.nss.option[number].reset();
|
information.nss.option[number].reset();
|
||||||
information.nss.setting[number] = node["name"].data;
|
information.nss.setting.append(node["name"].data);
|
||||||
for(auto &leaf : node) {
|
for(auto &leaf : node) {
|
||||||
if(leaf.name != "option") continue;
|
if(leaf.name != "option") continue;
|
||||||
string name = leaf["name"].data;
|
string name = leaf["name"].data;
|
||||||
unsigned value = parse_markup_integer(leaf["value"].data);
|
unsigned value = numeral(leaf["value"].data);
|
||||||
information.nss.option[number].append({ hex<4>(value), ":", name });
|
information.nss.option[number].append({ hex<4>(value), ":", name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +109,7 @@ void Cartridge::parse_markup_icd2(XML::Node &root) {
|
|||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
if(mode != Mode::SuperGameBoy) return;
|
if(mode != Mode::SuperGameBoy) return;
|
||||||
|
|
||||||
icd2.revision = max(1, parse_markup_integer(root["revision"].data));
|
icd2.revision = max(1, numeral(root["revision"].data));
|
||||||
|
|
||||||
for(auto &node : root) {
|
for(auto &node : root) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
@@ -140,7 +135,7 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
|
|||||||
if(node.name == "ram") {
|
if(node.name == "ram") {
|
||||||
for(auto &leaf : node) {
|
for(auto &leaf : node) {
|
||||||
if(leaf.name == "size") {
|
if(leaf.name == "size") {
|
||||||
ram_size = parse_markup_integer(leaf.data);
|
ram_size = numeral(leaf.data);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(leaf.name != "map") continue;
|
if(leaf.name != "map") continue;
|
||||||
@@ -193,7 +188,7 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
|
|||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
ram_size = parse_markup_integer(bwram["size"].data);
|
ram_size = numeral(bwram["size"].data);
|
||||||
for(auto &node : bwram) {
|
for(auto &node : bwram) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
Mapping m(sa1.cpubwram);
|
Mapping m(sa1.cpubwram);
|
||||||
@@ -217,7 +212,7 @@ void Cartridge::parse_markup_necdsp(XML::Node &root) {
|
|||||||
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
|
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
|
||||||
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
|
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
|
||||||
|
|
||||||
necdsp.frequency = parse_markup_integer(root["frequency"].data);
|
necdsp.frequency = numeral(root["frequency"].data);
|
||||||
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
||||||
necdsp.revision
|
necdsp.revision
|
||||||
= root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725
|
= root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725
|
||||||
@@ -286,7 +281,7 @@ void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
|
|||||||
|
|
||||||
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
|
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000;
|
||||||
|
|
||||||
hitachidsp.frequency = parse_markup_integer(root["frequency"].data);
|
hitachidsp.frequency = numeral(root["frequency"].data);
|
||||||
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
|
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
|
||||||
string firmware = root["firmware"].data;
|
string firmware = root["firmware"].data;
|
||||||
string sha256 = root["sha256"].data;
|
string sha256 = root["sha256"].data;
|
||||||
@@ -379,7 +374,7 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(node.name == "ram") {
|
if(node.name == "ram") {
|
||||||
unsigned ram_size = parse_markup_integer(node["size"].data);
|
unsigned ram_size = numeral(node["size"].data);
|
||||||
for(auto &leaf : node) {
|
for(auto &leaf : node) {
|
||||||
if(leaf.name != "map") continue;
|
if(leaf.name != "map") continue;
|
||||||
Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
|
Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
|
||||||
@@ -434,7 +429,7 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
|
|||||||
auto &dcu = root["dcu"];
|
auto &dcu = root["dcu"];
|
||||||
auto &rtc = root["rtc"];
|
auto &rtc = root["rtc"];
|
||||||
|
|
||||||
ram_size = parse_markup_integer(ram["size"].data);
|
ram_size = numeral(ram["size"].data);
|
||||||
for(auto &node : ram) {
|
for(auto &node : ram) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 });
|
Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 });
|
||||||
@@ -449,7 +444,7 @@ void Cartridge::parse_markup_spc7110(XML::Node &root) {
|
|||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
spc7110.data_rom_offset = parse_markup_integer(mcu["offset"].data);
|
spc7110.data_rom_offset = numeral(mcu["offset"].data);
|
||||||
if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000;
|
if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000;
|
||||||
for(auto &node : mcu) {
|
for(auto &node : mcu) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
@@ -524,7 +519,7 @@ void Cartridge::parse_markup_link(XML::Node &root) {
|
|||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
has_link = true;
|
has_link = true;
|
||||||
|
|
||||||
link.frequency = max(1, parse_markup_integer(root["frequency"].data));
|
link.frequency = max(1, numeral(root["frequency"].data));
|
||||||
link.program = root["program"].data;
|
link.program = root["program"].data;
|
||||||
|
|
||||||
for(auto &node : root) {
|
for(auto &node : root) {
|
||||||
|
@@ -9,6 +9,7 @@ unsigned Video::palette30(unsigned color) {
|
|||||||
unsigned r = (color >> 0) & 31;
|
unsigned r = (color >> 0) & 31;
|
||||||
|
|
||||||
double L = (1.0 + l) / 16.0;
|
double L = (1.0 + l) / 16.0;
|
||||||
|
if(l == 0) L *= 0.5;
|
||||||
unsigned R = L * ((r << 5) + (r << 0));
|
unsigned R = L * ((r << 5) + (r << 0));
|
||||||
unsigned G = L * ((g << 5) + (g << 0));
|
unsigned G = L * ((g << 5) + (g << 0));
|
||||||
unsigned B = L * ((b << 5) + (b << 0));
|
unsigned B = L * ((b << 5) + (b << 0));
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
DipSwitches *dipSwitches = 0;
|
DipSwitches *dipSwitches = nullptr;
|
||||||
|
|
||||||
DipSwitch::DipSwitch() {
|
DipSwitch::DipSwitch() {
|
||||||
append(name, { ~0, 0 }, 5);
|
append(name, { ~0, 0 }, 5);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
FileBrowser *fileBrowser = 0;
|
FileBrowser *fileBrowser = nullptr;
|
||||||
|
|
||||||
FileBrowser::FileBrowser() {
|
FileBrowser::FileBrowser() {
|
||||||
setGeometry({ 128, 128, 640, 400 });
|
setGeometry({ 128, 128, 640, 400 });
|
||||||
@@ -130,21 +130,23 @@ bool FileBrowser::loadFolder(const string &requestedPath) {
|
|||||||
if(path.wildcard(filter)) accept = true;
|
if(path.wildcard(filter)) accept = true;
|
||||||
}
|
}
|
||||||
if(accept == false) return false;
|
if(accept == false) return false;
|
||||||
|
loadFile(requestedPath);
|
||||||
lstring contentsList = directory::contents(requestedPath);
|
|
||||||
lstring fileNameList;
|
|
||||||
for(auto &fileName : contentsList) {
|
|
||||||
for(auto &filter : mode->filter) {
|
|
||||||
if(fileName.wildcard(filter)) {
|
|
||||||
fileNameList.append(fileName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fileNameList.size() != 1) return false;
|
|
||||||
loadFile({ requestedPath, fileNameList[0] });
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// lstring contentsList = directory::contents(requestedPath);
|
||||||
|
// lstring fileNameList;
|
||||||
|
// for(auto &fileName : contentsList) {
|
||||||
|
// for(auto &filter : mode->filter) {
|
||||||
|
// if(fileName.wildcard(filter)) {
|
||||||
|
// fileNameList.append(fileName);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(fileNameList.size() != 1) return false;
|
||||||
|
// loadFile({ requestedPath, fileNameList[0] });
|
||||||
|
// return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileBrowser::loadFile(const string &filename) {
|
void FileBrowser::loadFile(const string &filename) {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
MainWindow *mainWindow = 0;
|
MainWindow *mainWindow = nullptr;
|
||||||
|
|
||||||
MainWindow::MainWindow() {
|
MainWindow::MainWindow() {
|
||||||
setTitle(application->title);
|
setTitle(application->title);
|
||||||
@@ -338,7 +338,7 @@ void MainWindow::setupVideoFilters() {
|
|||||||
path = { application->userpath, "filters/" };
|
path = { application->userpath, "filters/" };
|
||||||
files = directory::files(path, "*.filter");
|
files = directory::files(path, "*.filter");
|
||||||
}
|
}
|
||||||
reference_array<RadioItem&> group;
|
array<RadioItem&> group;
|
||||||
|
|
||||||
settingsVideoFilterList = new RadioItem[files.size()];
|
settingsVideoFilterList = new RadioItem[files.size()];
|
||||||
for(unsigned n = 0; n < files.size(); n++) {
|
for(unsigned n = 0; n < files.size(); n++) {
|
||||||
@@ -369,7 +369,7 @@ void MainWindow::setupVideoShaders() {
|
|||||||
path = { application->userpath, "shaders/" };
|
path = { application->userpath, "shaders/" };
|
||||||
files = directory::files(path, { "*.", config->video.driver, ".shader" });
|
files = directory::files(path, { "*.", config->video.driver, ".shader" });
|
||||||
}
|
}
|
||||||
reference_array<RadioItem&> group;
|
array<RadioItem&> group;
|
||||||
|
|
||||||
settingsVideoShaderList = new RadioItem[files.size()];
|
settingsVideoShaderList = new RadioItem[files.size()];
|
||||||
for(unsigned n = 0; n < files.size(); n++) {
|
for(unsigned n = 0; n < files.size(); n++) {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
SlotLoader *slotLoader = 0;
|
SlotLoader *slotLoader = nullptr;
|
||||||
|
|
||||||
SlotLoaderPath::SlotLoaderPath() {
|
SlotLoaderPath::SlotLoaderPath() {
|
||||||
browse.setText("Browse ...");
|
browse.setText("Browse ...");
|
||||||
|
@@ -27,7 +27,7 @@ struct TurboInput : DigitalInput {
|
|||||||
TurboInput();
|
TurboInput();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TertiaryInput : reference_array<AbstractInput&> {
|
struct TertiaryInput : array<AbstractInput&> {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
virtual void attach(const string &primaryName, const string &secondaryName);
|
virtual void attach(const string &primaryName, const string &secondaryName);
|
||||||
@@ -35,14 +35,14 @@ struct TertiaryInput : reference_array<AbstractInput&> {
|
|||||||
virtual int16_t poll(unsigned n);
|
virtual int16_t poll(unsigned n);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SecondaryInput : reference_array<TertiaryInput&> {
|
struct SecondaryInput : array<TertiaryInput&> {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
virtual void attach(const string &primaryName);
|
virtual void attach(const string &primaryName);
|
||||||
virtual void bind();
|
virtual void bind();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PrimaryInput : reference_array<SecondaryInput&> {
|
struct PrimaryInput : array<SecondaryInput&> {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
virtual void attach();
|
virtual void attach();
|
||||||
@@ -59,7 +59,7 @@ struct InputManager {
|
|||||||
int16_t scancode[2][Scancode::Limit];
|
int16_t scancode[2][Scancode::Limit];
|
||||||
bool activeScancode;
|
bool activeScancode;
|
||||||
|
|
||||||
reference_array<PrimaryInput&> inputList;
|
array<PrimaryInput&> inputList;
|
||||||
NesInput nes;
|
NesInput nes;
|
||||||
SnesInput snes;
|
SnesInput snes;
|
||||||
GameBoyInput gameBoy;
|
GameBoyInput gameBoy;
|
||||||
|
@@ -10,10 +10,20 @@ bool InterfaceGameBoy::cartridgeLoaded() {
|
|||||||
bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const string &filename) {
|
bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const string &filename) {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
if(interface->loadFile(filename, data, size) == false) return false;
|
|
||||||
|
if(filename.endswith("/")) {
|
||||||
|
string basename = filename;
|
||||||
|
basename.rtrim<1>("/");
|
||||||
|
basename.append("/", notdir(basename));
|
||||||
|
if(file::read(basename, data, size) == false) return false;
|
||||||
|
interface->baseName = nall::basename(basename);
|
||||||
|
} else {
|
||||||
|
if(file::read(filename, data, size) == false) return false;
|
||||||
|
interface->baseName = nall::basename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(filename);
|
interface->applyPatch(interface->baseName, data, size);
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
|
@@ -188,11 +188,9 @@ Interface::Interface() : core(nullptr) {
|
|||||||
|
|
||||||
//internal
|
//internal
|
||||||
|
|
||||||
bool Interface::loadFile(const string &filename, uint8_t *&data, unsigned &size) {
|
bool Interface::applyPatch(const string &filename, uint8_t *&data, unsigned &size) {
|
||||||
if(file::read(filename, data, size) == false) return false;
|
|
||||||
|
|
||||||
string patchname = { nall::basename(filename), ".bps" };
|
string patchname = { nall::basename(filename), ".bps" };
|
||||||
if(file::exists(patchname) == false) return true;
|
if(file::exists(patchname) == false) return false;
|
||||||
|
|
||||||
bpspatch bps;
|
bpspatch bps;
|
||||||
bps.modify(patchname);
|
bps.modify(patchname);
|
||||||
@@ -202,7 +200,7 @@ bool Interface::loadFile(const string &filename, uint8_t *&data, unsigned &size)
|
|||||||
bps.target(targetData, targetSize);
|
bps.target(targetData, targetSize);
|
||||||
if(bps.apply() != bpspatch::result::success) {
|
if(bps.apply() != bpspatch::result::success) {
|
||||||
delete[] targetData;
|
delete[] targetData;
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
@@ -55,7 +55,7 @@ struct Interface : property<Interface> {
|
|||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
bool loadFile(const string &filename, uint8_t *&data, unsigned &size);
|
bool applyPatch(const string &filename, uint8_t *&data, unsigned &size);
|
||||||
void videoRefresh(const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height);
|
void videoRefresh(const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height);
|
||||||
|
|
||||||
string baseName; // = "/path/to/cartridge" (no extension)
|
string baseName; // = "/path/to/cartridge" (no extension)
|
||||||
|
@@ -25,10 +25,37 @@ bool InterfaceNES::cartridgeLoaded() {
|
|||||||
bool InterfaceNES::loadCartridge(const string &filename) {
|
bool InterfaceNES::loadCartridge(const string &filename) {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
if(interface->loadFile(filename, data, size) == false) return false;
|
|
||||||
|
if(filename.endswith("/")) {
|
||||||
|
string basename = filename;
|
||||||
|
basename.rtrim<1>("/");
|
||||||
|
basename.append("/", notdir(nall::basename(basename)));
|
||||||
|
|
||||||
|
if(file::exists({ basename, ".prg" }) && file::exists({ basename, ".chr" })) {
|
||||||
|
unsigned prgsize = file::size({ basename, ".prg" });
|
||||||
|
unsigned chrsize = file::size({ basename, ".chr" });
|
||||||
|
data = new uint8_t[size = prgsize + chrsize];
|
||||||
|
nall::file fp;
|
||||||
|
fp.open({ basename, ".prg" }, file::mode::read);
|
||||||
|
fp.read(data, fp.size());
|
||||||
|
fp.close();
|
||||||
|
fp.open({ basename, ".chr" }, file::mode::read);
|
||||||
|
fp.read(data + prgsize, fp.size());
|
||||||
|
fp.close();
|
||||||
|
} else if(file::exists({ basename, ".fc" })) {
|
||||||
|
file::read({ basename, ".fc" }, data, size);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface->baseName = basename;
|
||||||
|
} else {
|
||||||
|
file::read(filename, data, size);
|
||||||
|
interface->baseName = nall::basename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(filename);
|
interface->applyPatch(interface->baseName, data, size);
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
|
@@ -30,14 +30,25 @@ bool InterfaceSNES::cartridgeLoaded() {
|
|||||||
return SNES::cartridge.loaded();
|
return SNES::cartridge.loaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterfaceSNES::loadCartridge(const string &basename) {
|
bool InterfaceSNES::loadFile(string &filename, uint8_t *&data, unsigned &size) {
|
||||||
|
if(filename.endswith("/")) {
|
||||||
|
filename.rtrim<1>("/");
|
||||||
|
filename.append("/", notdir(filename));
|
||||||
|
}
|
||||||
|
if(file::read(filename, data, size) == false) return false;
|
||||||
|
filename = nall::basename(filename);
|
||||||
|
interface->applyPatch(filename, data, size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InterfaceSNES::loadCartridge(string basename) {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
if(interface->loadFile(basename, data, size) == false) return false;
|
if(loadFile(basename, data, size) == false) return false;
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(basename);
|
interface->baseName = basename;
|
||||||
interface->slotName = { nall::basename(basename) };
|
interface->slotName = { basename };
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
@@ -55,16 +66,16 @@ bool InterfaceSNES::loadCartridge(const string &basename) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterfaceSNES::loadSatellaviewSlottedCartridge(const string &basename, const string &slotname) {
|
bool InterfaceSNES::loadSatellaviewSlottedCartridge(string basename, string slotname) {
|
||||||
uint8_t *data[2];
|
uint8_t *data[2];
|
||||||
unsigned size[2];
|
unsigned size[2];
|
||||||
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
|
if(loadFile(basename, data[0], size[0]) == false) return false;
|
||||||
interface->loadFile(slotname, data[1], size[1]);
|
loadFile(slotname, data[1], size[1]);
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(basename);
|
interface->baseName = basename;
|
||||||
if(data[1]) interface->baseName.append("+", nall::basename(notdir(slotname)));
|
if(data[1]) interface->baseName.append("+", notdir(slotname));
|
||||||
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
|
interface->slotName = { basename, slotname };
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
@@ -84,16 +95,16 @@ bool InterfaceSNES::loadSatellaviewSlottedCartridge(const string &basename, cons
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterfaceSNES::loadSatellaviewCartridge(const string &basename, const string &slotname) {
|
bool InterfaceSNES::loadSatellaviewCartridge(string basename, string slotname) {
|
||||||
uint8_t *data[2];
|
uint8_t *data[2];
|
||||||
unsigned size[2];
|
unsigned size[2];
|
||||||
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
|
if(loadFile(basename, data[0], size[0]) == false) return false;
|
||||||
interface->loadFile(slotname, data[1], size[1]);
|
loadFile(slotname, data[1], size[1]);
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(basename);
|
interface->baseName = basename;
|
||||||
if(data[1]) interface->baseName.append("+", nall::basename(notdir(slotname)));
|
if(data[1]) interface->baseName.append("+", notdir(slotname));
|
||||||
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
|
interface->slotName = { basename, slotname };
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
@@ -113,19 +124,19 @@ bool InterfaceSNES::loadSatellaviewCartridge(const string &basename, const strin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterfaceSNES::loadSufamiTurboCartridge(const string &basename, const string &slotAname, const string &slotBname) {
|
bool InterfaceSNES::loadSufamiTurboCartridge(string basename, string slotAname, string slotBname) {
|
||||||
uint8_t *data[3];
|
uint8_t *data[3];
|
||||||
unsigned size[3];
|
unsigned size[3];
|
||||||
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
|
if(loadFile(basename, data[0], size[0]) == false) return false;
|
||||||
interface->loadFile(slotAname, data[1], size[1]);
|
loadFile(slotAname, data[1], size[1]);
|
||||||
interface->loadFile(slotBname, data[2], size[2]);
|
loadFile(slotBname, data[2], size[2]);
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(basename);
|
interface->baseName = basename;
|
||||||
if(data[1] && data[2]) interface->baseName = { nall::basename(slotAname), "+", nall::basename(notdir(slotBname)) };
|
if(data[1] && data[2]) interface->baseName = { slotAname, "+", notdir(slotBname) };
|
||||||
else if(data[1]) interface->baseName = nall::basename(slotAname);
|
else if(data[1]) interface->baseName = slotAname;
|
||||||
else if(data[2]) interface->baseName = nall::basename(slotBname);
|
else if(data[2]) interface->baseName = slotBname;
|
||||||
interface->slotName = { nall::basename(basename), nall::basename(slotAname), nall::basename(slotBname) };
|
interface->slotName = { basename, slotAname, slotBname };
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
@@ -147,16 +158,16 @@ bool InterfaceSNES::loadSufamiTurboCartridge(const string &basename, const strin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterfaceSNES::loadSuperGameBoyCartridge(const string &basename, const string &slotname) {
|
bool InterfaceSNES::loadSuperGameBoyCartridge(string basename, string slotname) {
|
||||||
uint8_t *data[2];
|
uint8_t *data[2];
|
||||||
unsigned size[2];
|
unsigned size[2];
|
||||||
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
|
if(loadFile(basename, data[0], size[0]) == false) return false;
|
||||||
interface->loadFile(slotname, data[1], size[1]);
|
loadFile(slotname, data[1], size[1]);
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
interface->baseName = nall::basename(basename);
|
interface->baseName = basename;
|
||||||
if(data[1]) interface->baseName = nall::basename(slotname);
|
if(data[1]) interface->baseName = slotname;
|
||||||
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
|
interface->slotName = { basename, slotname };
|
||||||
|
|
||||||
string markup;
|
string markup;
|
||||||
markup.readfile({ interface->baseName, ".xml" });
|
markup.readfile({ interface->baseName, ".xml" });
|
||||||
|
@@ -4,11 +4,12 @@ struct InterfaceSNES : InterfaceCore, SNES::Interface {
|
|||||||
void setController(bool port, unsigned device);
|
void setController(bool port, unsigned device);
|
||||||
|
|
||||||
bool cartridgeLoaded();
|
bool cartridgeLoaded();
|
||||||
bool loadCartridge(const string &filename);
|
bool loadFile(string &filename, uint8_t *&data, unsigned &size);
|
||||||
bool loadSatellaviewSlottedCartridge(const string &basename, const string &slotname);
|
bool loadCartridge(string basename);
|
||||||
bool loadSatellaviewCartridge(const string &basename, const string &slotname);
|
bool loadSatellaviewSlottedCartridge(string basename, string slotname);
|
||||||
bool loadSufamiTurboCartridge(const string &basename, const string &slotAname, const string &slotBname);
|
bool loadSatellaviewCartridge(string basename, string slotname);
|
||||||
bool loadSuperGameBoyCartridge(const string &basename, const string &slotname);
|
bool loadSufamiTurboCartridge(string basename, string slotAname, string slotBname);
|
||||||
|
bool loadSuperGameBoyCartridge(string basename, string slotname);
|
||||||
void unloadCartridge();
|
void unloadCartridge();
|
||||||
|
|
||||||
void power();
|
void power();
|
||||||
|
@@ -27,7 +27,7 @@ void Application::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(int argc, char **argv) {
|
Application::Application(int argc, char **argv) {
|
||||||
title = "bsnes v085.01";
|
title = "bsnes v085.02";
|
||||||
|
|
||||||
application = this;
|
application = this;
|
||||||
quit = false;
|
quit = false;
|
||||||
|
Reference in New Issue
Block a user