diff --git a/bsnes/gameboy/cartridge/cartridge.cpp b/bsnes/gameboy/cartridge/cartridge.cpp index 7370dc60..085f5c5a 100755 --- a/bsnes/gameboy/cartridge/cartridge.cpp +++ b/bsnes/gameboy/cartridge/cartridge.cpp @@ -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: diff --git a/bsnes/nall/any.hpp b/bsnes/nall/any.hpp index b31cff3c..fc577957 100755 --- a/bsnes/nall/any.hpp +++ b/bsnes/nall/any.hpp @@ -2,17 +2,15 @@ #define NALL_ANY_HPP #include -#include -#include +#include 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 any& operator=(const T& value_) { - typedef typename static_if< + typedef typename type_if< std::is_array::value, typename std::remove_extent::type>::type*, T diff --git a/bsnes/nall/array.hpp b/bsnes/nall/array.hpp index d722e597..cf376e54 100755 --- a/bsnes/nall/array.hpp +++ b/bsnes/nall/array.hpp @@ -4,143 +4,286 @@ #include #include #include -#include #include #include #include +#include +#include #include namespace nall { - //dynamic vector array - //neither constructor nor destructor is ever invoked; - //thus, this should only be used for POD objects. - template class array { - protected: - T *pool; - unsigned poolsize, buffersize; - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } +template struct array; - void reset() { - if(pool) free(pool); - pool = nullptr; - poolsize = 0; - buffersize = 0; +//non-reference array +//=================== + +template struct array::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 void sort(const Comparator &lessthan) { + nall::sort(pool, objectsize, lessthan); + } + + optional 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 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 struct array::value>::type> { + struct exception_out_of_bounds{}; + +protected: + typedef typename std::remove_reference::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 + bool append(T& data, Args&&... args) { + bool result = append(data); + append(std::forward(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 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 array(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) { + construct(std::forward(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 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 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 void construct(T& data, Args&&... args) { + append(data); + construct(std::forward(args)...); + } +}; + } #endif diff --git a/bsnes/nall/atoi.hpp b/bsnes/nall/atoi.hpp index cec3e72d..ac58b8ab 100755 --- a/bsnes/nall/atoi.hpp +++ b/bsnes/nall/atoi.hpp @@ -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); } diff --git a/bsnes/nall/config.hpp b/bsnes/nall/config.hpp index 0ce259d6..94be7dc1 100755 --- a/bsnes/nall/config.hpp +++ b/bsnes/nall/config.hpp @@ -53,21 +53,18 @@ namespace nall { } } }; - linear_vector list; + vector list; template 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::value) list[n].type = boolean_t; - else if(configuration_traits::is_signed::value) list[n].type = signed_t; - else if(configuration_traits::is_unsigned::value) list[n].type = unsigned_t; - else if(configuration_traits::is_double::value) list[n].type = double_t; - else if(configuration_traits::is_string::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::value) item.type = boolean_t; + else if(configuration_traits::is_signed::value) item.type = signed_t; + else if(configuration_traits::is_unsigned::value) item.type = unsigned_t; + else if(configuration_traits::is_double::value) item.type = double_t; + else if(configuration_traits::is_string::value) item.type = string_t; + else item.type = unknown_t; + list.append(item); } //deprecated diff --git a/bsnes/nall/directory.hpp b/bsnes/nall/directory.hpp index 31ca1e05..ff439803 100755 --- a/bsnes/nall/directory.hpp +++ b/bsnes/nall/directory.hpp @@ -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; } diff --git a/bsnes/nall/image.hpp b/bsnes/nall/image.hpp index 683b59e4..92870d3f 100755 --- a/bsnes/nall/image.hpp +++ b/bsnes/nall/image.hpp @@ -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(); } diff --git a/bsnes/nall/map.hpp b/bsnes/nall/map.hpp index 4e6bc204..84709781 100755 --- a/bsnes/nall/map.hpp +++ b/bsnes/nall/map.hpp @@ -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 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 list; @@ -64,22 +87,28 @@ protected: template struct bidirectional_map { - map lhs; - map rhs; + const map &lhs; + const map &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 llist; + map rlist; }; } diff --git a/bsnes/nall/resource.hpp b/bsnes/nall/resource.hpp deleted file mode 100755 index f8fd5153..00000000 --- a/bsnes/nall/resource.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef NALL_RESOURCE_HPP -#define NALL_RESOURCE_HPP - -#include -#include - -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 diff --git a/bsnes/nall/sort.hpp b/bsnes/nall/sort.hpp index 3bd6dc59..36d91865 100755 --- a/bsnes/nall/sort.hpp +++ b/bsnes/nall/sort.hpp @@ -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 - void sort(T list[], unsigned length) { - if(length <= 1) return; //nothing to sort + template + 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 + void sort(T list[], unsigned size) { + return sort(list, size, [](const T &l, const T &r) { return l < r; }); + } } #endif diff --git a/bsnes/nall/stack.hpp b/bsnes/nall/stack.hpp deleted file mode 100755 index fe8e16a1..00000000 --- a/bsnes/nall/stack.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NALL_STACK_HPP -#define NALL_STACK_HPP - -#include - -namespace nall { - template struct stack : public linear_vector { - void push(const T &value) { - linear_vector::append(value); - } - - T pull() { - if(linear_vector::size() == 0) throw; - T value = linear_vector::operator[](linear_vector::size() - 1); - linear_vector::remove(linear_vector::size() - 1); - return value; - } - - T& operator()() { - if(linear_vector::size() == 0) throw; - return linear_vector::operator[](linear_vector::size() - 1); - } - }; -} - -#endif diff --git a/bsnes/nall/static.hpp b/bsnes/nall/static.hpp deleted file mode 100755 index 4acb9fd0..00000000 --- a/bsnes/nall/static.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NALL_STATIC_HPP -#define NALL_STATIC_HPP - -namespace nall { - template struct static_if { typedef T type; }; - template struct static_if { typedef F type; }; - template struct mp_static_if { typedef typename static_if::type type; }; - - template struct static_and { enum { value = false }; }; - template<> struct static_and { enum { value = true }; }; - template struct mp_static_and { enum { value = static_and::value }; }; - - template struct static_or { enum { value = false }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template struct mp_static_or { enum { value = static_or::value }; }; -} - -#endif diff --git a/bsnes/nall/stdint.hpp b/bsnes/nall/stdint.hpp index d8b6c788..c63f5912 100755 --- a/bsnes/nall/stdint.hpp +++ b/bsnes/nall/stdint.hpp @@ -1,8 +1,6 @@ #ifndef NALL_STDINT_HPP #define NALL_STDINT_HPP -#include - #if defined(_MSC_VER) typedef signed char int8_t; typedef signed short int16_t; diff --git a/bsnes/nall/string.hpp b/bsnes/nall/string.hpp index fbc25384..996cd68a 100755 --- a/bsnes/nall/string.hpp +++ b/bsnes/nall/string.hpp @@ -45,7 +45,6 @@ #include #include #include -#include #undef NALL_STRING_INTERNAL_HPP #endif diff --git a/bsnes/nall/string/bml.hpp b/bsnes/nall/string/bml.hpp index 4f8139cc..d2fa60e3 100755 --- a/bsnes/nall/string/bml.hpp +++ b/bsnes/nall/string/bml.hpp @@ -20,7 +20,7 @@ struct Node { cstring value; private: - linear_vector children; + vector children; inline bool valid(char p) const { //A-Za-z0-9-. return p - 'A' < 26u | p - 'a' < 26u | p - '0' < 10u | p - '-' < 2u; diff --git a/bsnes/nall/type_traits.hpp b/bsnes/nall/type_traits.hpp new file mode 100755 index 00000000..1be3bf79 --- /dev/null +++ b/bsnes/nall/type_traits.hpp @@ -0,0 +1,33 @@ +#ifndef NALL_STATIC_HPP +#define NALL_STATIC_HPP + +#include + +namespace nall { + +template class has_default_constructor { + template class receive_size{}; + template static signed sfinae(receive_size*); + template static char sfinae(...); + +public: + enum : bool { value = sizeof(sfinae(0)) == sizeof(signed) }; +}; + +template struct enable_if { typedef T type; }; +template struct enable_if {}; + +template struct type_if { typedef T type; }; +template struct type_if { typedef F type; }; + +template struct static_and { enum { value = false }; }; +template<> struct static_and { enum { value = true }; }; + +template struct static_or { enum { value = false }; }; +template<> struct static_or { enum { value = true }; }; +template<> struct static_or { enum { value = true }; }; +template<> struct static_or { enum { value = true }; }; + +} + +#endif diff --git a/bsnes/nall/utility.hpp b/bsnes/nall/utility.hpp index 8da56ff3..b3c1e5aa 100755 --- a/bsnes/nall/utility.hpp +++ b/bsnes/nall/utility.hpp @@ -5,10 +5,6 @@ #include namespace nall { - template struct enable_if { typedef T type; }; - template struct enable_if {}; - template struct mp_enable_if : enable_if {}; - template struct base_from_member { T value; base_from_member(T value_) : value(value_) {} diff --git a/bsnes/nall/varint.hpp b/bsnes/nall/varint.hpp index d91ea2a5..24e4de7c 100755 --- a/bsnes/nall/varint.hpp +++ b/bsnes/nall/varint.hpp @@ -1,9 +1,7 @@ #ifndef NALL_VARINT_HPP #define NALL_VARINT_HPP -#include #include -#include namespace nall { template class uint_t { diff --git a/bsnes/nall/vector.hpp b/bsnes/nall/vector.hpp index e03214d0..9d4a76b4 100755 --- a/bsnes/nall/vector.hpp +++ b/bsnes/nall/vector.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace nall { @@ -70,6 +71,19 @@ namespace nall { objectsize = (count + index >= objectsize) ? index : objectsize - count; } + void sort() { + nall::sort(pool, objectsize); + } + + template void sort(const Comparator &lessthan) { + nall::sort(pool, objectsize, lessthan); + } + + optional 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 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 diff --git a/bsnes/nall/zip.hpp b/bsnes/nall/zip.hpp index ad9c7506..a224afe4 100755 --- a/bsnes/nall/zip.hpp +++ b/bsnes/nall/zip.hpp @@ -116,7 +116,7 @@ protected: } public: - linear_vector file; + vector file; }; } diff --git a/bsnes/nes/cartridge/board/board.cpp b/bsnes/nes/cartridge/board/board.cpp index c7198db7..15d7df48 100755 --- a/bsnes/nes/cartridge/board/board.cpp +++ b/bsnes/nes/cartridge/board/board.cpp @@ -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](); diff --git a/bsnes/nes/cartridge/cartridge.cpp b/bsnes/nes/cartridge/cartridge.cpp index a88c4950..c1634d57 100755 --- a/bsnes/nes/cartridge/cartridge.cpp +++ b/bsnes/nes/cartridge/cartridge.cpp @@ -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; diff --git a/bsnes/nes/cartridge/ines.cpp b/bsnes/nes/cartridge/ines.cpp index 902ef440..e90b6cb7 100755 --- a/bsnes/nes/cartridge/ines.cpp +++ b/bsnes/nes/cartridge/ines.cpp @@ -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("\n"); output.append("\n"); @@ -151,7 +151,7 @@ static string iNES(const uint8_t *data, unsigned size) { "\n" ); -//print(output, "\n"); + print(output, "\n"); return output; } diff --git a/bsnes/phoenix/core/core.cpp b/bsnes/phoenix/core/core.cpp index 7e4c559e..e2ee6e04 100755 --- a/bsnes/phoenix/core/core.cpp +++ b/bsnes/phoenix/core/core.cpp @@ -412,7 +412,7 @@ Action::~Action() { //Menu //==== -void Menu::append(const reference_array &list) { +void Menu::append(const array &list) { for(auto &action : list) { if(state.action.append(action)) { action.state.menu = this; @@ -421,7 +421,7 @@ void Menu::append(const reference_array &list) { } } -void Menu::remove(const reference_array &list) { +void Menu::remove(const array &list) { for(auto &action : list) { if(state.action.remove(action)) { action.state.menu = 0; @@ -430,6 +430,11 @@ void Menu::remove(const reference_array &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 &list) { +void RadioItem::group(const array &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 &list) { +void RadioBox::group(const array &list) { for(auto &item : list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } diff --git a/bsnes/phoenix/core/core.hpp b/bsnes/phoenix/core/core.hpp index bb18b1f2..8fcbf378 100755 --- a/bsnes/phoenix/core/core.hpp +++ b/bsnes/phoenix/core/core.hpp @@ -231,8 +231,9 @@ struct Menu : private nall::base_from_member, Action { template void append(Args&... args) { append({ args... }); } template void remove(Args&... args) { remove({ args... }); } - void append(const nall::reference_array &list); - void remove(const nall::reference_array &list); + void append(const nall::array &list); + void remove(const nall::array &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, Action { struct RadioItem : private nall::base_from_member, Action { template static void group(Args&... args) { group({ args... }); } - static void group(const nall::reference_array &list); + static void group(const nall::array &list); nall::function onActivate; @@ -357,6 +358,11 @@ struct Button : private nall::base_from_member, Widget { }; struct Canvas : private nall::base_from_member, Widget { + nall::function onMouseLeave; + nall::function onMouseMove; + nall::function onMousePress; + nall::function 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, Widget { struct RadioBox : private nall::base_from_member, Widget { template static void group(Args&... args) { group({ args... }); } - static void group(const nall::reference_array &list); + static void group(const nall::array &list); nall::function onActivate; @@ -577,6 +583,11 @@ struct VerticalSlider : private nall::base_from_member, Widget }; struct Viewport : private nall::base_from_member, Widget { + nall::function onMouseLeave; + nall::function onMouseMove; + nall::function onMousePress; + nall::function onMouseRelease; + uintptr_t handle(); Viewport(); diff --git a/bsnes/phoenix/core/state.hpp b/bsnes/phoenix/core/state.hpp index e0c3b2df..1a4de4c0 100755 --- a/bsnes/phoenix/core/state.hpp +++ b/bsnes/phoenix/core/state.hpp @@ -14,8 +14,8 @@ struct Window::State { bool fullScreen; Geometry geometry; bool ignore; - reference_array layout; - reference_array menu; + array layout; + array menu; string menuFont; bool menuVisible; bool resizable; @@ -24,7 +24,7 @@ struct Window::State { bool statusVisible; string title; bool visible; - reference_array widget; + array widget; string widgetFont; State() { @@ -55,8 +55,12 @@ struct Action::State { }; struct Menu::State { - reference_array action; + array 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 group; + array group; string text; State() { @@ -229,7 +233,7 @@ struct ProgressBar::State { struct RadioBox::State { bool checked; - reference_array group; + array group; string text; State() { diff --git a/bsnes/phoenix/gtk/action/menu.cpp b/bsnes/phoenix/gtk/action/menu.cpp index 9a81dfa3..356d2d8e 100755 --- a/bsnes/phoenix/gtk/action/menu.cpp +++ b/bsnes/phoenix/gtk/action/menu.cpp @@ -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); } diff --git a/bsnes/phoenix/gtk/action/radio-item.cpp b/bsnes/phoenix/gtk/action/radio-item.cpp index 35ca6d9b..7a868d53 100755 --- a/bsnes/phoenix/gtk/action/radio-item.cpp +++ b/bsnes/phoenix/gtk/action/radio-item.cpp @@ -14,7 +14,7 @@ void pRadioItem::setChecked() { locked = false; } -void pRadioItem::setGroup(const reference_array &group) { +void pRadioItem::setGroup(const array &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)); diff --git a/bsnes/phoenix/gtk/keyboard.cpp b/bsnes/phoenix/gtk/keyboard.cpp index 6082d376..4e45fe13 100755 --- a/bsnes/phoenix/gtk/keyboard.cpp +++ b/bsnes/phoenix/gtk/keyboard.cpp @@ -1,8 +1,6 @@ -bidirectional_map 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 pKeyboard::state() { array 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; } diff --git a/bsnes/phoenix/gtk/platform.cpp b/bsnes/phoenix/gtk/platform.cpp index 0866412a..c6650dbb 100755 --- a/bsnes/phoenix/gtk/platform.cpp +++ b/bsnes/phoenix/gtk/platform.cpp @@ -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" diff --git a/bsnes/phoenix/gtk/platform.hpp b/bsnes/phoenix/gtk/platform.hpp index c46b051d..4d8cd41d 100755 --- a/bsnes/phoenix/gtk/platform.hpp +++ b/bsnes/phoenix/gtk/platform.hpp @@ -1,4 +1,6 @@ struct Settings : public configuration { + bidirectional_map keymap; + unsigned frameGeometryX; unsigned frameGeometryY; unsigned frameGeometryWidth; @@ -32,8 +34,6 @@ struct pDesktop { }; struct pKeyboard { - static bidirectional_map keymap; - static bool pressed(Keyboard::Scancode scancode); static array 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 &group); + void setGroup(const array &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 &group); + void setGroup(const array &group); void setText(const string &text); pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {} diff --git a/bsnes/phoenix/gtk/widget/canvas.cpp b/bsnes/phoenix/gtk/widget/canvas.cpp index 0231dbdb..9d17dc82 100755 --- a/bsnes/phoenix/gtk/widget/canvas.cpp +++ b/bsnes/phoenix/gtk/widget/canvas.cpp @@ -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() { diff --git a/bsnes/phoenix/gtk/widget/radio-box.cpp b/bsnes/phoenix/gtk/widget/radio-box.cpp index a06743b3..3aa39693 100755 --- a/bsnes/phoenix/gtk/widget/radio-box.cpp +++ b/bsnes/phoenix/gtk/widget/radio-box.cpp @@ -19,7 +19,7 @@ void pRadioBox::setChecked() { locked = false; } -void pRadioBox::setGroup(const reference_array &group) { +void pRadioBox::setGroup(const array &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)); diff --git a/bsnes/phoenix/gtk/widget/viewport.cpp b/bsnes/phoenix/gtk/widget/viewport.cpp index 18c61f5b..e842a2e5 100755 --- a/bsnes/phoenix/gtk/widget/viewport.cpp +++ b/bsnes/phoenix/gtk/widget/viewport.cpp @@ -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; diff --git a/bsnes/phoenix/phoenix.hpp b/bsnes/phoenix/phoenix.hpp index 4767d0ed..e4bb3f4c 100755 --- a/bsnes/phoenix/phoenix.hpp +++ b/bsnes/phoenix/phoenix.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/bsnes/phoenix/qt/action/menu.cpp b/bsnes/phoenix/qt/action/menu.cpp index f484e17e..de3a7341 100755 --- a/bsnes/phoenix/qt/action/menu.cpp +++ b/bsnes/phoenix/qt/action/menu.cpp @@ -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)); } diff --git a/bsnes/phoenix/qt/action/radio-item.cpp b/bsnes/phoenix/qt/action/radio-item.cpp index 30211219..8fcc1c22 100755 --- a/bsnes/phoenix/qt/action/radio-item.cpp +++ b/bsnes/phoenix/qt/action/radio-item.cpp @@ -12,7 +12,7 @@ void pRadioItem::setChecked() { locked = false; } -void pRadioItem::setGroup(const reference_array &group) { +void pRadioItem::setGroup(const array &group) { } void pRadioItem::setText(const string &text) { diff --git a/bsnes/phoenix/qt/keyboard.cpp b/bsnes/phoenix/qt/keyboard.cpp index aa7be5f0..4e45fe13 100755 --- a/bsnes/phoenix/qt/keyboard.cpp +++ b/bsnes/phoenix/qt/keyboard.cpp @@ -1,8 +1,6 @@ -bidirectional_map 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 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; } diff --git a/bsnes/phoenix/qt/platform.cpp b/bsnes/phoenix/qt/platform.cpp index 01068595..0ff46b2b 100755 --- a/bsnes/phoenix/qt/platform.cpp +++ b/bsnes/phoenix/qt/platform.cpp @@ -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" diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc index dffcba03..c73f8fa2 100755 --- a/bsnes/phoenix/qt/platform.moc +++ b/bsnes/phoenix/qt/platform.moc @@ -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! diff --git a/bsnes/phoenix/qt/platform.moc.hpp b/bsnes/phoenix/qt/platform.moc.hpp index f931b8b3..9a98f96e 100755 --- a/bsnes/phoenix/qt/platform.moc.hpp +++ b/bsnes/phoenix/qt/platform.moc.hpp @@ -1,6 +1,8 @@ static QApplication *qtApplication = 0; struct Settings : public configuration { + bidirectional_map keymap; + unsigned frameGeometryX; unsigned frameGeometryY; unsigned frameGeometryWidth; @@ -31,8 +33,6 @@ struct pDesktop { }; struct pKeyboard { - static bidirectional_map keymap; - static bool pressed(Keyboard::Scancode scancode); static array 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 &group); + void setGroup(const array &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 &group); + void setGroup(const array &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(); diff --git a/bsnes/phoenix/qt/widget/button.cpp b/bsnes/phoenix/qt/widget/button.cpp index 98c04373..dfcc6813 100755 --- a/bsnes/phoenix/qt/widget/button.cpp +++ b/bsnes/phoenix/qt/widget/button.cpp @@ -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; diff --git a/bsnes/phoenix/qt/widget/canvas.cpp b/bsnes/phoenix/qt/widget/canvas.cpp index 387f16dd..245c1e9f 100755 --- a/bsnes/phoenix/qt/widget/canvas.cpp +++ b/bsnes/phoenix/qt/widget/canvas.cpp @@ -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); diff --git a/bsnes/phoenix/qt/widget/radio-box.cpp b/bsnes/phoenix/qt/widget/radio-box.cpp index ca138108..4f37a884 100755 --- a/bsnes/phoenix/qt/widget/radio-box.cpp +++ b/bsnes/phoenix/qt/widget/radio-box.cpp @@ -17,7 +17,7 @@ void pRadioBox::setChecked() { locked = false; } -void pRadioBox::setGroup(const reference_array &group) { +void pRadioBox::setGroup(const array &group) { locked = true; if(qtGroup) { delete qtGroup; diff --git a/bsnes/phoenix/qt/widget/viewport.cpp b/bsnes/phoenix/qt/widget/viewport.cpp index 3a6254f9..1b67d776 100755 --- a/bsnes/phoenix/qt/widget/viewport.cpp +++ b/bsnes/phoenix/qt/widget/viewport.cpp @@ -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) { +} diff --git a/bsnes/phoenix/reference/action/menu.cpp b/bsnes/phoenix/reference/action/menu.cpp index c2c239f2..4f0a65a8 100755 --- a/bsnes/phoenix/reference/action/menu.cpp +++ b/bsnes/phoenix/reference/action/menu.cpp @@ -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) { } diff --git a/bsnes/phoenix/reference/action/radio-item.cpp b/bsnes/phoenix/reference/action/radio-item.cpp index fc732e04..65c07b6c 100755 --- a/bsnes/phoenix/reference/action/radio-item.cpp +++ b/bsnes/phoenix/reference/action/radio-item.cpp @@ -5,7 +5,7 @@ bool pRadioItem::checked() { void pRadioItem::setChecked() { } -void pRadioItem::setGroup(const reference_array &group) { +void pRadioItem::setGroup(const array &group) { } void pRadioItem::setText(const string &text) { diff --git a/bsnes/phoenix/reference/platform.hpp b/bsnes/phoenix/reference/platform.hpp index 666b0af3..ac759c0f 100755 --- a/bsnes/phoenix/reference/platform.hpp +++ b/bsnes/phoenix/reference/platform.hpp @@ -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 &group); + void setGroup(const array &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 &group); + void setGroup(const array &group); void setText(const string &text); pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {} diff --git a/bsnes/phoenix/reference/widget/radio-box.cpp b/bsnes/phoenix/reference/widget/radio-box.cpp index 603e2442..dd207271 100755 --- a/bsnes/phoenix/reference/widget/radio-box.cpp +++ b/bsnes/phoenix/reference/widget/radio-box.cpp @@ -5,7 +5,7 @@ bool pRadioBox::checked() { void pRadioBox::setChecked() { } -void pRadioBox::setGroup(const reference_array &group) { +void pRadioBox::setGroup(const array &group) { } void pRadioBox::setText(const string &text) { diff --git a/bsnes/phoenix/windows/action/item.cpp b/bsnes/phoenix/windows/action/item.cpp index eb076c3a..2804bfcb 100755 --- a/bsnes/phoenix/windows/action/item.cpp +++ b/bsnes/phoenix/windows/action/item.cpp @@ -26,4 +26,4 @@ void pItem::createBitmap() { nallImage.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear); hbitmap = CreateBitmap(nallImage); } -} \ No newline at end of file +} diff --git a/bsnes/phoenix/windows/action/menu.cpp b/bsnes/phoenix/windows/action/menu.cpp index 633a831f..5d9da04e 100755 --- a/bsnes/phoenix/windows/action/menu.cpp +++ b/bsnes/phoenix/windows/action/menu.cpp @@ -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(&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(&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(&action)) { Item &item = (Item&)action; if(action.state.visible) { @@ -53,21 +94,16 @@ void pMenu::update(Window &parentWindow, Menu *parentMenu) { } } else if(dynamic_cast(&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(&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); - } -} diff --git a/bsnes/phoenix/windows/action/radio-item.cpp b/bsnes/phoenix/windows/action/radio-item.cpp index b5399799..fa961239 100755 --- a/bsnes/phoenix/windows/action/radio-item.cpp +++ b/bsnes/phoenix/windows/action/radio-item.cpp @@ -11,7 +11,7 @@ void pRadioItem::setChecked() { } } -void pRadioItem::setGroup(const reference_array &group) { +void pRadioItem::setGroup(const array &group) { } void pRadioItem::setText(const string &text) { diff --git a/bsnes/phoenix/windows/keyboard.cpp b/bsnes/phoenix/windows/keyboard.cpp index eb288979..e007916d 100755 --- a/bsnes/phoenix/windows/keyboard.cpp +++ b/bsnes/phoenix/windows/keyboard.cpp @@ -1,8 +1,6 @@ -bidirectional_map 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 pKeyboard::state() { @@ -129,7 +127,7 @@ array 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; } diff --git a/bsnes/phoenix/windows/platform.cpp b/bsnes/phoenix/windows/platform.cpp index 27cfef8b..bce8037e 100755 --- a/bsnes/phoenix/windows/platform.cpp +++ b/bsnes/phoenix/windows/platform.cpp @@ -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(); } diff --git a/bsnes/phoenix/windows/platform.hpp b/bsnes/phoenix/windows/platform.hpp index bc4d4808..8abb93f3 100755 --- a/bsnes/phoenix/windows/platform.hpp +++ b/bsnes/phoenix/windows/platform.hpp @@ -1,3 +1,7 @@ +struct Settings { + bidirectional_map keymap; +}; + struct pFont; struct pWindow; struct pMenu; @@ -20,8 +24,6 @@ struct pDesktop { }; struct pKeyboard { - static bidirectional_map keymap; - static bool pressed(Keyboard::Scancode scancode); static array 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 &group); + void setGroup(const array &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 &group); + void setGroup(const array &group); void setText(const string &text); pRadioBox(RadioBox &radioBox) : pWidget(radioBox), radioBox(radioBox) {} diff --git a/bsnes/phoenix/windows/settings.cpp b/bsnes/phoenix/windows/settings.cpp new file mode 100755 index 00000000..343fc9fb --- /dev/null +++ b/bsnes/phoenix/windows/settings.cpp @@ -0,0 +1 @@ +static Settings *settings = nullptr; \ No newline at end of file diff --git a/bsnes/phoenix/windows/widget/canvas.cpp b/bsnes/phoenix/windows/widget/canvas.cpp index 613381d6..f2be9e38 100755 --- a/bsnes/phoenix/windows/widget/canvas.cpp +++ b/bsnes/phoenix/windows/widget/canvas.cpp @@ -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(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(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); } diff --git a/bsnes/phoenix/windows/widget/radio-box.cpp b/bsnes/phoenix/windows/widget/radio-box.cpp index 555a27a8..37e9905f 100755 --- a/bsnes/phoenix/windows/widget/radio-box.cpp +++ b/bsnes/phoenix/windows/widget/radio-box.cpp @@ -13,7 +13,7 @@ void pRadioBox::setChecked() { } } -void pRadioBox::setGroup(const reference_array &group) { +void pRadioBox::setGroup(const array &group) { } void pRadioBox::setText(const string &text) { diff --git a/bsnes/phoenix/windows/widget/viewport.cpp b/bsnes/phoenix/windows/widget/viewport.cpp index e46764f7..c0b13b69 100755 --- a/bsnes/phoenix/windows/widget/viewport.cpp +++ b/bsnes/phoenix/windows/widget/viewport.cpp @@ -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(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); -} +} \ No newline at end of file diff --git a/bsnes/snes/cartridge/cartridge.hpp b/bsnes/snes/cartridge/cartridge.hpp index 37555bc0..015b9ccf 100755 --- a/bsnes/snes/cartridge/cartridge.hpp +++ b/bsnes/snes/cartridge/cartridge.hpp @@ -91,7 +91,6 @@ struct Cartridge : property { private: void parse_markup(const char*); - unsigned parse_markup_integer(string&); void parse_markup_map(Mapping&, XML::Node&); void parse_markup_rom(XML::Node&); diff --git a/bsnes/snes/cartridge/markup.cpp b/bsnes/snes/cartridge/markup.cpp index e639fe52..43aadf13 100755 --- a/bsnes/snes/cartridge/markup.cpp +++ b/bsnes/snes/cartridge/markup.cpp @@ -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) { diff --git a/bsnes/snes/system/video.cpp b/bsnes/snes/system/video.cpp index 1d6020eb..2a562f18 100755 --- a/bsnes/snes/system/video.cpp +++ b/bsnes/snes/system/video.cpp @@ -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)); diff --git a/bsnes/ui/general/dip-switches.cpp b/bsnes/ui/general/dip-switches.cpp index 80ed1158..38bfab16 100755 --- a/bsnes/ui/general/dip-switches.cpp +++ b/bsnes/ui/general/dip-switches.cpp @@ -1,4 +1,4 @@ -DipSwitches *dipSwitches = 0; +DipSwitches *dipSwitches = nullptr; DipSwitch::DipSwitch() { append(name, { ~0, 0 }, 5); diff --git a/bsnes/ui/general/file-browser.cpp b/bsnes/ui/general/file-browser.cpp index 4a9d6fee..cf51b675 100755 --- a/bsnes/ui/general/file-browser.cpp +++ b/bsnes/ui/general/file-browser.cpp @@ -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) { diff --git a/bsnes/ui/general/main-window.cpp b/bsnes/ui/general/main-window.cpp index 43ae89bd..7cc94c4b 100755 --- a/bsnes/ui/general/main-window.cpp +++ b/bsnes/ui/general/main-window.cpp @@ -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 group; + array 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 group; + array group; settingsVideoShaderList = new RadioItem[files.size()]; for(unsigned n = 0; n < files.size(); n++) { diff --git a/bsnes/ui/general/slot-loader.cpp b/bsnes/ui/general/slot-loader.cpp index ff87d3b3..ad6e21d4 100755 --- a/bsnes/ui/general/slot-loader.cpp +++ b/bsnes/ui/general/slot-loader.cpp @@ -1,4 +1,4 @@ -SlotLoader *slotLoader = 0; +SlotLoader *slotLoader = nullptr; SlotLoaderPath::SlotLoaderPath() { browse.setText("Browse ..."); diff --git a/bsnes/ui/input/input.hpp b/bsnes/ui/input/input.hpp index ba0a5775..c4b57b73 100755 --- a/bsnes/ui/input/input.hpp +++ b/bsnes/ui/input/input.hpp @@ -27,7 +27,7 @@ struct TurboInput : DigitalInput { TurboInput(); }; -struct TertiaryInput : reference_array { +struct TertiaryInput : array { string name; virtual void attach(const string &primaryName, const string &secondaryName); @@ -35,14 +35,14 @@ struct TertiaryInput : reference_array { virtual int16_t poll(unsigned n); }; -struct SecondaryInput : reference_array { +struct SecondaryInput : array { string name; virtual void attach(const string &primaryName); virtual void bind(); }; -struct PrimaryInput : reference_array { +struct PrimaryInput : array { string name; virtual void attach(); @@ -59,7 +59,7 @@ struct InputManager { int16_t scancode[2][Scancode::Limit]; bool activeScancode; - reference_array inputList; + array inputList; NesInput nes; SnesInput snes; GameBoyInput gameBoy; diff --git a/bsnes/ui/interface/gameboy/gameboy.cpp b/bsnes/ui/interface/gameboy/gameboy.cpp index 473cbc78..72fd9510 100755 --- a/bsnes/ui/interface/gameboy/gameboy.cpp +++ b/bsnes/ui/interface/gameboy/gameboy.cpp @@ -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" }); diff --git a/bsnes/ui/interface/interface.cpp b/bsnes/ui/interface/interface.cpp index bae5cb61..6ef11b9c 100755 --- a/bsnes/ui/interface/interface.cpp +++ b/bsnes/ui/interface/interface.cpp @@ -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; diff --git a/bsnes/ui/interface/interface.hpp b/bsnes/ui/interface/interface.hpp index 2b87b02b..3e1003eb 100755 --- a/bsnes/ui/interface/interface.hpp +++ b/bsnes/ui/interface/interface.hpp @@ -55,7 +55,7 @@ struct Interface : property { 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) diff --git a/bsnes/ui/interface/nes/nes.cpp b/bsnes/ui/interface/nes/nes.cpp index f4cef721..49fc3f84 100755 --- a/bsnes/ui/interface/nes/nes.cpp +++ b/bsnes/ui/interface/nes/nes.cpp @@ -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" }); diff --git a/bsnes/ui/interface/snes/snes.cpp b/bsnes/ui/interface/snes/snes.cpp index 5469d6a1..9c9fd386 100755 --- a/bsnes/ui/interface/snes/snes.cpp +++ b/bsnes/ui/interface/snes/snes.cpp @@ -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" }); diff --git a/bsnes/ui/interface/snes/snes.hpp b/bsnes/ui/interface/snes/snes.hpp index 16ec5eec..981eab40 100755 --- a/bsnes/ui/interface/snes/snes.hpp +++ b/bsnes/ui/interface/snes/snes.hpp @@ -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(); diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 66d32045..3263115f 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -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;