Update to v084r04 release.

byuu says:

Fixed the Ys 5 input bug in the auto joypad polling code. Can't
guarantee it's hardware-accurate (I have no way to extensively test it),
but I can guarantee it is closer to being correct now.
Also uses updated version of phoenix.

The justifier input is indeed all fucked up now. Seems like it stops
updating input after firing for a few frames.
I really don't want to debug that code anymore ... anyone want to make
$10 by fixing it? :P
This commit is contained in:
Tim Allen 2011-12-12 21:59:53 +11:00
parent ad0805b168
commit ea95eaca3c
57 changed files with 764 additions and 242 deletions

View File

@ -74,7 +74,23 @@ clean:
-@$(call delete,*.pdb)
-@$(call delete,*.manifest)
sync:
if [ -d ./libco ]; then rm -r ./libco; fi
if [ -d ./nall ]; then rm -r ./nall; fi
if [ -d ./ruby ]; then rm -r ./ruby; fi
if [ -d ./phoenix ]; then rm -r ./phoenix; fi
cp -r ../libco ./libco
cp -r ../nall ./nall
cp -r ../ruby ./ruby
cp -r ../phoenix ./phoenix
rm -r libco/doc
rm -r libco/test
rm -r nall/test
rm -r ruby/_test
rm -r phoenix/nall
rm -r phoenix/test
archive-all:
tar -cjf bsnes.tar.bz2 data gameboy libco nall nes obj out phoenix ruby snes ui ui-libsnes Makefile cc.bat clean.bat sync.sh
tar -cjf bsnes.tar.bz2 data gameboy libco nall nes obj out phoenix ruby snes ui ui-libsnes Makefile cc.bat clean.bat
help:;

View File

@ -118,16 +118,21 @@ namespace nall {
operator=(std::move(source));
}
//index
inline T& operator[](unsigned index) {
if(index >= buffersize) resize(index + 1);
if(index >= buffersize) throw "array[] out of bounds";
return pool[index];
//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 index) const {
if(index >= buffersize) throw "array[] out of bounds";
return pool[index];
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

View File

@ -1,6 +1,7 @@
#ifndef NALL_FILEMAP_HPP
#define NALL_FILEMAP_HPP
#include <nall/file.hpp>
#include <nall/stdint.hpp>
#include <nall/windows/utf8.hpp>

55
bsnes/nall/hid.hpp Executable file
View File

@ -0,0 +1,55 @@
#ifndef NALL_HID_HPP
#define NALL_HID_HPP
#include <nall/xorg/xorg.hpp>
#include <nall/input.hpp>
namespace nall {
namespace HID {
struct Keyboard {
XlibDisplay *display;
inline void poll() {
XQueryKeymap(display, state);
}
inline bool operator[](unsigned id) {
return state[scancode[id] >> 3] & (1 << (scancode[id] & 7));
}
inline Keyboard() {
display = XOpenDisplay(0);
memset(&scancode, 0, sizeof scancode);
#define map(key, sym) scancode[key] = XKeysymToKeycode(display, sym)
using nall::Keyboard;
map(Keyboard::Insert, XK_Insert);
map(Keyboard::Delete, XK_Delete);
map(Keyboard::Home, XK_Home);
map(Keyboard::End, XK_End);
map(Keyboard::PageUp, XK_Prior);
map(Keyboard::PageDown, XK_Next);
map(Keyboard::Up, XK_Up);
map(Keyboard::Down, XK_Down);
map(Keyboard::Left, XK_Left);
map(Keyboard::Right, XK_Right);
#undef map
}
inline ~Keyboard() {
XCloseDisplay(display);
}
private:
char state[32];
uint8_t scancode[256];
};
}
}
#endif

View File

@ -42,6 +42,7 @@ struct image {
inline void free();
inline void allocate(unsigned width, unsigned height);
inline void clear(uint64_t color);
inline bool load(const string &filename);
inline void scale(unsigned width, unsigned height, interpolation op);
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
@ -169,6 +170,7 @@ void image::free() {
}
void image::allocate(unsigned width, unsigned height) {
if(data != nullptr && this->width == width && this->height == height) return;
free();
data = new uint8_t[width * height * stride]();
pitch = width * stride;
@ -176,6 +178,14 @@ void image::allocate(unsigned width, unsigned height) {
this->height = height;
}
void image::clear(uint64_t color) {
uint8_t *dp = data;
for(unsigned n = 0; n < width * height; n++) {
write(dp, color);
dp += stride;
}
}
bool image::load(const string &filename) {
if(loadBMP(filename) == true) return true;
if(loadPNG(filename) == true) return true;
@ -209,7 +219,7 @@ void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAl
g = normalize(g, green.depth, output.green.depth);
b = normalize(b, blue.depth, output.blue.depth);
output.write(dp, (a << output.alpha.shift) + (r << output.red.shift) + (g << output.green.shift) + (b << output.blue.shift));
output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift));
dp += output.stride;
}
}
@ -239,7 +249,7 @@ void image::alphaBlend(uint64_t alphaColor) {
colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale));
colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale));
write(dp, (colorA << alpha.shift) + (colorR << red.shift) + (colorG << green.shift) + (colorB << blue.shift));
write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift));
dp += stride;
}
}
@ -267,7 +277,7 @@ uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, d
G = max(0, min(G, (1 << green.depth) - 1));
B = max(0, min(B, (1 << blue.depth) - 1));
return (A << alpha.shift) + (R << red.shift) + (G << green.shift) + (B << blue.shift);
return (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift);
}
void image::scaleX(unsigned outputWidth, interpolation op) {
@ -360,7 +370,7 @@ bool image::loadBMP(const string &filename) {
uint64_t r = normalize((uint8_t)(color >> 16), 8, red.depth);
uint64_t g = normalize((uint8_t)(color >> 8), 8, green.depth);
uint64_t b = normalize((uint8_t)(color >> 0), 8, blue.depth);
write(dp, (a << alpha.shift) + (r << red.shift) + (g << green.shift) + (b << blue.shift));
write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift));
dp += stride;
}
}
@ -415,7 +425,7 @@ bool image::loadPNG(const string &filename) {
g = normalize(g, source.info.bitDepth, green.depth);
b = normalize(b, source.info.bitDepth, blue.depth);
return (a << alpha.shift) + (r << red.shift) + (g << green.shift) + (b << blue.shift);
return (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift);
};
for(unsigned y = 0; y < height; y++) {

10
bsnes/nall/mosaic.hpp Executable file
View File

@ -0,0 +1,10 @@
#ifndef NALL_MOSAIC_HPP
#define NALL_MOSAIC_HPP
#define NALL_MOSAIC_INTERNAL_HPP
#include <nall/mosaic/bitstream.hpp>
#include <nall/mosaic/context.hpp>
#include <nall/mosaic/parser.hpp>
#undef NALL_MOSAIC_INTERNAL_HPP
#endif

55
bsnes/nall/mosaic/bitstream.hpp Executable file
View File

@ -0,0 +1,55 @@
#ifdef NALL_MOSAIC_INTERNAL_HPP
namespace nall {
namespace mosaic {
struct bitstream {
filemap fp;
uint8_t *data;
unsigned size;
bool readonly;
bool endian;
inline bool read(uint64_t addr) const {
if(data == nullptr || (addr >> 3) >= size) return 0;
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
return data[addr >> 3] & mask;
}
inline void write(uint64_t addr, bool value) {
if(data == nullptr || readonly == true || (addr >> 3) >= size) return;
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
if(value == 0) data[addr >> 3] &= ~mask;
if(value == 1) data[addr >> 3] |= mask;
}
inline bool open(const string &filename) {
readonly = false;
if(fp.open(filename, filemap::mode::readwrite) == false) {
readonly = true;
if(fp.open(filename, filemap::mode::read) == false) {
return false;
}
}
data = fp.data();
size = fp.size();
return true;
}
inline void close() {
fp.close();
data = nullptr;
}
inline bitstream() : data(nullptr), endian(1) {
}
inline ~bitstream() {
close();
}
};
}
}
#endif

181
bsnes/nall/mosaic/context.hpp Executable file
View File

@ -0,0 +1,181 @@
#ifdef NALL_MOSAIC_INTERNAL_HPP
namespace nall {
namespace mosaic {
struct context {
unsigned offset;
unsigned width;
unsigned height;
unsigned count;
bool endian;
unsigned depth;
unsigned blockWidth;
unsigned blockHeight;
unsigned blockStride;
unsigned blockOffset;
array<unsigned> block;
unsigned tileWidth;
unsigned tileHeight;
unsigned tileStride;
unsigned tileOffset;
array<unsigned> tile;
unsigned mosaicWidth;
unsigned mosaicHeight;
unsigned mosaicStride;
unsigned mosaicOffset;
array<unsigned> mosaic;
unsigned paddingWidth;
unsigned paddingHeight;
unsigned paddingColor;
array<unsigned> palette;
inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
inline unsigned objectSize() const {
unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
+ blockOffset * tileHeight * mosaicWidth * mosaicHeight
+ tileStride * mosaicWidth * mosaicHeight
+ tileOffset * mosaicHeight;
return max(1u, size);
}
inline unsigned eval(const string &expression) {
intmax_t result;
if(fixedpoint::eval(expression, result) == false) return 0u;
return result;
}
inline void eval(array<unsigned> &buffer, const string &expression) {
lstring list = expression.split(",");
for(auto &item : list) {
item.trim();
if(item.wildcard("f(?*) *")) {
lstring part = item.split<1>(" ");
part[0].trim("f(", ")");
unsigned length = decimal(part[0].trim());
for(unsigned n = 0; n < length; n++) {
string fn = part[1];
fn.replace("n", decimal(n));
fn.replace("p", decimal(buffer.size()));
buffer.append(eval(fn));
}
} else if(item != "") {
buffer.append(eval(item));
}
}
}
inline void parse(const string &data) {
reset();
lstring lines = data.split("\n");
for(auto &line : lines) {
lstring part = line.split<1>(":");
if(part.size() != 2) continue;
part[0].trim();
part[1].trim();
if(part[0] == "offset") offset = eval(part[1]);
if(part[0] == "width") width = eval(part[1]);
if(part[0] == "height") height = eval(part[1]);
if(part[0] == "count") count = eval(part[1]);
if(part[0] == "endian") endian = eval(part[1]);
if(part[0] == "depth") depth = eval(part[1]);
if(part[0] == "blockWidth") blockWidth = eval(part[1]);
if(part[0] == "blockHeight") blockHeight = eval(part[1]);
if(part[0] == "blockStride") blockStride = eval(part[1]);
if(part[0] == "blockOffset") blockOffset = eval(part[1]);
if(part[0] == "block") eval(block, part[1]);
if(part[0] == "tileWidth") tileWidth = eval(part[1]);
if(part[0] == "tileHeight") tileHeight = eval(part[1]);
if(part[0] == "tileStride") tileStride = eval(part[1]);
if(part[0] == "tileOffset") tileOffset = eval(part[1]);
if(part[0] == "tile") eval(tile, part[1]);
if(part[0] == "mosaicWidth") mosaicWidth = eval(part[1]);
if(part[0] == "mosaicHeight") mosaicHeight = eval(part[1]);
if(part[0] == "mosaicStride") mosaicStride = eval(part[1]);
if(part[0] == "mosaicOffset") mosaicOffset = eval(part[1]);
if(part[0] == "mosaic") eval(mosaic, part[1]);
if(part[0] == "paddingWidth") paddingWidth = eval(part[1]);
if(part[0] == "paddingHeight") paddingHeight = eval(part[1]);
if(part[0] == "paddingColor") paddingColor = eval(part[1]);
if(part[0] == "palette") eval(palette, part[1]);
}
sanitize();
}
inline bool load(const string &filename) {
string filedata;
if(filedata.readfile(filename) == false) return false;
parse(filedata);
return true;
}
inline void sanitize() {
if(depth < 1) depth = 1;
if(depth > 24) depth = 24;
if(blockWidth < 1) blockWidth = 1;
if(blockHeight < 1) blockHeight = 1;
if(tileWidth < 1) tileWidth = 1;
if(tileHeight < 1) tileHeight = 1;
if(mosaicWidth < 1) mosaicWidth = 1;
if(mosaicHeight < 1) mosaicHeight = 1;
}
inline void reset() {
offset = 0;
width = 0;
height = 0;
count = 0;
endian = 1;
depth = 1;
blockWidth = 1;
blockHeight = 1;
blockStride = 0;
blockOffset = 0;
block.reset();
tileWidth = 1;
tileHeight = 1;
tileStride = 0;
tileOffset = 0;
tile.reset();
mosaicWidth = 1;
mosaicHeight = 1;
mosaicStride = 0;
mosaicOffset = 0;
mosaic.reset();
paddingWidth = 0;
paddingHeight = 0;
paddingColor = 0x000000;
palette.reset();
}
inline context() {
reset();
}
};
}
}
#endif

116
bsnes/nall/mosaic/parser.hpp Executable file
View File

@ -0,0 +1,116 @@
#ifdef NALL_MOSAIC_INTERNAL_HPP
namespace nall {
namespace mosaic {
struct parser {
image canvas;
inline void importData(bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
canvas.allocate(width, height);
canvas.clear(ctx.paddingColor);
parse(1, stream, offset, ctx, width, height);
}
inline bool exportData(bitstream &stream, uint64_t offset, context &ctx) {
if(stream.readonly) return false;
parse(0, stream, offset, ctx, canvas.width, canvas.height);
return true;
}
inline parser() : canvas(0, 32, 0u, 255u << 16, 255u << 8, 255u << 0) {
}
private:
inline uint32_t read(unsigned x, unsigned y) const {
unsigned addr = y * canvas.width + x;
if(addr >= canvas.width * canvas.height) return 0u;
uint32_t *buffer = (uint32_t*)canvas.data;
return buffer[addr];
}
inline void write(unsigned x, unsigned y, uint32_t data) {
unsigned addr = y * canvas.width + x;
if(addr >= canvas.width * canvas.height) return;
uint32_t *buffer = (uint32_t*)canvas.data;
buffer[addr] = data;
}
inline void parse(bool import, bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
stream.endian = ctx.endian;
unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
unsigned objectOffset = 0;
for(unsigned objectY = 0; objectY < canvasHeight; objectY++) {
for(unsigned objectX = 0; objectX < canvasWidth; objectX++) {
if(objectOffset++ >= ctx.count && ctx.count > 0) break;
unsigned objectIX = objectX * ctx.objectWidth();
unsigned objectIY = objectY * ctx.objectHeight();
unsigned mosaicOffset = 0;
for(unsigned mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) {
for(unsigned mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) {
unsigned mosaicData = ctx.mosaic(mosaicOffset++, 0);
unsigned mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth);
unsigned mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight);
unsigned tileOffset = 0;
for(unsigned tileY = 0; tileY < ctx.tileHeight; tileY++) {
for(unsigned tileX = 0; tileX < ctx.tileWidth; tileX++) {
unsigned tileData = ctx.tile(tileOffset++, 0);
unsigned tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth;
unsigned tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight;
unsigned blockOffset = 0;
for(unsigned blockY = 0; blockY < ctx.blockHeight; blockY++) {
for(unsigned blockX = 0; blockX < ctx.blockWidth; blockX++) {
if(import) {
unsigned palette = 0;
for(unsigned n = 0; n < ctx.depth; n++) {
palette |= stream.read(offset + ctx.block(blockOffset++, 0)) << n;
}
write(
objectIX + mosaicIX + tileIX + blockX,
objectIY + mosaicIY + tileIY + blockY,
ctx.palette(palette, palette)
);
} else {
uint32_t palette = read(
objectIX + mosaicIX + tileIX + blockX,
objectIY + mosaicIY + tileIY + blockY
);
for(unsigned n = 0; n < ctx.depth; n++) {
stream.write(offset + ctx.block(blockOffset++, 0), palette & 1);
palette >>= 1;
}
}
} //blockX
} //blockY
offset += ctx.blockStride;
} //tileX
offset += ctx.blockOffset;
} //tileY
offset += ctx.tileStride;
} //mosaicX
offset += ctx.tileOffset;
} //mosaicY
offset += ctx.mosaicStride;
} //objectX
offset += ctx.mosaicOffset;
} //objectY
}
};
}
}
#endif

View File

@ -23,6 +23,7 @@ namespace nall {
struct string {
inline void reserve(unsigned);
inline bool empty() const;
template<typename... Args> inline string& assign(Args&&... args);
template<typename... Args> inline string& append(Args&&... args);
@ -35,6 +36,7 @@ namespace nall {
template<unsigned Limit = 0> inline string& iqreplace(const char*, const char*);
inline unsigned length() const;
inline unsigned capacity() const;
template<unsigned Limit = 0> inline lstring split(const char*) const;
template<unsigned Limit = 0> inline lstring isplit(const char*) const;

View File

@ -19,6 +19,10 @@ void string::reserve(unsigned size_) {
}
}
bool string::empty() const {
return !*data;
}
template<typename... Args> string& string::assign(Args&&... args) {
*data = 0;
istring(*this, std::forward<Args>(args)...);

View File

@ -152,6 +152,15 @@ static bool eval(const char *s, intmax_t &result) {
}
}
static intmax_t parse(const char *s) {
try {
intmax_t result = eval(s);
return result;
} catch(const char *) {
return 0;
}
}
}
#endif

View File

@ -138,12 +138,20 @@ static bool eval(const char *s, double &result) {
result = eval(s);
return true;
} catch(const char*e) {
printf("%s\n", e);
result = 0;
return false;
}
}
static double parse(const char *s) {
try {
double result = eval(s);
return result;
} catch(const char *) {
return 0;
}
}
}
#endif

View File

@ -3,6 +3,7 @@
namespace nall {
unsigned string::length() const { return strlen(data); }
unsigned string::capacity() const { return size; }
template<unsigned limit> lstring string::split(const char *key) const { lstring result; result.split<limit>(key, data); return result; }
template<unsigned limit> lstring string::isplit(const char *key) const { lstring result; result.isplit<limit>(key, data); return result; }

29
bsnes/nall/xorg/guard.hpp Executable file
View File

@ -0,0 +1,29 @@
#ifndef NALL_XORG_GUARD_HPP
#define NALL_XORG_GUARD_HPP
#define None
#undef XlibNone
#define XlibNone 0L
#define Button1 XlibButton1
#define Button2 XlibButton2
#define Button3 XlibButton3
#define Button4 XlibButton4
#define Button5 XlibButton5
#define Display XlibDisplay
#define Screen XlibScreen
#define Window XlibWindow
#else
#undef NALL_XORG_GUARD_HPP
#undef None
#undef Button1
#undef Button2
#undef Button3
#undef Button4
#undef Button5
#undef Display
#undef Screen
#undef Window
#endif

12
bsnes/nall/xorg/xorg.hpp Executable file
View File

@ -0,0 +1,12 @@
#ifndef NALL_XORG_XORG_HPP
#define NALL_XORG_XORG_HPP
#include <nall/xorg/guard.hpp>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <nall/xorg/guard.hpp>
#endif

View File

@ -16,6 +16,21 @@
static bool OS_quit = false;
Window Window::None;
//Geometry
//========
string Geometry::text() {
return { x, ",", y, ",", width, ",", height };
}
Geometry::Geometry(const string &text) {
lstring part = text.split(",");
x = integer(part(0, "256"));
y = integer(part(1, "256"));
width = decimal(part(2, "256"));
height = decimal(part(3, "256"));
}
//Font
//====

View File

@ -50,8 +50,10 @@ struct Color {
struct Geometry {
signed x, y;
unsigned width, height;
nall::string text();
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
Geometry(const nall::string &text);
};
struct Position {
@ -208,7 +210,7 @@ struct Separator : private nall::base_from_member<pSeparator&>, Action {
};
struct Item : private nall::base_from_member<pItem&>, Action {
nall::function<void ()> onTick;
nall::function<void ()> onActivate;
void setText(const nall::string &text);
@ -220,7 +222,7 @@ struct Item : private nall::base_from_member<pItem&>, Action {
};
struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
nall::function<void ()> onTick;
nall::function<void ()> onToggle;
bool checked();
void setChecked(bool checked = true);
@ -237,7 +239,7 @@ struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
template<typename... Args> static void group(Args&... args) { group({ args... }); }
static void group(const nall::reference_array<RadioItem&> &list);
nall::function<void ()> onTick;
nall::function<void ()> onActivate;
bool checked();
void setChecked();
@ -302,7 +304,7 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
};
struct Button : private nall::base_from_member<pButton&>, Widget {
nall::function<void ()> onTick;
nall::function<void ()> onActivate;
void setText(const nall::string &text);
@ -328,7 +330,7 @@ struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
};
struct CheckBox : private nall::base_from_member<pCheckBox&>, Widget {
nall::function<void ()> onTick;
nall::function<void ()> onToggle;
bool checked();
void setChecked(bool checked = true);
@ -431,7 +433,7 @@ struct LineEdit : private nall::base_from_member<pLineEdit&>, Widget {
struct ListView : private nall::base_from_member<pListView&>, Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
nall::function<void (unsigned)> onToggle;
template<typename... Args> void append(const Args&... args) { append_({ args... }); }
void autoSizeColumns();
@ -473,7 +475,7 @@ struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
template<typename... Args> static void group(Args&... args) { group({ args... }); }
static void group(const nall::reference_array<RadioBox&> &list);
nall::function<void ()> onTick;
nall::function<void ()> onActivate;
bool checked();
void setChecked();

View File

@ -1,5 +1,5 @@
static void CheckItem_tick(CheckItem *self) {
if(self->p.locked == false && self->onTick) self->onTick();
static void CheckItem_toggle(CheckItem *self) {
if(self->p.locked == false && self->onToggle) self->onToggle();
}
bool pCheckItem::checked() {
@ -19,7 +19,7 @@ void pCheckItem::setText(const string &text) {
void pCheckItem::constructor() {
widget = gtk_check_menu_item_new_with_label(checkItem.state.text);
setChecked(checkItem.state.checked);
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_tick), (gpointer)&checkItem);
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_toggle), (gpointer)&checkItem);
}
void pCheckItem::destructor() {

View File

@ -1,5 +1,5 @@
static void Item_tick(Item *self) {
if(self->onTick) self->onTick();
static void Item_activate(Item *self) {
if(self->onActivate) self->onActivate();
}
void pItem::setText(const string &text) {
@ -8,7 +8,7 @@ void pItem::setText(const string &text) {
void pItem::constructor() {
widget = gtk_menu_item_new_with_label(item.state.text);
g_signal_connect_swapped(G_OBJECT(widget), "activate", G_CALLBACK(Item_tick), (gpointer)&item);
g_signal_connect_swapped(G_OBJECT(widget), "activate", G_CALLBACK(Item_activate), (gpointer)&item);
}
void pItem::destructor() {

View File

@ -1,6 +1,6 @@
static void RadioItem_tick(RadioItem *self) {
static void RadioItem_activate(RadioItem *self) {
for(auto &item : self->state.group) item.state.checked = (&item == self);
if(self->p.locked == false && self->checked() && self->onTick) self->onTick();
if(self->p.locked == false && self->checked() && self->onActivate) self->onActivate();
}
bool pRadioItem::checked() {
@ -34,7 +34,7 @@ void pRadioItem::constructor() {
for(auto &item : radioItem.state.group) {
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item.p.widget), item.state.checked);
}
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_tick), (gpointer)&radioItem);
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_activate), (gpointer)&radioItem);
}
void pRadioItem::destructor() {

View File

@ -34,11 +34,11 @@
Font pOS::defaultFont;
Geometry pOS::availableGeometry() {
Display *display = XOpenDisplay(0);
XlibDisplay *display = XOpenDisplay(0);
int screen = DefaultScreen(display);
static Atom atom = X11None;
if(atom == X11None) atom = XInternAtom(display, "_NET_WORKAREA", True);
static Atom atom = XlibNone;
if(atom == XlibNone) atom = XInternAtom(display, "_NET_WORKAREA", True);
int format;
unsigned char *data = 0;

View File

@ -1,5 +1,5 @@
static void Button_tick(Button *self) {
if(self->onTick) self->onTick();
static void Button_activate(Button *self) {
if(self->onActivate) self->onActivate();
}
Geometry pButton::minimumGeometry() {
@ -9,11 +9,12 @@ Geometry pButton::minimumGeometry() {
void pButton::setText(const string &text) {
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
setFont(widget.state.font);
}
void pButton::constructor() {
gtkWidget = gtk_button_new();
g_signal_connect_swapped(G_OBJECT(gtkWidget), "clicked", G_CALLBACK(Button_tick), (gpointer)&button);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "clicked", G_CALLBACK(Button_activate), (gpointer)&button);
setText(button.state.text);
}

View File

@ -1,6 +1,6 @@
static void CheckBox_tick(CheckBox *self) {
static void CheckBox_toggle(CheckBox *self) {
self->state.checked = self->checked();
if(self->p.locked == false && self->onTick) self->onTick();
if(self->p.locked == false && self->onToggle) self->onToggle();
}
bool pCheckBox::checked() {
@ -24,7 +24,7 @@ void pCheckBox::setText(const string &text) {
void pCheckBox::constructor() {
gtkWidget = gtk_check_button_new_with_label("");
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckBox_tick), (gpointer)&checkBox);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckBox_toggle), (gpointer)&checkBox);
setChecked(checkBox.state.checked);
setText(checkBox.state.text);

View File

@ -1,7 +1,7 @@
static void HorizontalScrollBar_change(HorizontalScrollBar *self) {
if(self->state.position == self->position()) return;
self->state.position = self->position();
if(self->onChange) self->onChange();
if(self->p.locked == false && self->onChange) self->onChange();
}
Geometry pHorizontalScrollBar::minimumGeometry() {
@ -13,9 +13,11 @@ unsigned pHorizontalScrollBar::position() {
}
void pHorizontalScrollBar::setLength(unsigned length) {
locked = true;
length += length == 0;
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
locked = false;
}
void pHorizontalScrollBar::setPosition(unsigned position) {

View File

@ -10,10 +10,10 @@ static void ListView_change(ListView *self) {
}
}
static void ListView_tick(GtkCellRendererToggle *cell, gchar *path_string, ListView *self) {
static void ListView_toggle(GtkCellRendererToggle *cell, gchar *path_string, ListView *self) {
unsigned row = decimal(path_string);
self->setChecked(row, !self->checked(row));
if(self->onTick) self->onTick(row);
if(self->onToggle) self->onToggle(row);
}
void pListView::append(const lstring &text) {
@ -134,7 +134,7 @@ void pListView::constructor() {
column[n].column = gtk_tree_view_column_new_with_attributes("", column[n].renderer, "active", n, (void*)0);
gtk_tree_view_column_set_resizable(column[n].column, false);
gtk_tree_view_column_set_visible(column[n].column, false);
g_signal_connect(column[n].renderer, "toggled", G_CALLBACK(ListView_tick), (gpointer)&listView);
g_signal_connect(column[n].renderer, "toggled", G_CALLBACK(ListView_toggle), (gpointer)&listView);
} else {
column[n].renderer = gtk_cell_renderer_text_new();
column[n].column = gtk_tree_view_column_new_with_attributes("", column[n].renderer, "text", n, (void*)0);

View File

@ -1,5 +1,5 @@
static void RadioBox_tick(RadioBox *self) {
if(self->p.locked == false && self->checked() && self->onTick) self->onTick();
static void RadioBox_activate(RadioBox *self) {
if(self->p.locked == false && self->checked() && self->onActivate) self->onActivate();
}
bool pRadioBox::checked() {
@ -35,7 +35,7 @@ void pRadioBox::setText(const string &text) {
void pRadioBox::constructor() {
gtkWidget = gtk_radio_button_new_with_label(0, "");
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioBox_tick), (gpointer)&radioBox);
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioBox_activate), (gpointer)&radioBox);
setText(radioBox.state.text);
}

View File

@ -1,7 +1,7 @@
static void VerticalScrollBar_change(VerticalScrollBar *self) {
if(self->state.position == self->position()) return;
self->state.position = self->position();
if(self->onChange) self->onChange();
if(self->p.locked == false && self->onChange) self->onChange();
}
Geometry pVerticalScrollBar::minimumGeometry() {
@ -13,9 +13,11 @@ unsigned pVerticalScrollBar::position() {
}
void pVerticalScrollBar::setLength(unsigned length) {
locked = true;
length += length == 0;
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
locked = false;
}
void pVerticalScrollBar::setPosition(unsigned position) {

View File

@ -18,19 +18,14 @@
#include <QApplication>
#include <QtGui>
#elif defined(PHOENIX_GTK)
#define None
#define Window X11Window
#define X11None 0L
#include <nall/xorg/guard.hpp>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <cairo.h>
#include <gdk/gdkkeysyms.h>
#include <X11/Xatom.h>
#undef None
#undef Window
#include <nall/xorg/guard.hpp>
#elif defined(PHOENIX_REFERENCE)
#else
#error "phoenix: unrecognized target"

View File

@ -13,7 +13,7 @@ void pCheckItem::setText(const string &text) {
void pCheckItem::constructor() {
qtAction = new QAction(0);
qtAction->setCheckable(true);
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
connect(qtAction, SIGNAL(triggered()), SLOT(onToggle()));
}
void pCheckItem::destructor() {
@ -21,7 +21,7 @@ void pCheckItem::destructor() {
delete qtAction;
}
void pCheckItem::onTick() {
void pCheckItem::onToggle() {
checkItem.state.checked = checked();
if(checkItem.onTick) checkItem.onTick();
if(checkItem.onToggle) checkItem.onToggle();
}

View File

@ -4,7 +4,7 @@ void pItem::setText(const string &text) {
void pItem::constructor() {
qtAction = new QAction(0);
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
}
void pItem::destructor() {
@ -12,6 +12,6 @@ void pItem::destructor() {
delete qtAction;
}
void pItem::onTick() {
if(item.onTick) item.onTick();
void pItem::onActivate() {
if(item.onActivate) item.onActivate();
}

View File

@ -25,7 +25,7 @@ void pRadioItem::constructor() {
qtAction->setCheckable(true);
qtAction->setActionGroup(qtGroup);
qtAction->setChecked(true);
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
}
void pRadioItem::destructor() {
@ -33,9 +33,9 @@ void pRadioItem::destructor() {
delete qtAction;
}
void pRadioItem::onTick() {
void pRadioItem::onActivate() {
if(radioItem.state.checked == false) {
setChecked();
if(locked == false && radioItem.onTick) radioItem.onTick();
if(locked == false && radioItem.onActivate) radioItem.onActivate();
}
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp'
**
** Created: Tue Nov 29 20:27:15 2011
** Created: Sun Dec 11 12:26:40 2011
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
**
** WARNING! All changes made in this file will be lost!
@ -148,7 +148,7 @@ static const uint qt_meta_data_pItem[] = {
};
static const char qt_meta_stringdata_pItem[] = {
"pItem\0\0onTick()\0"
"pItem\0\0onActivate()\0"
};
const QMetaObject pItem::staticMetaObject = {
@ -182,7 +182,7 @@ int pItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onTick(); break;
case 0: onActivate(); break;
default: ;
}
_id -= 1;
@ -209,7 +209,7 @@ static const uint qt_meta_data_pCheckItem[] = {
};
static const char qt_meta_stringdata_pCheckItem[] = {
"pCheckItem\0\0onTick()\0"
"pCheckItem\0\0onToggle()\0"
};
const QMetaObject pCheckItem::staticMetaObject = {
@ -243,7 +243,7 @@ int pCheckItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onTick(); break;
case 0: onToggle(); break;
default: ;
}
_id -= 1;
@ -270,7 +270,7 @@ static const uint qt_meta_data_pRadioItem[] = {
};
static const char qt_meta_stringdata_pRadioItem[] = {
"pRadioItem\0\0onTick()\0"
"pRadioItem\0\0onActivate()\0"
};
const QMetaObject pRadioItem::staticMetaObject = {
@ -304,7 +304,7 @@ int pRadioItem::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onTick(); break;
case 0: onActivate(); break;
default: ;
}
_id -= 1;
@ -331,7 +331,7 @@ static const uint qt_meta_data_pButton[] = {
};
static const char qt_meta_stringdata_pButton[] = {
"pButton\0\0onTick()\0"
"pButton\0\0onActivate()\0"
};
const QMetaObject pButton::staticMetaObject = {
@ -365,7 +365,7 @@ int pButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onTick(); break;
case 0: onActivate(); break;
default: ;
}
_id -= 1;
@ -443,7 +443,7 @@ static const uint qt_meta_data_pCheckBox[] = {
};
static const char qt_meta_stringdata_pCheckBox[] = {
"pCheckBox\0\0onTick()\0"
"pCheckBox\0\0onToggle()\0"
};
const QMetaObject pCheckBox::staticMetaObject = {
@ -477,7 +477,7 @@ int pCheckBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onTick(); break;
case 0: onToggle(); break;
default: ;
}
_id -= 1;
@ -815,7 +815,7 @@ static const uint qt_meta_data_pListView[] = {
static const char qt_meta_stringdata_pListView[] = {
"pListView\0\0onActivate()\0item\0"
"onChange(QTreeWidgetItem*)\0"
"onTick(QTreeWidgetItem*)\0"
"onToggle(QTreeWidgetItem*)\0"
};
const QMetaObject pListView::staticMetaObject = {
@ -851,7 +851,7 @@ int pListView::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
switch (_id) {
case 0: onActivate(); break;
case 1: onChange((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
case 2: onTick((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
case 2: onToggle((*reinterpret_cast< QTreeWidgetItem*(*)>(_a[1]))); break;
default: ;
}
_id -= 3;
@ -878,7 +878,7 @@ static const uint qt_meta_data_pRadioBox[] = {
};
static const char qt_meta_stringdata_pRadioBox[] = {
"pRadioBox\0\0onTick()\0"
"pRadioBox\0\0onActivate()\0"
};
const QMetaObject pRadioBox::staticMetaObject = {
@ -912,7 +912,7 @@ int pRadioBox::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: onTick(); break;
case 0: onActivate(); break;
default: ;
}
_id -= 1;

View File

@ -172,7 +172,7 @@ public:
void destructor();
public slots:
void onTick();
void onActivate();
};
struct pCheckItem : public QObject, public pAction {
@ -191,7 +191,7 @@ public:
void destructor();
public slots:
void onTick();
void onToggle();
};
struct pRadioItem : public QObject, public pAction {
@ -212,7 +212,7 @@ public:
void destructor();
public slots:
void onTick();
void onActivate();
};
struct pSizable : public pObject {
@ -267,7 +267,7 @@ public:
void orphan();
public slots:
void onTick();
void onActivate();
};
struct pCanvas : public QObject, public pWidget {
@ -311,7 +311,7 @@ public:
void orphan();
public slots:
void onTick();
void onToggle();
};
struct pComboBox : public QObject, public pWidget {
@ -472,7 +472,7 @@ public:
public slots:
void onActivate();
void onChange(QTreeWidgetItem *item);
void onTick(QTreeWidgetItem *item);
void onToggle(QTreeWidgetItem *item);
};
struct pProgressBar : public pWidget {
@ -508,7 +508,7 @@ public:
void orphan();
public slots:
void onTick();
void onActivate();
};
struct pTextEdit : public QObject, public pWidget {

View File

@ -9,7 +9,7 @@ void pButton::setText(const string &text) {
void pButton::constructor() {
qtWidget = qtButton = new QPushButton;
connect(qtButton, SIGNAL(released()), SLOT(onTick()));
connect(qtButton, SIGNAL(released()), SLOT(onActivate()));
pWidget::synchronizeState();
setText(button.state.text);
@ -25,6 +25,6 @@ void pButton::orphan() {
constructor();
}
void pButton::onTick() {
if(button.onTick) button.onTick();
void pButton::onActivate() {
if(button.onActivate) button.onActivate();
}

View File

@ -19,7 +19,7 @@ void pCheckBox::setText(const string &text) {
void pCheckBox::constructor() {
qtWidget = qtCheckBox = new QCheckBox;
connect(qtCheckBox, SIGNAL(stateChanged(int)), SLOT(onTick()));
connect(qtCheckBox, SIGNAL(stateChanged(int)), SLOT(onToggle()));
pWidget::synchronizeState();
setChecked(checkBox.state.checked);
@ -36,7 +36,7 @@ void pCheckBox::orphan() {
constructor();
}
void pCheckBox::onTick() {
void pCheckBox::onToggle() {
checkBox.state.checked = checked();
if(locked == false && checkBox.onTick) checkBox.onTick();
if(locked == false && checkBox.onToggle) checkBox.onToggle();
}

View File

@ -100,7 +100,7 @@ void pListView::constructor() {
connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
connect(qtListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(onChange(QTreeWidgetItem*)));
connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onToggle(QTreeWidgetItem*)));
pWidget::synchronizeState();
setCheckable(listView.state.checkable);
@ -139,9 +139,9 @@ void pListView::onChange(QTreeWidgetItem *item) {
if(locked == false && listView.onChange) listView.onChange();
}
void pListView::onTick(QTreeWidgetItem *item) {
void pListView::onToggle(QTreeWidgetItem *item) {
unsigned row = item->data(0, Qt::UserRole).toUInt();
bool checkState = checked(row);
listView.state.checked[row] = checkState;
if(locked == false && listView.onTick) listView.onTick(row);
if(locked == false && listView.onToggle) listView.onToggle(row);
}

View File

@ -40,7 +40,7 @@ void pRadioBox::constructor() {
qtGroup = new QButtonGroup;
qtGroup->addButton(qtRadioBox);
qtRadioBox->setChecked(true);
connect(qtRadioBox, SIGNAL(toggled(bool)), SLOT(onTick()));
connect(qtRadioBox, SIGNAL(toggled(bool)), SLOT(onActivate()));
pWidget::synchronizeState();
setGroup(radioBox.state.group);
@ -59,6 +59,6 @@ void pRadioBox::orphan() {
constructor();
}
void pRadioBox::onTick() {
if(locked == false && checked() && radioBox.onTick) radioBox.onTick();
void pRadioBox::onActivate() {
if(locked == false && checked() && radioBox.onActivate) radioBox.onActivate();
}

View File

@ -319,16 +319,16 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
if(!object) break;
if(dynamic_cast<pItem*>(object)) {
Item &item = ((pItem*)object)->item;
if(item.onTick) item.onTick();
if(item.onActivate) item.onActivate();
} else if(dynamic_cast<pCheckItem*>(object)) {
CheckItem &checkItem = ((pCheckItem*)object)->checkItem;
checkItem.setChecked(!checkItem.state.checked);
if(checkItem.onTick) checkItem.onTick();
if(checkItem.onToggle) checkItem.onToggle();
} else if(dynamic_cast<pRadioItem*>(object)) {
RadioItem &radioItem = ((pRadioItem*)object)->radioItem;
if(radioItem.state.checked == false) {
radioItem.setChecked();
if(radioItem.onTick) radioItem.onTick();
if(radioItem.onActivate) radioItem.onActivate();
}
}
} else {
@ -336,11 +336,11 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
if(!object) break;
if(dynamic_cast<Button*>(object)) {
Button &button = (Button&)*object;
if(button.onTick) button.onTick();
if(button.onActivate) button.onActivate();
} else if(dynamic_cast<CheckBox*>(object)) {
CheckBox &checkBox = (CheckBox&)*object;
checkBox.setChecked(!checkBox.state.checked);
if(checkBox.onTick) checkBox.onTick();
if(checkBox.onToggle) checkBox.onToggle();
} else if(dynamic_cast<ComboBox*>(object)) {
ComboBox &comboBox = (ComboBox&)*object;
if(HIWORD(wparam) == CBN_SELCHANGE) {
@ -358,7 +358,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
RadioBox &radioBox = (RadioBox&)*object;
if(radioBox.state.checked == false) {
radioBox.setChecked();
if(radioBox.onTick) radioBox.onTick();
if(radioBox.onActivate) radioBox.onActivate();
}
} else if(dynamic_cast<TextEdit*>(object)) {
TextEdit &textEdit = (TextEdit&)*object;
@ -384,7 +384,7 @@ static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) {
unsigned imagemask = ((nmlistview->uNewState & LVIS_STATEIMAGEMASK) >> 12) - 1;
if(imagemask == 0 || imagemask == 1) {
if(listView.p.locked == false && listView.onTick) listView.onTick(nmlistview->iItem);
if(listView.p.locked == false && listView.onToggle) listView.onToggle(nmlistview->iItem);
} else if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
listView.p.lostFocus = true;
} else if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) {

View File

@ -223,6 +223,7 @@ struct pCanvas : public pWidget {
void constructor();
void destructor();
void orphan();
void paint();
};
struct pCheckBox : public pWidget {

View File

@ -7,7 +7,7 @@ static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LP
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(object && dynamic_cast<Canvas*>(object)) {
Canvas &canvas = (Canvas&)*object;
canvas.update();
canvas.p.paint();
}
return TRUE;
}
@ -18,28 +18,10 @@ static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LP
void pCanvas::setSize(const Size &size) {
delete[] data;
data = new uint32_t[size.width * size.height];
memcpy(data, canvas.state.data, size.width * size.height * sizeof(uint32_t));
}
void pCanvas::update() {
RECT rc;
GetClientRect(hwnd, &rc);
unsigned width = canvas.state.width, height = canvas.state.height; //rc.right, height = rc.bottom;
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside now; negative height flips bitmap
bmi.bmiHeader.biSizeImage = sizeof(uint32_t) * width * height;
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
SetDIBitsToDevice(ps.hdc, 0, 0, width, height, 0, 0, 0, height, (void*)data, &bmi, DIB_RGB_COLORS);
EndPaint(hwnd, &ps);
memcpy(data, canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
InvalidateRect(hwnd, 0, false);
}
@ -60,3 +42,24 @@ void pCanvas::orphan() {
destructor();
constructor();
}
void pCanvas::paint() {
RECT rc;
GetClientRect(hwnd, &rc);
unsigned width = canvas.state.width, height = canvas.state.height;
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside now; negative height flips bitmap
bmi.bmiHeader.biSizeImage = sizeof(uint32_t) * width * height;
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
SetDIBitsToDevice(ps.hdc, 0, 0, width, height, 0, 0, 0, height, (void*)data, &bmi, DIB_RGB_COLORS);
EndPaint(hwnd, &ps);
}

View File

@ -75,6 +75,7 @@ private:
//auto joypad polling
bool auto_joypad_active;
bool auto_joypad_latch;
unsigned auto_joypad_counter;
unsigned auto_joypad_clock;

View File

@ -47,6 +47,7 @@ void CPU::serialize(serializer &s) {
s.integer(status.hdma_mode);
s.integer(status.auto_joypad_active);
s.integer(status.auto_joypad_latch);
s.integer(status.auto_joypad_counter);
s.integer(status.auto_joypad_clock);

View File

@ -3,9 +3,11 @@
//called every 256 clocks; see CPU::add_clocks()
void CPU::step_auto_joypad_poll() {
if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) {
//cache enable state at first iteration
if(status.auto_joypad_counter == 0) status.auto_joypad_latch = status.auto_joypad_poll;
status.auto_joypad_active = status.auto_joypad_counter <= 15;
if(status.auto_joypad_active && status.auto_joypad_poll) {
if(status.auto_joypad_active && status.auto_joypad_latch) {
if(status.auto_joypad_counter == 0) {
input.port1->latch(1);
input.port2->latch(1);

View File

@ -191,6 +191,7 @@ void CPU::timing_reset() {
status.hdma_mode = 0;
status.auto_joypad_active = false;
status.auto_joypad_latch = false;
status.auto_joypad_counter = 0;
status.auto_joypad_clock = 0;
}

View File

@ -1,18 +0,0 @@
synchronize() {
if [ -d ../"$1" ]; then
test -d "$1" && rm -r "$1"
cp -r ../"$1" ./"$1"
fi
}
synchronize "libco"
synchronize "nall"
synchronize "ruby"
synchronize "phoenix"
test -d libco/doc && rm -r libco/doc
test -d libco/test && rm -r libco/test
test -d nall/test && rm -r nall/test
test -d ruby/_test && rm -r ruby/_test
test -d phoenix/nall && rm -r phoenix/nall
test -d phoenix/test && rm -r phoenix/test

View File

@ -21,7 +21,7 @@ DipSwitches::DipSwitches() {
setGeometry({ 128, 128, 400, layout.minimumGeometry().height });
windowManager->append(this, "DipSwitches");
acceptButton.onTick = { &DipSwitches::accept, this };
acceptButton.onActivate = { &DipSwitches::accept, this };
}
void DipSwitches::load() {

View File

@ -26,12 +26,12 @@ FileBrowser::FileBrowser() {
setPath(path);
};
pathBrowse.onTick = [&] {
pathBrowse.onActivate = [&] {
string path = OS::folderSelect(*this, mode->path);
if(path != "") setPath(path);
};
pathUp.onTick = [&] {
pathUp.onActivate = [&] {
if(mode->path == "/") return;
string path = mode->path;
path.rtrim<1>("/");
@ -40,7 +40,7 @@ FileBrowser::FileBrowser() {
};
fileList.onChange = { &FileBrowser::synchronize, this };
fileList.onActivate = openButton.onTick = { &FileBrowser::fileListActivate, this };
fileList.onActivate = openButton.onActivate = { &FileBrowser::fileListActivate, this };
filterModes.append({ "Default", "", { "*" } });
filterModes.append({ "NES", "", { "*.fc", "*.nes" } });

View File

@ -199,124 +199,124 @@ MainWindow::MainWindow() {
onClose = [&] { application->quit = true; };
onSize = [&] { utility->resizeMainWindow(); };
cartridgeLoadNES.onTick = [&] {
cartridgeLoadNES.onActivate = [&] {
fileBrowser->open("Load Cartridge - NES", FileBrowser::Mode::NES, [](string filename) {
interface->nes.loadCartridge(filename);
});
};
cartridgeLoadSNES.onTick = [&] {
cartridgeLoadSNES.onActivate = [&] {
fileBrowser->open("Load Cartridge - SNES", FileBrowser::Mode::SNES, [](string filename) {
interface->snes.loadCartridge(filename);
});
};
cartridgeLoadGameBoy.onTick = [&] {
cartridgeLoadGameBoy.onActivate = [&] {
fileBrowser->open("Load Cartridge - Game Boy", FileBrowser::Mode::GameBoy, [](string filename) {
interface->gameBoy.loadCartridge(GameBoy::System::Revision::GameBoy, filename);
});
};
cartridgeLoadGameBoyColor.onTick = [&] {
cartridgeLoadGameBoyColor.onActivate = [&] {
fileBrowser->open("Load Cartridge - Game Boy Color", FileBrowser::Mode::GameBoyColor, [](string filename) {
interface->gameBoy.loadCartridge(GameBoy::System::Revision::GameBoyColor, filename);
});
};
cartridgeLoadSatellaviewSlotted.onTick = [&] { slotLoader->loadSatellaviewSlotted(); };
cartridgeLoadSatellaview.onTick = [&] { slotLoader->loadSatellaview(); };
cartridgeLoadSufamiTurbo.onTick = [&] { slotLoader->loadSufamiTurbo(); };
cartridgeLoadSuperGameBoy.onTick = [&] { slotLoader->loadSuperGameBoy(); };
cartridgeLoadSatellaviewSlotted.onActivate = [&] { slotLoader->loadSatellaviewSlotted(); };
cartridgeLoadSatellaview.onActivate = [&] { slotLoader->loadSatellaview(); };
cartridgeLoadSufamiTurbo.onActivate = [&] { slotLoader->loadSufamiTurbo(); };
cartridgeLoadSuperGameBoy.onActivate = [&] { slotLoader->loadSuperGameBoy(); };
nesPower.onTick = { &Interface::power, interface };
nesReset.onTick = { &Interface::reset, interface };
nesPower.onActivate = { &Interface::power, interface };
nesReset.onActivate = { &Interface::reset, interface };
nesPort1Device[0].onTick = [&] { interface->setController(0, 0); };
nesPort1Device[1].onTick = [&] { interface->setController(0, 1); };
nesPort1Device[0].onActivate = [&] { interface->setController(0, 0); };
nesPort1Device[1].onActivate = [&] { interface->setController(0, 1); };
nesPort2Device[0].onTick = [&] { interface->setController(1, 0); };
nesPort2Device[1].onTick = [&] { interface->setController(1, 1); };
nesPort2Device[0].onActivate = [&] { interface->setController(1, 0); };
nesPort2Device[1].onActivate = [&] { interface->setController(1, 1); };
nesCartridgeUnload.onTick = { &Interface::unloadCartridge, interface };
nesCartridgeUnload.onActivate = { &Interface::unloadCartridge, interface };
snesPower.onTick = { &Interface::power, interface };
snesReset.onTick = { &Interface::reset, interface };
snesPower.onActivate = { &Interface::power, interface };
snesReset.onActivate = { &Interface::reset, interface };
snesPort1Device[0].onTick = [&] { interface->setController(0, 0); };
snesPort1Device[1].onTick = [&] { interface->setController(0, 1); };
snesPort1Device[2].onTick = [&] { interface->setController(0, 2); };
snesPort1Device[3].onTick = [&] { interface->setController(0, 3); };
snesPort1Device[0].onActivate = [&] { interface->setController(0, 0); };
snesPort1Device[1].onActivate = [&] { interface->setController(0, 1); };
snesPort1Device[2].onActivate = [&] { interface->setController(0, 2); };
snesPort1Device[3].onActivate = [&] { interface->setController(0, 3); };
snesPort2Device[0].onTick = [&] { interface->setController(1, 0); };
snesPort2Device[1].onTick = [&] { interface->setController(1, 1); };
snesPort2Device[2].onTick = [&] { interface->setController(1, 2); };
snesPort2Device[3].onTick = [&] { interface->setController(1, 3); };
snesPort2Device[4].onTick = [&] { interface->setController(1, 4); };
snesPort2Device[5].onTick = [&] { interface->setController(1, 5); };
snesPort2Device[6].onTick = [&] { interface->setController(1, 6); };
snesPort2Device[7].onTick = [&] { interface->setController(1, 7); };
snesPort2Device[0].onActivate = [&] { interface->setController(1, 0); };
snesPort2Device[1].onActivate = [&] { interface->setController(1, 1); };
snesPort2Device[2].onActivate = [&] { interface->setController(1, 2); };
snesPort2Device[3].onActivate = [&] { interface->setController(1, 3); };
snesPort2Device[4].onActivate = [&] { interface->setController(1, 4); };
snesPort2Device[5].onActivate = [&] { interface->setController(1, 5); };
snesPort2Device[6].onActivate = [&] { interface->setController(1, 6); };
snesPort2Device[7].onActivate = [&] { interface->setController(1, 7); };
snesCartridgeUnload.onTick = { &Interface::unloadCartridge, interface };
snesCartridgeUnload.onActivate = { &Interface::unloadCartridge, interface };
gameBoyPower.onTick = { &Interface::power, interface };
gameBoyCartridgeUnload.onTick = { &Interface::unloadCartridge, interface };
gameBoyPower.onActivate = { &Interface::power, interface };
gameBoyCartridgeUnload.onActivate = { &Interface::unloadCartridge, interface };
settingsVideoFilterNone.onTick = [&] {
settingsVideoFilterNone.onActivate = [&] {
config->video.filter = "None";
utility->bindVideoFilter();
};
settingsVideoShaderNone.onTick = [&] {
settingsVideoShaderNone.onActivate = [&] {
config->video.shader = "None";
utility->bindVideoShader();
};
settingsVideoShaderBlur.onTick = [&] {
settingsVideoShaderBlur.onActivate = [&] {
config->video.shader = "Blur";
utility->bindVideoShader();
};
settingsSynchronizeVideo.onTick = [&] {
settingsSynchronizeVideo.onToggle = [&] {
config->video.synchronize = settingsSynchronizeVideo.checked();
video.set(Video::Synchronize, config->video.synchronize);
};
settingsSynchronizeAudio.onTick = [&] {
settingsSynchronizeAudio.onToggle = [&] {
config->audio.synchronize = settingsSynchronizeAudio.checked();
audio.set(Audio::Synchronize, config->audio.synchronize);
};
settingsCorrectAspectRatio.onTick = [&] {
settingsCorrectAspectRatio.onToggle = [&] {
config->video.correctAspectRatio = settingsCorrectAspectRatio.checked();
utility->resizeMainWindow();
};
settingsMaskOverscan.onTick = [&] {
settingsMaskOverscan.onToggle = [&] {
config->video.maskOverscan = settingsMaskOverscan.checked();
};
settingsMuteAudio.onTick = [&] {
settingsMuteAudio.onToggle = [&] {
config->audio.mute = settingsMuteAudio.checked();
dspaudio.setVolume(config->audio.mute == false ? (double)config->audio.volume / 100.0 : 0.0);
};
settingsConfiguration.onTick = [&] { settingsWindow->setVisible(); };
settingsConfiguration.onActivate = [&] { settingsWindow->setVisible(); };
toolsStateSave1.onTick = [&] { interface->saveState(1); };
toolsStateSave2.onTick = [&] { interface->saveState(2); };
toolsStateSave3.onTick = [&] { interface->saveState(3); };
toolsStateSave4.onTick = [&] { interface->saveState(4); };
toolsStateSave5.onTick = [&] { interface->saveState(5); };
toolsStateSave1.onActivate = [&] { interface->saveState(1); };
toolsStateSave2.onActivate = [&] { interface->saveState(2); };
toolsStateSave3.onActivate = [&] { interface->saveState(3); };
toolsStateSave4.onActivate = [&] { interface->saveState(4); };
toolsStateSave5.onActivate = [&] { interface->saveState(5); };
toolsStateLoad1.onTick = [&] { interface->loadState(1); };
toolsStateLoad2.onTick = [&] { interface->loadState(2); };
toolsStateLoad3.onTick = [&] { interface->loadState(3); };
toolsStateLoad4.onTick = [&] { interface->loadState(4); };
toolsStateLoad5.onTick = [&] { interface->loadState(5); };
toolsStateLoad1.onActivate = [&] { interface->loadState(1); };
toolsStateLoad2.onActivate = [&] { interface->loadState(2); };
toolsStateLoad3.onActivate = [&] { interface->loadState(3); };
toolsStateLoad4.onActivate = [&] { interface->loadState(4); };
toolsStateLoad5.onActivate = [&] { interface->loadState(5); };
toolsShrinkWindow.onTick = [&] { utility->resizeMainWindow(true); };
toolsCheatEditor.onTick = [&] { cheatEditor->setVisible(); };
toolsStateManager.onTick = [&] { stateManager->setVisible(); };
toolsShrinkWindow.onActivate = [&] { utility->resizeMainWindow(true); };
toolsCheatEditor.onActivate = [&] { cheatEditor->setVisible(); };
toolsStateManager.onActivate = [&] { stateManager->setVisible(); };
synchronize();
}
@ -347,7 +347,7 @@ void MainWindow::setupVideoFilters() {
if(auto position = name.position(".filter")) name[position()] = 0;
settingsVideoFilterList[n].setText(name);
settingsVideoFilterList[n].onTick = [&, n] {
settingsVideoFilterList[n].onActivate = [&, n] {
config->video.filter = videoFilterName[n];
utility->bindVideoFilter();
};
@ -378,7 +378,7 @@ void MainWindow::setupVideoShaders() {
if(auto position = name.position(string{ ".", config->video.driver, ".shader" })) name[position()] = 0;
settingsVideoShaderList[n].setText(name);
settingsVideoShaderList[n].onTick = [&, n] {
settingsVideoShaderList[n].onActivate = [&, n] {
config->video.shader = videoShaderName[n];
utility->bindVideoShader();
};

View File

@ -43,21 +43,21 @@ void SlotLoader::loadSatellaviewSlotted() {
slot[1].path.setEnabled(false);
slot[1].browse.setEnabled(false);
base.browse.onTick = [&] {
base.browse.onActivate = [&] {
fileBrowser->open("Load Cartridge - SNES", FileBrowser::Mode::SNES, [&](const string &filename) {
base.path.setText(filename);
synchronize();
});
};
slot[0].browse.onTick = [&] {
slot[0].browse.onActivate = [&] {
fileBrowser->open("Load Cartridge - Satellaview", FileBrowser::Mode::Satellaview, [&](const string &filename) {
slot[0].path.setText(filename);
synchronize();
});
};
loadButton.onTick = [&] {
loadButton.onActivate = [&] {
this->setVisible(false);
interface->snes.loadSatellaviewSlottedCartridge(base.path.text(), slot[0].path.text());
};
@ -79,7 +79,7 @@ void SlotLoader::loadSatellaview() {
slot[1].path.setEnabled(false);
slot[1].browse.setEnabled(false);
base.browse.onTick = [&] {
base.browse.onActivate = [&] {
fileBrowser->open("Load BIOS - Satellaview", FileBrowser::Mode::SNES, [&](const string &filename) {
config->path.bios.satellaview = filename;
base.path.setText(filename);
@ -87,14 +87,14 @@ void SlotLoader::loadSatellaview() {
});
};
slot[0].browse.onTick = [&] {
slot[0].browse.onActivate = [&] {
fileBrowser->open("Load Cartridge - Satellaview", FileBrowser::Mode::Satellaview, [&](const string &filename) {
slot[0].path.setText(filename);
synchronize();
});
};
loadButton.onTick = [&] {
loadButton.onActivate = [&] {
this->setVisible(false);
interface->snes.loadSatellaviewCartridge(base.path.text(), slot[0].path.text());
};
@ -116,7 +116,7 @@ void SlotLoader::loadSufamiTurbo() {
slot[1].path.setEnabled(true);
slot[1].browse.setEnabled(true);
base.browse.onTick = [&] {
base.browse.onActivate = [&] {
fileBrowser->open("Load BIOS - Sufami Turbo", FileBrowser::Mode::SNES, [&](const string &filename) {
config->path.bios.sufamiTurbo = filename;
base.path.setText(filename);
@ -124,21 +124,21 @@ void SlotLoader::loadSufamiTurbo() {
});
};
slot[0].browse.onTick = [&] {
slot[0].browse.onActivate = [&] {
fileBrowser->open("Load Cartridge - Sufami Turbo", FileBrowser::Mode::SufamiTurbo, [&](const string &filename) {
slot[0].path.setText(filename);
synchronize();
});
};
slot[1].browse.onTick = [&] {
slot[1].browse.onActivate = [&] {
fileBrowser->open("Load Cartridge - Sufami Turbo", FileBrowser::Mode::SufamiTurbo, [&](const string &filename) {
slot[1].path.setText(filename);
synchronize();
});
};
loadButton.onTick = [&] {
loadButton.onActivate = [&] {
this->setVisible(false);
interface->snes.loadSufamiTurboCartridge(base.path.text(), slot[0].path.text(), slot[1].path.text());
};
@ -160,7 +160,7 @@ void SlotLoader::loadSuperGameBoy() {
slot[1].path.setEnabled(false);
slot[1].browse.setEnabled(false);
base.browse.onTick = [&] {
base.browse.onActivate = [&] {
fileBrowser->open("Load BIOS - Super Game Boy", FileBrowser::Mode::SNES, [&](const string &filename) {
config->path.bios.superGameBoy = filename;
base.path.setText(filename);
@ -168,14 +168,14 @@ void SlotLoader::loadSuperGameBoy() {
});
};
slot[0].browse.onTick = [&] {
slot[0].browse.onActivate = [&] {
fileBrowser->open("Load Cartridge - Game Boy", FileBrowser::Mode::GameBoy, [&](const string &filename) {
slot[0].path.setText(filename);
synchronize();
});
};
loadButton.onTick = [&] {
loadButton.onActivate = [&] {
this->setVisible(false);
interface->snes.loadSuperGameBoyCartridge(base.path.text(), slot[0].path.text());
};

View File

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

View File

@ -76,7 +76,7 @@ AdvancedSettings::AdvancedSettings() {
config->input.driver = list[inputDriver.selection()];
};
focusPolicy[0].onTick = [&] { config->input.focusPolicy = 0; };
focusPolicy[1].onTick = [&] { config->input.focusPolicy = 1; };
focusPolicy[2].onTick = [&] { config->input.focusPolicy = 2; };
focusPolicy[0].onActivate = [&] { config->input.focusPolicy = 0; };
focusPolicy[1].onActivate = [&] { config->input.focusPolicy = 1; };
focusPolicy[2].onActivate = [&] { config->input.focusPolicy = 2; };
}

View File

@ -33,10 +33,10 @@ InputSettings::InputSettings() : activeInput(0) {
tertiary.onChange = { &InputSettings::tertiaryChange, this };
inputList.onChange = { &InputSettings::synchronize, this };
inputList.onActivate = { &InputSettings::assignInput, this };
assignPrimary.onTick = [&] { assignMouseInput(0); };
assignSecondary.onTick = [&] { assignMouseInput(1); };
assignTertiary.onTick = [&] { assignMouseInput(2); };
clearButton.onTick = { &InputSettings::clearInput, this };
assignPrimary.onActivate = [&] { assignMouseInput(0); };
assignSecondary.onActivate = [&] { assignMouseInput(1); };
assignTertiary.onActivate = [&] { assignMouseInput(2); };
clearButton.onActivate = { &InputSettings::clearInput, this };
synchronize();
}

View File

@ -69,21 +69,21 @@ VideoSettings::VideoSettings() {
overscanHorizontal.slider.onChange = overscanVertical.slider.onChange =
{ &VideoSettings::synchronize, this };
fullScreen[0].onTick = [&] { config->video.fullScreenMode = 0; };
fullScreen[1].onTick = [&] { config->video.fullScreenMode = 1; };
fullScreen[2].onTick = [&] { config->video.fullScreenMode = 2; };
fullScreen[0].onActivate = [&] { config->video.fullScreenMode = 0; };
fullScreen[1].onActivate = [&] { config->video.fullScreenMode = 1; };
fullScreen[2].onActivate = [&] { config->video.fullScreenMode = 2; };
compositor[0].onTick = [&] {
compositor[0].onActivate = [&] {
config->video.compositionMode = 0;
compositor::enable(application->compositionEnable);
};
compositor[1].onTick = [&] {
compositor[1].onActivate = [&] {
config->video.compositionMode = 1;
compositor::enable(application->compositionEnable && mainWindow->fullScreen() == false);
};
compositor[2].onTick = [&] {
compositor[2].onActivate = [&] {
config->video.compositionMode = 2;
compositor::enable(false);
};

View File

@ -18,15 +18,15 @@ CheatDatabase::CheatDatabase() {
controlLayout.append(spacer, { ~0, 0 }, 0);
controlLayout.append(acceptButton, { 80, 0 }, 0);
selectAllButton.onTick = [&] {
selectAllButton.onActivate = [&] {
for(unsigned n = 0; n < cheatCode.size(); n++) cheatList.setChecked(n, true);
};
unselectAllButton.onTick = [&] {
unselectAllButton.onActivate = [&] {
for(unsigned n = 0; n < cheatCode.size(); n++) cheatList.setChecked(n, false);
};
acceptButton.onTick = { &CheatDatabase::addCodes, this };
acceptButton.onActivate = { &CheatDatabase::addCodes, this };
}
void CheatDatabase::findCodes() {

View File

@ -34,12 +34,12 @@ CheatEditor::CheatEditor() {
synchronize();
cheatList.onChange = { &CheatEditor::synchronize, this };
cheatList.onTick = [&](unsigned) { updateInterface(); };
cheatList.onToggle = [&](unsigned) { updateInterface(); };
codeEdit.onChange = { &CheatEditor::updateCode, this };
descEdit.onChange = { &CheatEditor::updateDesc, this };
findButton.onTick = { &CheatDatabase::findCodes, cheatDatabase };
clearAllButton.onTick = { &CheatEditor::clearAll, this };
clearButton.onTick = { &CheatEditor::clearSelected, this };
findButton.onActivate = { &CheatDatabase::findCodes, cheatDatabase };
clearAllButton.onActivate = { &CheatEditor::clearAll, this };
clearButton.onActivate = { &CheatEditor::clearSelected, this };
}
void CheatEditor::synchronize() {

View File

@ -1,4 +1,4 @@
StateManager *stateManager = 0;
StateManager *stateManager = nullptr;
StateManager::StateManager() {
setTitle("State Manager");
@ -32,9 +32,9 @@ StateManager::StateManager() {
stateList.onActivate = { &StateManager::slotLoad, this };
stateList.onChange = { &StateManager::synchronize, this };
descEdit.onChange = { &StateManager::slotSaveDescription, this };
loadButton.onTick = { &StateManager::slotLoad, this };
saveButton.onTick = { &StateManager::slotSave, this };
eraseButton.onTick = { &StateManager::slotErase, this };
loadButton.onActivate = { &StateManager::slotLoad, this };
saveButton.onActivate = { &StateManager::slotSave, this };
eraseButton.onActivate = { &StateManager::slotErase, this };
}
void StateManager::synchronize() {