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:
Tim Allen 2012-01-26 17:50:09 +11:00
parent cc518dcc3c
commit e4e50308d2
74 changed files with 978 additions and 510 deletions

View File

@ -45,8 +45,8 @@ void Cartridge::load(System::Revision revision, const string &markup, const uint
info.rtc = document["cartridge"]["rtc"].data == "true";
info.rumble = document["cartridge"]["rumble"].data == "true";
info.romsize = hex(document["cartridge"]["rom"]["size"].data);
info.ramsize = hex(document["cartridge"]["ram"]["size"].data);
info.romsize = numeral(document["cartridge"]["rom"]["size"].data);
info.ramsize = numeral(document["cartridge"]["ram"]["size"].data);
info.battery = document["cartridge"]["ram"]["battery"].data == "true";
switch(info.mapper) { default:

View File

@ -2,17 +2,15 @@
#define NALL_ANY_HPP
#include <typeinfo>
#include <type_traits>
#include <nall/static.hpp>
#include <nall/type_traits.hpp>
namespace nall {
class any {
public:
struct any {
bool empty() const { return container; }
const std::type_info& type() const { return container ? container->type() : typeid(void); }
template<typename T> any& operator=(const T& value_) {
typedef typename static_if<
typedef typename type_if<
std::is_array<T>::value,
typename std::remove_extent<typename std::add_const<T>::type>::type*,
T

View File

@ -4,143 +4,286 @@
#include <stdlib.h>
#include <algorithm>
#include <initializer_list>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/sort.hpp>
#include <nall/type_traits.hpp>
#include <nall/utility.hpp>
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:
unsigned size() const { return buffersize; }
unsigned capacity() const { return poolsize; }
template<typename T, typename Enable = void> struct array;
void reset() {
if(pool) free(pool);
pool = nullptr;
poolsize = 0;
buffersize = 0;
//non-reference array
//===================
template<typename T> struct array<T, typename std::enable_if<!std::is_reference<T>::value>::type> {
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) {
if(newsize == poolsize) return;
void sort() {
nall::sort(pool, objectsize);
}
pool = (T*)realloc(pool, newsize * sizeof(T));
poolsize = newsize;
buffersize = min(buffersize, newsize);
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 };
}
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) {
if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2
buffersize = newsize;
}
optional<unsigned> find(const T& data) {
for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return { true, n };
return { false, 0u };
}
T* get(unsigned minsize = 0) {
if(minsize > buffersize) resize(minsize);
if(minsize > buffersize) throw "array[] out of bounds";
return pool;
}
template<typename... Args> array(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) {
construct(std::forward<Args>(args)...);
}
void append(const T data) {
operator[](buffersize) = data;
}
~array() {
reset();
}
void append(const T data[], unsigned length) {
for(unsigned n = 0; n < length; n++) operator[](buffersize) = data[n];
}
array& operator=(const array &source) {
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() {
if(size > 0) resize(size - 1); //remove last element only
}
array& operator=(const array &&source) {
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) {
for(unsigned i = index; count + i < buffersize; i++) {
pool[i] = pool[count + i];
}
if(count + index >= buffersize) resize(index); //every element >= index was removed
else resize(buffersize - count);
}
T& operator[](unsigned position) const {
if(position >= objectsize) throw exception_out_of_bounds();
return *pool[position];
}
optional<unsigned> find(const T data) {
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return { true, i };
return { false, 0 };
}
void clear() {
memset(pool, 0, buffersize * sizeof(T));
}
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]; }
//iteration
struct iterator {
bool operator!=(const iterator &source) const { return position != source.position; }
T& operator*() { return source.operator[](position); }
iterator& operator++() { position++; return *this; }
iterator(const array &source, unsigned position) : source(source), position(position) {}
private:
const array &source;
unsigned position;
};
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

View File

@ -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) {
return atof(s);
}

View File

@ -53,21 +53,18 @@ namespace nall {
}
}
};
linear_vector<item_t> list;
vector<item_t> list;
template<typename T>
inline void append(T &data, const char *name, const char *desc = "") {
unsigned n = list.size();
list[n].data = (uintptr_t)&data;
list[n].name = name;
list[n].desc = desc;
if(configuration_traits::is_boolean<T>::value) list[n].type = boolean_t;
else if(configuration_traits::is_signed<T>::value) list[n].type = signed_t;
else if(configuration_traits::is_unsigned<T>::value) list[n].type = unsigned_t;
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;
item_t item = { (uintptr_t)&data, name, desc };
if(configuration_traits::is_boolean<T>::value) item.type = boolean_t;
else if(configuration_traits::is_signed<T>::value) item.type = signed_t;
else if(configuration_traits::is_unsigned<T>::value) item.type = unsigned_t;
else if(configuration_traits::is_double<T>::value) item.type = double_t;
else if(configuration_traits::is_string<T>::value) item.type = string_t;
else item.type = unknown_t;
list.append(item);
}
//deprecated

View File

@ -56,7 +56,7 @@ struct directory {
}
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
return list;
}
@ -83,7 +83,7 @@ struct directory {
}
FindClose(handle);
}
if(list.size() > 0) sort(&list[0], list.size());
if(list.size() > 0) list.sort();
return list;
}
@ -116,7 +116,7 @@ struct directory {
}
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
return list;
}
@ -136,7 +136,7 @@ struct directory {
}
closedir(dp);
}
if(list.size() > 0) sort(&list[0], list.size());
if(list.size() > 0) list.sort();
return list;
}

View File

@ -35,6 +35,7 @@ struct image {
inline image(const 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();
inline ~image();
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);
}
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() {
free();
}

View File

@ -12,51 +12,74 @@ struct map {
RHS data;
};
void reset() {
inline void reset() {
list.reset();
}
unsigned size() const {
inline unsigned size() const {
return list.size();
}
//O(n)
void append(const LHS &name, const RHS &data) {
//O(log n) find
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();
for(unsigned n = 0; n < size(); n++) {
if(name < list[n].name) { offset = n; break; }
}
list.insert(offset, { name, data });
return list[offset].data;
}
//O(log n)
RHS& operator[](const LHS &name) {
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(name > list[middle].name) first = middle + 1; //search upper half
else return list[middle].data; //match found
}
//O(log n) find
inline void modify(const LHS &name, const RHS &data) {
if(auto position = find(name)) list[position()].data = data;
}
//O(n) remove + O(log n) find
inline void remove(const LHS &name) {
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;
}
//O(log n) nothrow
const RHS& operator()(const LHS &name, const RHS &data) {
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(name > list[middle].name) first = middle + 1; //search upper half
else return list[middle].data; //match found
}
inline const RHS& operator[](const LHS &name) const {
if(auto position = find(name)) return list[position()].data;
throw;
}
inline RHS& operator()(const LHS &name) {
return insert(name, RHS());
}
inline const RHS& operator()(const LHS &name, const RHS &data) const {
if(auto position = find(name)) return list[position()].data;
return data;
}
pair* begin() { return list.begin(); }
pair* end() { return list.end(); }
const pair* begin() const { return list.begin(); }
const pair* end() const { return list.end(); }
inline pair* begin() { return list.begin(); }
inline pair* end() { return list.end(); }
inline const pair* begin() const { return list.begin(); }
inline const pair* end() const { return list.end(); }
protected:
vector<pair> list;
@ -64,22 +87,28 @@ protected:
template<typename LHS, typename RHS>
struct bidirectional_map {
map<LHS, RHS> lhs;
map<RHS, LHS> rhs;
const map<LHS, RHS> &lhs;
const map<RHS, LHS> &rhs;
void reset() {
lhs.reset();
rhs.reset();
inline void reset() {
llist.reset();
rlist.reset();
}
unsigned size() const {
return lhs.size();
inline unsigned size() const {
return llist.size();
}
void append(const LHS &ldata, const RHS &rdata) {
lhs.append(ldata, rdata);
rhs.append(rdata, ldata);
inline void insert(const LHS &ldata, const RHS &rdata) {
llist.insert(ldata, rdata);
rlist.insert(rdata, ldata);
}
inline bidirectional_map() : lhs(llist), rhs(rlist) {}
protected:
map<LHS, RHS> llist;
map<RHS, LHS> rlist;
};
}

View File

@ -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

View File

@ -11,53 +11,67 @@
//stack: O(log n)
//stable?: yes
//notes:
//there are two primary reasons for choosing merge sort
//over the (usually) faster quick sort*:
//1: it is a stable sort.
//2: it lacks O(n^2) worst-case overhead.
//(* which is also O(n log n) in the average case.)
//note: merge sort was chosen over quick sort, because:
//* it is a stable sort
//* it lacks O(n^2) worst-case overhead
#define NALL_SORT_INSERTION
//#define NALL_SORT_SELECTION
namespace nall {
template<typename T>
void sort(T list[], unsigned length) {
if(length <= 1) return; //nothing to sort
template<typename T, typename Comparator>
void sort(T list[], unsigned size, const Comparator &lessthan) {
if(size <= 1) return; //nothing to sort
//use insertion sort to quickly sort smaller blocks
if(length < 64) {
for(unsigned i = 0; i < length; i++) {
if(size < 64) {
#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;
for(unsigned j = i + 1; j < length; j++) {
if(list[j] < list[min]) min = j;
for(unsigned j = i + 1; j < size; j++) {
if(lessthan(list[j], list[min])) min = j;
}
if(min != i) std::swap(list[i], list[min]);
}
#endif
return;
}
//split list in half and recursively sort both
unsigned middle = length / 2;
sort(list, middle);
sort(list + middle, length - middle);
unsigned middle = size / 2;
sort(list, middle, lessthan);
sort(list + middle, size - middle, lessthan);
//left and right are sorted here; perform merge sort
T *buffer = new T[length];
unsigned offset = 0;
unsigned left = 0;
unsigned right = middle;
while(left < middle && right < length) {
if(list[left] < list[right]) {
buffer[offset++] = list[left++];
T *buffer = new T[size];
unsigned offset = 0, left = 0, right = middle;
while(left < middle && right < size) {
if(lessthan(list[left], list[right])) {
buffer[offset++] = std::move(list[left++]);
} else {
buffer[offset++] = list[right++];
buffer[offset++] = std::move(list[right++]);
}
}
while(left < middle) buffer[offset++] = list[left++];
while(right < length) buffer[offset++] = list[right++];
while(left < middle) buffer[offset++] = std::move(list[left++]);
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;
}
template<typename T>
void sort(T list[], unsigned size) {
return sort(list, size, [](const T &l, const T &r) { return l < r; });
}
}
#endif

View File

@ -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

View File

@ -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

View File

@ -1,8 +1,6 @@
#ifndef NALL_STDINT_HPP
#define NALL_STDINT_HPP
#include <nall/static.hpp>
#if defined(_MSC_VER)
typedef signed char int8_t;
typedef signed short int16_t;

View File

@ -45,7 +45,6 @@
#include <nall/string/wildcard.hpp>
#include <nall/string/wrapper.hpp>
#include <nall/string/xml.hpp>
#include <nall/string/xml-legacy.hpp>
#undef NALL_STRING_INTERNAL_HPP
#endif

View File

@ -20,7 +20,7 @@ struct Node {
cstring value;
private:
linear_vector<Node> children;
vector<Node> children;
inline bool valid(char p) const { //A-Za-z0-9-.
return p - 'A' < 26u | p - 'a' < 26u | p - '0' < 10u | p - '-' < 2u;

33
bsnes/nall/type_traits.hpp Executable file
View 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

View File

@ -5,10 +5,6 @@
#include <utility>
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 {
T value;
base_from_member(T value_) : value(value_) {}

View File

@ -1,9 +1,7 @@
#ifndef NALL_VARINT_HPP
#define NALL_VARINT_HPP
#include <type_traits>
#include <nall/bit.hpp>
#include <nall/static.hpp>
namespace nall {
template<unsigned bits> class uint_t {

View File

@ -8,6 +8,7 @@
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/sort.hpp>
#include <nall/utility.hpp>
namespace nall {
@ -70,6 +71,19 @@ namespace nall {
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
inline T& operator[](unsigned position) {
if(position >= objectsize) throw exception_out_of_bounds();
@ -81,6 +95,12 @@ namespace nall {
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 {
if(position >= objectsize) return data;
return pool[position];
@ -141,6 +161,8 @@ namespace nall {
//if objects hold memory address references to themselves (introspection), a
//valid copy constructor will be needed to keep pointers valid.
#define NALL_DEPRECATED
#if defined(NALL_DEPRECATED)
template<typename T> struct linear_vector {
protected:
T *pool;
@ -412,6 +434,7 @@ namespace nall {
const iterator begin() const { return iterator(*this, 0); }
const iterator end() const { return iterator(*this, objectsize); }
};
#endif
}
#endif

View File

@ -116,7 +116,7 @@ protected:
}
public:
linear_vector<File> file;
vector<File> file;
};
}

View File

@ -90,10 +90,10 @@ Board::Board(XML::Node &board, const uint8_t *data, unsigned size) {
information.type = board["type"].data;
information.battery = board["prg"]["battery"].data == "true";
prgrom.size = hex(board["prg"]["rom"].data);
prgram.size = hex(board["prg"]["ram"].data);
chrrom.size = hex(board["chr"]["rom"].data);
chrram.size = hex(board["chr"]["ram"].data);
prgrom.size = numeral(board["prg"]["rom"].data);
prgram.size = numeral(board["prg"]["ram"].data);
chrrom.size = numeral(board["chr"]["rom"].data);
chrram.size = numeral(board["chr"]["ram"].data);
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
if(prgram.size) prgram.data = new uint8[prgram.size]();

View File

@ -23,7 +23,7 @@ void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
//unsigned crc32 = crc32_calculate(data + 16, size - 16);
//print(hex<8>(crc32), "\n");
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;

View File

@ -14,7 +14,7 @@ static string iNES(const uint8_t *data, unsigned size) {
unsigned prgram = 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("<cartridge>\n");
@ -151,7 +151,7 @@ static string iNES(const uint8_t *data, unsigned size) {
"</cartridge>\n"
);
//print(output, "\n");
print(output, "\n");
return output;
}

View File

@ -412,7 +412,7 @@ Action::~Action() {
//Menu
//====
void Menu::append(const reference_array<Action&> &list) {
void Menu::append(const array<Action&> &list) {
for(auto &action : list) {
if(state.action.append(action)) {
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) {
if(state.action.remove(action)) {
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) {
state.text = text;
return p.setText(text);
@ -521,7 +526,7 @@ CheckItem::~CheckItem() {
//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);
if(list.size()) list[0].setChecked();
}
@ -1105,7 +1110,7 @@ ProgressBar::~ProgressBar() {
//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);
if(list.size()) list[0].setChecked();
}

View File

@ -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 remove(Args&... args) { remove({ args... }); }
void append(const nall::reference_array<Action&> &list);
void remove(const nall::reference_array<Action&> &list);
void append(const nall::array<Action&> &list);
void remove(const nall::array<Action&> &list);
void setImage(const nall::image &image);
void setText(const nall::string &text);
Menu();
@ -277,7 +278,7 @@ struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
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;
@ -357,6 +358,11 @@ struct Button : private nall::base_from_member<pButton&>, 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();
bool setImage(const nall::image &image);
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 {
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;
@ -577,6 +583,11 @@ struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, 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();
Viewport();

View File

@ -14,8 +14,8 @@ struct Window::State {
bool fullScreen;
Geometry geometry;
bool ignore;
reference_array<Layout&> layout;
reference_array<Menu&> menu;
array<Layout&> layout;
array<Menu&> menu;
string menuFont;
bool menuVisible;
bool resizable;
@ -24,7 +24,7 @@ struct Window::State {
bool statusVisible;
string title;
bool visible;
reference_array<Widget&> widget;
array<Widget&> widget;
string widgetFont;
State() {
@ -55,8 +55,12 @@ struct Action::State {
};
struct Menu::State {
reference_array<Action&> action;
array<Action&> action;
nall::image image;
string text;
State() : image(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0) {
}
};
struct Item::State {
@ -78,7 +82,7 @@ struct CheckItem::State {
struct RadioItem::State {
bool checked;
reference_array<RadioItem&> group;
array<RadioItem&> group;
string text;
State() {
@ -229,7 +233,7 @@ struct ProgressBar::State {
struct RadioBox::State {
bool checked;
reference_array<RadioBox&> group;
array<RadioBox&> group;
string text;
State() {

View File

@ -13,13 +13,18 @@ void pMenu::remove(Action &action) {
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) {
gtk_menu_item_set_label(GTK_MENU_ITEM(widget), text);
}
void pMenu::constructor() {
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);
}

View File

@ -14,7 +14,7 @@ void pRadioItem::setChecked() {
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++) {
if(n == 0) continue;
GSList *currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(group[0].p.widget));

View File

@ -1,8 +1,6 @@
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
void pKeyboard::initialize() {
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);
@ -123,18 +121,18 @@ void pKeyboard::initialize() {
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
char state[256];
XQueryKeymap(pOS::display, state);
unsigned id = keymap.lhs[scancode];
unsigned id = settings->keymap.lhs[scancode];
return state[id >> 3] & (1 << (id & 7));
}
array<bool> pKeyboard::state() {
array<bool> output;
output.reserve((unsigned)Keyboard::Scancode::Limit);
output.resize((unsigned)Keyboard::Scancode::Limit);
for(auto &n : output) n = false;
char state[256];
XQueryKeymap(pOS::display, state);
for(auto &n : keymap.rhs) {
for(auto &n : settings->keymap.rhs) {
if(state[n.name >> 3] & (1 << (n.name & 7))) {
output[(unsigned)n.data] = true;
}

View File

@ -1,5 +1,6 @@
#include "platform.hpp"
#include "utility.cpp"
#include "settings.cpp"
#include "desktop.cpp"
#include "keyboard.cpp"
@ -7,7 +8,6 @@
#include "dialog-window.cpp"
#include "message-window.cpp"
#include "settings.cpp"
#include "font.cpp"
#include "timer.cpp"
#include "window.cpp"

View File

@ -1,4 +1,6 @@
struct Settings : public configuration {
bidirectional_map<Keyboard::Scancode, unsigned> keymap;
unsigned frameGeometryX;
unsigned frameGeometryY;
unsigned frameGeometryWidth;
@ -32,8 +34,6 @@ struct pDesktop {
};
struct pKeyboard {
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
static bool pressed(Keyboard::Scancode scancode);
static array<bool> state();
@ -150,6 +150,7 @@ struct pMenu : public pAction {
void append(Action &action);
void remove(Action &action);
void setImage(const image &image);
void setText(const string &text);
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
@ -198,7 +199,7 @@ struct pRadioItem : public pAction {
bool checked();
void setChecked();
void setGroup(const reference_array<RadioItem&> &group);
void setGroup(const array<RadioItem&> &group);
void setText(const string &text);
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
@ -424,7 +425,7 @@ struct pRadioBox : public pWidget {
bool checked();
Geometry minimumGeometry();
void setChecked();
void setGroup(const reference_array<RadioBox&> &group);
void setGroup(const array<RadioBox&> &group);
void setText(const string &text);
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}

View File

@ -6,6 +6,34 @@ static gboolean Canvas_expose(GtkWidget *widget, GdkEvent *event, pCanvas *self)
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) {
cairo_surface_destroy(surface);
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));
gtkWidget = gtk_drawing_area_new();
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), "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() {

View File

@ -19,7 +19,7 @@ void pRadioBox::setChecked() {
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++) {
if(n == 0) continue;
GSList *currentGroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(group[0].p.gtkWidget));

View File

@ -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() {
return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget));
}
@ -5,6 +33,12 @@ uintptr_t pViewport::handle() {
void pViewport::constructor() {
gtkWidget = gtk_drawing_area_new();
//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;
color.pixel = 0;

View File

@ -7,7 +7,6 @@
#include <nall/function.hpp>
#include <nall/image.hpp>
#include <nall/map.hpp>
#include <nall/reference_array.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/utility.hpp>

View File

@ -33,6 +33,15 @@ void pMenu::setFont(const string &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) {
qtMenu->setTitle(QString::fromUtf8(text));
}

View File

@ -12,7 +12,7 @@ void pRadioItem::setChecked() {
locked = false;
}
void pRadioItem::setGroup(const reference_array<RadioItem&> &group) {
void pRadioItem::setGroup(const array<RadioItem&> &group) {
}
void pRadioItem::setText(const string &text) {

View File

@ -1,8 +1,6 @@
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
void pKeyboard::initialize() {
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);
@ -123,7 +121,7 @@ void pKeyboard::initialize() {
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
char state[256];
XQueryKeymap(pOS::display, state);
unsigned id = keymap.lhs[scancode];
unsigned id = settings->keymap.lhs[scancode];
return state[id >> 3] & (1 << (id & 7));
}
@ -134,7 +132,7 @@ array<bool> pKeyboard::state() {
char state[256];
XQueryKeymap(pOS::display, state);
for(auto &n : keymap.rhs) {
for(auto &n : settings->keymap.rhs) {
if(state[n.name >> 3] & (1 << (n.name & 7))) {
output[(unsigned)n.data] = true;
}

View File

@ -1,6 +1,7 @@
#include "platform.moc.hpp"
#include "platform.moc"
#include "utility.cpp"
#include "settings.cpp"
#include "desktop.cpp"
#include "keyboard.cpp"
@ -8,7 +9,6 @@
#include "dialog-window.cpp"
#include "message-window.cpp"
#include "settings.cpp"
#include "font.cpp"
#include "timer.cpp"
#include "window.cpp"

View File

@ -1,7 +1,7 @@
/****************************************************************************
** 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)
**
** WARNING! All changes made in this file will be lost!

View File

@ -1,6 +1,8 @@
static QApplication *qtApplication = 0;
struct Settings : public configuration {
bidirectional_map<Keyboard::Scancode, unsigned> keymap;
unsigned frameGeometryX;
unsigned frameGeometryY;
unsigned frameGeometryWidth;
@ -31,8 +33,6 @@ struct pDesktop {
};
struct pKeyboard {
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
static bool pressed(Keyboard::Scancode scancode);
static array<bool> state();
@ -166,6 +166,7 @@ struct pMenu : public pAction {
void append(Action &action);
void remove(Action &action);
void setFont(const string &font);
void setImage(const image &image);
void setText(const string &text);
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
@ -229,7 +230,7 @@ public:
bool checked();
void setChecked();
void setGroup(const reference_array<RadioItem&> &group);
void setGroup(const array<RadioItem&> &group);
void setText(const string &text);
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
@ -304,6 +305,10 @@ public:
QImage *qtImage;
struct QtCanvas : public QWidget {
pCanvas &self;
void leaveEvent(QEvent*);
void mouseMoveEvent(QMouseEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void paintEvent(QPaintEvent*);
QtCanvas(pCanvas &self);
} *qtCanvas;
@ -525,7 +530,7 @@ public:
bool checked();
Geometry minimumGeometry();
void setChecked();
void setGroup(const reference_array<RadioBox&> &group);
void setGroup(const array<RadioBox&> &group);
void setText(const string &text);
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}
@ -603,6 +608,14 @@ public slots:
struct pViewport : public pWidget {
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();

View File

@ -22,6 +22,7 @@ void pButton::setImage(const image &image, Orientation orientation) {
QIcon qtIcon(QPixmap::fromImage(qtImage));
qtButton->setIconSize(QSize(qtBuffer.width, qtBuffer.height));
qtButton->setIcon(qtIcon);
qtButton->setStyleSheet("text-align: top;");
switch(orientation) {
case Orientation::Horizontal: qtButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
case Orientation::Vertical: qtButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;

View File

@ -11,6 +11,7 @@ void pCanvas::update() {
void pCanvas::constructor() {
qtWidget = qtCanvas = new QtCanvas(*this);
qtCanvas->setMouseTracking(true);
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));
@ -30,6 +31,32 @@ void pCanvas::orphan() {
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) {
QPainter painter(self.qtCanvas);
painter.drawImage(0, 0, *self.qtImage);

View File

@ -17,7 +17,7 @@ void pRadioBox::setChecked() {
locked = false;
}
void pRadioBox::setGroup(const reference_array<RadioBox&> &group) {
void pRadioBox::setGroup(const array<RadioBox&> &group) {
locked = true;
if(qtGroup) {
delete qtGroup;

View File

@ -1,21 +1,51 @@
uintptr_t pViewport::handle() {
return (uintptr_t)qtWidget->winId();
return (uintptr_t)qtViewport->winId();
}
void pViewport::constructor() {
qtWidget = new QWidget;
qtWidget->setAttribute(Qt::WA_PaintOnScreen, true);
qtWidget->setStyleSheet("background: #000000");
qtWidget = qtViewport = new QtViewport(*this);
qtViewport->setMouseTracking(true);
qtViewport->setAttribute(Qt::WA_PaintOnScreen, true);
qtViewport->setStyleSheet("background: #000000");
pWidget::synchronizeState();
}
void pViewport::destructor() {
delete qtWidget;
qtWidget = 0;
delete qtViewport;
qtWidget = qtViewport = nullptr;
}
void pViewport::orphan() {
destructor();
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) {
}

View File

@ -4,6 +4,9 @@ void pMenu::append(Action &action) {
void pMenu::remove(Action &action) {
}
void pMenu::setImage(const image &image) {
}
void pMenu::setText(const string &text) {
}

View File

@ -5,7 +5,7 @@ bool pRadioItem::checked() {
void pRadioItem::setChecked() {
}
void pRadioItem::setGroup(const reference_array<RadioItem&> &group) {
void pRadioItem::setGroup(const array<RadioItem&> &group) {
}
void pRadioItem::setText(const string &text) {

View File

@ -112,6 +112,7 @@ struct pMenu : public pAction {
void append(Action &action);
void remove(Action &action);
void setImage(const image &image);
void setText(const string &text);
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
@ -155,7 +156,7 @@ struct pRadioItem : public pAction {
bool checked();
void setChecked();
void setGroup(const reference_array<RadioItem&> &group);
void setGroup(const array<RadioItem&> &group);
void setText(const string &text);
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
@ -323,7 +324,7 @@ struct pRadioBox : public pWidget {
bool checked();
void setChecked();
void setGroup(const reference_array<RadioBox&> &group);
void setGroup(const array<RadioBox&> &group);
void setText(const string &text);
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}

View File

@ -5,7 +5,7 @@ bool pRadioBox::checked() {
void pRadioBox::setChecked() {
}
void pRadioBox::setGroup(const reference_array<RadioBox&> &group) {
void pRadioBox::setGroup(const array<RadioBox&> &group) {
}
void pRadioBox::setText(const string &text) {

View File

@ -26,4 +26,4 @@ void pItem::createBitmap() {
nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
hbitmap = CreateBitmap(nallImage);
}
}
}

View File

@ -8,12 +8,40 @@ void pMenu::remove(Action &action) {
action.p.parentMenu = 0;
}
void pMenu::setImage(const image &image) {
createBitmap();
if(parentWindow) parentWindow->p.updateMenu();
}
void pMenu::setText(const string &text) {
if(parentWindow) parentWindow->p.updateMenu();
}
void pMenu::constructor() {
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.
@ -32,11 +60,24 @@ void pMenu::update(Window &parentWindow, Menu *parentMenu) {
unsigned enabled = action.state.enabled ? 0 : MF_GRAYED;
if(dynamic_cast<Menu*>(&action)) {
Menu &item = (Menu&)action;
item.p.update(parentWindow, &menu);
AppendMenu(hmenu, MF_STRING | MF_POPUP | enabled, (UINT_PTR)item.p.hmenu, utf16_t(item.state.text));
if(action.state.visible) {
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)) {
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)) {
Item &item = (Item&)action;
if(action.state.visible) {
@ -53,21 +94,16 @@ void pMenu::update(Window &parentWindow, Menu *parentMenu) {
}
} else if(dynamic_cast<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();
} else if(dynamic_cast<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();
}
}
}
void pMenu::destructor() {
if(parentMenu) {
parentMenu->remove(menu);
} else if(parentWindow) {
//belongs to window's main menubar
parentWindow->remove(menu);
}
}

View File

@ -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) {

View File

@ -1,8 +1,6 @@
bidirectional_map<Keyboard::Scancode, unsigned> pKeyboard::keymap;
void pKeyboard::initialize() {
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
keymap.append(scancode, keysym);
settings->keymap.insert(scancode, keysym);
};
append(Keyboard::Scancode::Escape, VK_ESCAPE);
@ -121,7 +119,7 @@ void pKeyboard::initialize() {
}
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
return GetAsyncKeyState(keymap.lhs[scancode]) & 0x8000;
return GetAsyncKeyState(settings->keymap.lhs[scancode]) & 0x8000;
}
array<bool> pKeyboard::state() {
@ -129,7 +127,7 @@ array<bool> pKeyboard::state() {
output.resize((unsigned)Keyboard::Scancode::Limit);
for(auto &n : output) n = false;
for(auto &n : keymap.rhs) {
for(auto &n : settings->keymap.rhs) {
if(GetAsyncKeyState(n.name) & 0x8000) {
output[(unsigned)n.data] = true;
}

View File

@ -1,5 +1,6 @@
#include "platform.hpp"
#include "utility.cpp"
#include "settings.cpp"
#include "desktop.cpp"
#include "keyboard.cpp"
@ -135,6 +136,7 @@ void pOS::initialize() {
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
settings = new Settings;
pKeyboard::initialize();
}

View File

@ -1,3 +1,7 @@
struct Settings {
bidirectional_map<Keyboard::Scancode, unsigned> keymap;
};
struct pFont;
struct pWindow;
struct pMenu;
@ -20,8 +24,6 @@ struct pDesktop {
};
struct pKeyboard {
static bidirectional_map<Keyboard::Scancode, unsigned> keymap;
static bool pressed(Keyboard::Scancode scancode);
static array<bool> state();
@ -134,14 +136,17 @@ struct pAction : public pObject {
struct pMenu : public pAction {
Menu &menu;
HMENU hmenu;
HBITMAP hbitmap;
void append(Action &action);
void remove(Action &action);
void setImage(const image &image);
void setText(const string &text);
pMenu(Menu &menu) : pAction(menu), menu(menu) {}
pMenu(Menu &menu) : pAction(menu), menu(menu), hbitmap(0) {}
void constructor();
void destructor();
void createBitmap();
void update(Window &parentWindow, Menu *parentMenu = 0);
};
@ -183,7 +188,7 @@ struct pRadioItem : public pAction {
bool checked();
void setChecked();
void setGroup(const reference_array<RadioItem&> &group);
void setGroup(const array<RadioItem&> &group);
void setText(const string &text);
pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {}
@ -398,7 +403,7 @@ struct pRadioBox : public pWidget {
bool checked();
Geometry minimumGeometry();
void setChecked();
void setGroup(const reference_array<RadioBox&> &group);
void setGroup(const array<RadioBox&> &group);
void setText(const string &text);
pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {}

View File

@ -0,0 +1 @@
static Settings *settings = nullptr;

View File

@ -1,17 +1,44 @@
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) {
return DLGC_STATIC | DLGC_WANTCHARS;
}
if(msg == WM_PAINT) {
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(object && dynamic_cast<Canvas*>(object)) {
Canvas &canvas = (Canvas&)*object;
canvas.p.paint();
}
canvas.p.paint();
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);
}

View File

@ -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) {

View File

@ -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() {
return (uintptr_t)hwnd;
}
@ -15,9 +54,4 @@ void pViewport::destructor() {
void pViewport::orphan() {
destructor();
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);
}
}

View File

@ -91,7 +91,6 @@ struct Cartridge : property<Cartridge> {
private:
void parse_markup(const char*);
unsigned parse_markup_integer(string&);
void parse_markup_map(Mapping&, XML::Node&);
void parse_markup_rom(XML::Node&);

View File

@ -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) {
m.offset = parse_markup_integer(map["offset"].data);
m.size = parse_markup_integer(map["size"].data);
m.offset = numeral(map["offset"].data);
m.size = numeral(map["size"].data);
string data = map["mode"].data;
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) {
if(root.exists() == false) return;
ram_size = parse_markup_integer(root["size"].data);
ram_size = numeral(root["size"].data);
for(auto &node : root) {
Mapping m(ram);
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
information.nss.option[number].reset();
information.nss.setting[number] = node["name"].data;
information.nss.setting.append(node["name"].data);
for(auto &leaf : node) {
if(leaf.name != "option") continue;
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 });
}
}
@ -114,7 +109,7 @@ void Cartridge::parse_markup_icd2(XML::Node &root) {
if(root.exists() == false) 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) {
if(node.name != "map") continue;
@ -140,7 +135,7 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
if(node.name == "ram") {
for(auto &leaf : node) {
if(leaf.name == "size") {
ram_size = parse_markup_integer(leaf.data);
ram_size = numeral(leaf.data);
continue;
}
if(leaf.name != "map") continue;
@ -193,7 +188,7 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
mapping.append(m);
}
ram_size = parse_markup_integer(bwram["size"].data);
ram_size = numeral(bwram["size"].data);
for(auto &node : bwram) {
if(node.name != "map") continue;
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 < 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;
necdsp.revision
= 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;
hitachidsp.frequency = parse_markup_integer(root["frequency"].data);
hitachidsp.frequency = numeral(root["frequency"].data);
if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
@ -379,7 +374,7 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
}
}
if(node.name == "ram") {
unsigned ram_size = parse_markup_integer(node["size"].data);
unsigned ram_size = numeral(node["size"].data);
for(auto &leaf : node) {
if(leaf.name != "map") continue;
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 &rtc = root["rtc"];
ram_size = parse_markup_integer(ram["size"].data);
ram_size = numeral(ram["size"].data);
for(auto &node : ram) {
if(node.name != "map") continue;
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);
}
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;
for(auto &node : mcu) {
if(node.name != "map") continue;
@ -524,7 +519,7 @@ void Cartridge::parse_markup_link(XML::Node &root) {
if(root.exists() == false) return;
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;
for(auto &node : root) {

View File

@ -9,6 +9,7 @@ unsigned Video::palette30(unsigned color) {
unsigned r = (color >> 0) & 31;
double L = (1.0 + l) / 16.0;
if(l == 0) L *= 0.5;
unsigned R = L * ((r << 5) + (r << 0));
unsigned G = L * ((g << 5) + (g << 0));
unsigned B = L * ((b << 5) + (b << 0));

View File

@ -1,4 +1,4 @@
DipSwitches *dipSwitches = 0;
DipSwitches *dipSwitches = nullptr;
DipSwitch::DipSwitch() {
append(name, { ~0, 0 }, 5);

View File

@ -1,4 +1,4 @@
FileBrowser *fileBrowser = 0;
FileBrowser *fileBrowser = nullptr;
FileBrowser::FileBrowser() {
setGeometry({ 128, 128, 640, 400 });
@ -130,21 +130,23 @@ bool FileBrowser::loadFolder(const string &requestedPath) {
if(path.wildcard(filter)) accept = true;
}
if(accept == false) return false;
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] });
loadFile(requestedPath);
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) {

View File

@ -1,4 +1,4 @@
MainWindow *mainWindow = 0;
MainWindow *mainWindow = nullptr;
MainWindow::MainWindow() {
setTitle(application->title);
@ -338,7 +338,7 @@ void MainWindow::setupVideoFilters() {
path = { application->userpath, "filters/" };
files = directory::files(path, "*.filter");
}
reference_array<RadioItem&> group;
array<RadioItem&> group;
settingsVideoFilterList = new RadioItem[files.size()];
for(unsigned n = 0; n < files.size(); n++) {
@ -369,7 +369,7 @@ void MainWindow::setupVideoShaders() {
path = { application->userpath, "shaders/" };
files = directory::files(path, { "*.", config->video.driver, ".shader" });
}
reference_array<RadioItem&> group;
array<RadioItem&> group;
settingsVideoShaderList = new RadioItem[files.size()];
for(unsigned n = 0; n < files.size(); n++) {

View File

@ -1,4 +1,4 @@
SlotLoader *slotLoader = 0;
SlotLoader *slotLoader = nullptr;
SlotLoaderPath::SlotLoaderPath() {
browse.setText("Browse ...");

View File

@ -27,7 +27,7 @@ struct TurboInput : DigitalInput {
TurboInput();
};
struct TertiaryInput : reference_array<AbstractInput&> {
struct TertiaryInput : array<AbstractInput&> {
string name;
virtual void attach(const string &primaryName, const string &secondaryName);
@ -35,14 +35,14 @@ struct TertiaryInput : reference_array<AbstractInput&> {
virtual int16_t poll(unsigned n);
};
struct SecondaryInput : reference_array<TertiaryInput&> {
struct SecondaryInput : array<TertiaryInput&> {
string name;
virtual void attach(const string &primaryName);
virtual void bind();
};
struct PrimaryInput : reference_array<SecondaryInput&> {
struct PrimaryInput : array<SecondaryInput&> {
string name;
virtual void attach();
@ -59,7 +59,7 @@ struct InputManager {
int16_t scancode[2][Scancode::Limit];
bool activeScancode;
reference_array<PrimaryInput&> inputList;
array<PrimaryInput&> inputList;
NesInput nes;
SnesInput snes;
GameBoyInput gameBoy;

View File

@ -10,10 +10,20 @@ bool InterfaceGameBoy::cartridgeLoaded() {
bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const string &filename) {
uint8_t *data;
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->baseName = nall::basename(filename);
interface->applyPatch(interface->baseName, data, size);
string markup;
markup.readfile({ interface->baseName, ".xml" });

View File

@ -188,11 +188,9 @@ Interface::Interface() : core(nullptr) {
//internal
bool Interface::loadFile(const string &filename, uint8_t *&data, unsigned &size) {
if(file::read(filename, data, size) == false) return false;
bool Interface::applyPatch(const string &filename, uint8_t *&data, unsigned &size) {
string patchname = { nall::basename(filename), ".bps" };
if(file::exists(patchname) == false) return true;
if(file::exists(patchname) == false) return false;
bpspatch bps;
bps.modify(patchname);
@ -202,7 +200,7 @@ bool Interface::loadFile(const string &filename, uint8_t *&data, unsigned &size)
bps.target(targetData, targetSize);
if(bps.apply() != bpspatch::result::success) {
delete[] targetData;
return true;
return false;
}
delete[] data;

View File

@ -55,7 +55,7 @@ struct Interface : property<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);
string baseName; // = "/path/to/cartridge" (no extension)

View File

@ -25,10 +25,37 @@ bool InterfaceNES::cartridgeLoaded() {
bool InterfaceNES::loadCartridge(const string &filename) {
uint8_t *data;
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->baseName = nall::basename(filename);
interface->applyPatch(interface->baseName, data, size);
string markup;
markup.readfile({ interface->baseName, ".xml" });

View File

@ -30,14 +30,25 @@ bool InterfaceSNES::cartridgeLoaded() {
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;
unsigned size;
if(interface->loadFile(basename, data, size) == false) return false;
if(loadFile(basename, data, size) == false) return false;
interface->unloadCartridge();
interface->baseName = nall::basename(basename);
interface->slotName = { nall::basename(basename) };
interface->baseName = basename;
interface->slotName = { basename };
string markup;
markup.readfile({ interface->baseName, ".xml" });
@ -55,16 +66,16 @@ bool InterfaceSNES::loadCartridge(const string &basename) {
return true;
}
bool InterfaceSNES::loadSatellaviewSlottedCartridge(const string &basename, const string &slotname) {
bool InterfaceSNES::loadSatellaviewSlottedCartridge(string basename, string slotname) {
uint8_t *data[2];
unsigned size[2];
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
interface->loadFile(slotname, data[1], size[1]);
if(loadFile(basename, data[0], size[0]) == false) return false;
loadFile(slotname, data[1], size[1]);
interface->unloadCartridge();
interface->baseName = nall::basename(basename);
if(data[1]) interface->baseName.append("+", nall::basename(notdir(slotname)));
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
interface->baseName = basename;
if(data[1]) interface->baseName.append("+", notdir(slotname));
interface->slotName = { basename, slotname };
string markup;
markup.readfile({ interface->baseName, ".xml" });
@ -84,16 +95,16 @@ bool InterfaceSNES::loadSatellaviewSlottedCartridge(const string &basename, cons
return true;
}
bool InterfaceSNES::loadSatellaviewCartridge(const string &basename, const string &slotname) {
bool InterfaceSNES::loadSatellaviewCartridge(string basename, string slotname) {
uint8_t *data[2];
unsigned size[2];
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
interface->loadFile(slotname, data[1], size[1]);
if(loadFile(basename, data[0], size[0]) == false) return false;
loadFile(slotname, data[1], size[1]);
interface->unloadCartridge();
interface->baseName = nall::basename(basename);
if(data[1]) interface->baseName.append("+", nall::basename(notdir(slotname)));
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
interface->baseName = basename;
if(data[1]) interface->baseName.append("+", notdir(slotname));
interface->slotName = { basename, slotname };
string markup;
markup.readfile({ interface->baseName, ".xml" });
@ -113,19 +124,19 @@ bool InterfaceSNES::loadSatellaviewCartridge(const string &basename, const strin
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];
unsigned size[3];
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
interface->loadFile(slotAname, data[1], size[1]);
interface->loadFile(slotBname, data[2], size[2]);
if(loadFile(basename, data[0], size[0]) == false) return false;
loadFile(slotAname, data[1], size[1]);
loadFile(slotBname, data[2], size[2]);
interface->unloadCartridge();
interface->baseName = nall::basename(basename);
if(data[1] && data[2]) interface->baseName = { nall::basename(slotAname), "+", nall::basename(notdir(slotBname)) };
else if(data[1]) interface->baseName = nall::basename(slotAname);
else if(data[2]) interface->baseName = nall::basename(slotBname);
interface->slotName = { nall::basename(basename), nall::basename(slotAname), nall::basename(slotBname) };
interface->baseName = basename;
if(data[1] && data[2]) interface->baseName = { slotAname, "+", notdir(slotBname) };
else if(data[1]) interface->baseName = slotAname;
else if(data[2]) interface->baseName = slotBname;
interface->slotName = { basename, slotAname, slotBname };
string markup;
markup.readfile({ interface->baseName, ".xml" });
@ -147,16 +158,16 @@ bool InterfaceSNES::loadSufamiTurboCartridge(const string &basename, const strin
return true;
}
bool InterfaceSNES::loadSuperGameBoyCartridge(const string &basename, const string &slotname) {
bool InterfaceSNES::loadSuperGameBoyCartridge(string basename, string slotname) {
uint8_t *data[2];
unsigned size[2];
if(interface->loadFile(basename, data[0], size[0]) == false) return false;
interface->loadFile(slotname, data[1], size[1]);
if(loadFile(basename, data[0], size[0]) == false) return false;
loadFile(slotname, data[1], size[1]);
interface->unloadCartridge();
interface->baseName = nall::basename(basename);
if(data[1]) interface->baseName = nall::basename(slotname);
interface->slotName = { nall::basename(basename), nall::basename(slotname) };
interface->baseName = basename;
if(data[1]) interface->baseName = slotname;
interface->slotName = { basename, slotname };
string markup;
markup.readfile({ interface->baseName, ".xml" });

View File

@ -4,11 +4,12 @@ struct InterfaceSNES : InterfaceCore, SNES::Interface {
void setController(bool port, unsigned device);
bool cartridgeLoaded();
bool loadCartridge(const string &filename);
bool loadSatellaviewSlottedCartridge(const string &basename, const string &slotname);
bool loadSatellaviewCartridge(const string &basename, const string &slotname);
bool loadSufamiTurboCartridge(const string &basename, const string &slotAname, const string &slotBname);
bool loadSuperGameBoyCartridge(const string &basename, const string &slotname);
bool loadFile(string &filename, uint8_t *&data, unsigned &size);
bool loadCartridge(string basename);
bool loadSatellaviewSlottedCartridge(string basename, string slotname);
bool loadSatellaviewCartridge(string basename, string slotname);
bool loadSufamiTurboCartridge(string basename, string slotAname, string slotBname);
bool loadSuperGameBoyCartridge(string basename, string slotname);
void unloadCartridge();
void power();

View File

@ -27,7 +27,7 @@ void Application::run() {
}
Application::Application(int argc, char **argv) {
title = "bsnes v085.01";
title = "bsnes v085.02";
application = this;
quit = false;