mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-10 21:54:23 +02:00
Update to v082r15 release.
byuu says: 7.5 hours of power coding. Das Keyboard definitely helped (but didn't eliminate) RSI, neato. Okay, the NES resampler was using 315 / 88.8 by mistake, so the output rate was wrong, causing way more video/audio stuttering than necessary. STILL forgot the NES APU frame IRQ clear thing on $4015 reads, blah. Why do I always remember things right after uploading the WIPs? Recreated the input manager with a new design, works much nicer than the old one, a whole lot less duplicated code. Recreated the input settings window to work with the new multi-system emulation. All input settings are saved to their own configuration file, input.cfg. Going to batch folder for now. Okay, so the new input settings window ... basically there are now three drop-downs, and I'm not even trying to label them anymore. They are primary, secondary, tertiary selectors for the listed group below. Examples: "NES -> Controller Port 1 -> Gamepad" "SNES -> Controller Port 2 -> Super Scope" "User Interface -> Hotkeys -> Save States" I am aware that "Clear" gets disabled when assigning. I will work on that later, being lazy for now and disabling the entire window. Have to add the mouse binders back, too. Escape and modifiers are both mappable as individual keys now. If you want to clear, click the damn clear button :P Oh, and all input goes to all windows for now. That'll be fixed too when input focus stuff is re-added.
This commit is contained in:
@@ -4,27 +4,56 @@ namespace GameBoy {
|
|||||||
|
|
||||||
Cheat cheat;
|
Cheat cheat;
|
||||||
|
|
||||||
bool Cheat::decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp) {
|
bool Cheat::decode(const string &code_, unsigned &addr, unsigned &data, unsigned &comp) {
|
||||||
static bool initialize = false;
|
static bool initialize = false;
|
||||||
static uint8 asciiMap[256];
|
static uint8 mapProActionReplay[256], mapGameGenie[256];
|
||||||
|
|
||||||
if(initialize == false) {
|
if(initialize == false) {
|
||||||
initialize = true;
|
initialize = true;
|
||||||
foreach(n, asciiMap) n = ~0;
|
|
||||||
asciiMap['0'] = 0; asciiMap['1'] = 1; asciiMap['2'] = 2; asciiMap['3'] = 3;
|
foreach(n, mapProActionReplay) n = ~0;
|
||||||
asciiMap['4'] = 4; asciiMap['5'] = 5; asciiMap['6'] = 6; asciiMap['7'] = 7;
|
mapProActionReplay['0'] = 0; mapProActionReplay['1'] = 1; mapProActionReplay['2'] = 2; mapProActionReplay['3'] = 3;
|
||||||
asciiMap['8'] = 8; asciiMap['9'] = 9; asciiMap['A'] = 10; asciiMap['B'] = 11;
|
mapProActionReplay['4'] = 4; mapProActionReplay['5'] = 5; mapProActionReplay['6'] = 6; mapProActionReplay['7'] = 7;
|
||||||
asciiMap['C'] = 12; asciiMap['D'] = 13; asciiMap['E'] = 14; asciiMap['F'] = 15;
|
mapProActionReplay['8'] = 8; mapProActionReplay['9'] = 9; mapProActionReplay['A'] = 10; mapProActionReplay['B'] = 11;
|
||||||
|
mapProActionReplay['C'] = 12; mapProActionReplay['D'] = 13; mapProActionReplay['E'] = 14; mapProActionReplay['F'] = 15;
|
||||||
|
|
||||||
|
foreach(n, mapGameGenie) n = ~0;
|
||||||
|
mapGameGenie['0'] = 0; mapGameGenie['1'] = 1; mapGameGenie['2'] = 2; mapGameGenie['3'] = 3;
|
||||||
|
mapGameGenie['4'] = 4; mapGameGenie['5'] = 5; mapGameGenie['6'] = 6; mapGameGenie['7'] = 7;
|
||||||
|
mapGameGenie['8'] = 8; mapGameGenie['9'] = 9; mapGameGenie['A'] = 10; mapGameGenie['B'] = 11;
|
||||||
|
mapGameGenie['C'] = 12; mapGameGenie['D'] = 13; mapGameGenie['E'] = 14; mapGameGenie['F'] = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string code = code_;
|
||||||
|
code.upper();
|
||||||
unsigned length = code.length(), bits = 0;
|
unsigned length = code.length(), bits = 0;
|
||||||
for(unsigned n = 0; n < length; n++) if(asciiMap[code[n]] > 15 && code[n] != '-') return false;
|
|
||||||
|
if(code.wildcard("????:??")) {
|
||||||
|
code = { substr(code, 0, 4), substr(code, 5, 2) };
|
||||||
|
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
|
bits = hex(code);
|
||||||
|
addr = (bits >> 8) & 0xffff;
|
||||||
|
data = (bits >> 0) & 0xff;
|
||||||
|
comp = ~0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(code.wildcard("????:??:??")) {
|
||||||
|
code = { substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2) };
|
||||||
|
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
|
bits = hex(code);
|
||||||
|
addr = (bits >> 16) & 0xffff;
|
||||||
|
data = (bits >> 8) & 0xff;
|
||||||
|
comp = (bits >> 0) & 0xff;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(code.wildcard("???" "-" "???")) {
|
if(code.wildcard("???" "-" "???")) {
|
||||||
string text = string(code).replace("-", "");
|
code = { substr(code, 0, 3), substr(code, 4, 3) };
|
||||||
for(unsigned n = 0; n < 6; n++) bits |= asciiMap[text[n]] << (20 - n * 4);
|
for(unsigned n = 0; n < 6; n++) if(mapGameGenie[code[n]] > 15) return false;
|
||||||
|
for(unsigned n = 0; n < 6; n++) bits |= mapGameGenie[code[n]] << (20 - n * 4);
|
||||||
|
|
||||||
addr = (bits >> 0) & 0xffff;
|
addr = (bits >> 0) & 0xffff;
|
||||||
data = (bits >> 16) & 0xff;
|
data = (bits >> 16) & 0xff;
|
||||||
comp = ~0;
|
comp = ~0;
|
||||||
|
|
||||||
@@ -34,12 +63,13 @@ bool Cheat::decode(const string &code, unsigned &addr, unsigned &data, unsigned
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(code.wildcard("???" "-" "???" "-" "???")) {
|
if(code.wildcard("???" "-" "???" "-" "???")) {
|
||||||
string text = string(code).replace("-", "");
|
code = { substr(code, 0, 3), substr(code, 4, 3), substr(code, 8, 1), substr(code, 10, 1) };
|
||||||
for(unsigned n = 0; n < 8; n++) bits |= asciiMap[text[n == 7 ? 8 : n]] << (28 - n * 4);
|
for(unsigned n = 0; n < 8; n++) if(mapGameGenie[code[n]] > 15) return false;
|
||||||
|
for(unsigned n = 0; n < 8; n++) bits |= mapGameGenie[code[n]] << (28 - n * 4);
|
||||||
|
|
||||||
addr = (bits >> 8) & 0xffff;
|
addr = (bits >> 8) & 0xffff;
|
||||||
data = (bits >> 24) & 0xff;
|
data = (bits >> 24) & 0xff;
|
||||||
comp = (bits >> 0) & 0xff;
|
comp = (bits >> 0) & 0xff;
|
||||||
|
|
||||||
addr = (((addr >> 4) | (addr << 12)) & 0xffff) ^ 0xf000;
|
addr = (((addr >> 4) | (addr << 12)) & 0xffff) ^ 0xf000;
|
||||||
comp = (((comp >> 2) | (comp << 6)) & 0xff) ^ 0xba;
|
comp = (((comp >> 2) | (comp << 6)) & 0xff) ^ 0xba;
|
||||||
|
@@ -48,7 +48,8 @@ uint8 Bus::read(uint16 addr) {
|
|||||||
for(unsigned n = 0; n < cheat.size(); n++) {
|
for(unsigned n = 0; n < cheat.size(); n++) {
|
||||||
if(cheat[n].addr == addr) {
|
if(cheat[n].addr == addr) {
|
||||||
if(cheat[n].comp > 255 || cheat[n].comp == data) {
|
if(cheat[n].comp > 255 || cheat[n].comp == data) {
|
||||||
return cheat[n].data;
|
data = cheat[n].data;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -121,6 +121,8 @@
|
|||||||
*path = 0;
|
*path = 0;
|
||||||
struct passwd *userinfo = getpwuid(getuid());
|
struct passwd *userinfo = getpwuid(getuid());
|
||||||
if(userinfo) strcpy(path, userinfo->pw_dir);
|
if(userinfo) strcpy(path, userinfo->pw_dir);
|
||||||
|
unsigned length = strlen(path);
|
||||||
|
if(path[length] != '/') strcpy(path + length, "/");
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,24 +4,53 @@ namespace NES {
|
|||||||
|
|
||||||
Cheat cheat;
|
Cheat cheat;
|
||||||
|
|
||||||
bool Cheat::decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp) {
|
bool Cheat::decode(const string &code_, unsigned &addr, unsigned &data, unsigned &comp) {
|
||||||
static bool initialize = false;
|
static bool initialize = false;
|
||||||
static uint8 asciiMap[256];
|
static uint8 mapProActionReplay[256], mapGameGenie[256];
|
||||||
|
|
||||||
if(initialize == false) {
|
if(initialize == false) {
|
||||||
initialize = true;
|
initialize = true;
|
||||||
foreach(n, asciiMap) n = ~0;
|
|
||||||
asciiMap['A'] = 0; asciiMap['P'] = 1; asciiMap['Z'] = 2; asciiMap['L'] = 3;
|
foreach(n, mapProActionReplay) n = ~0;
|
||||||
asciiMap['G'] = 4; asciiMap['I'] = 5; asciiMap['T'] = 6; asciiMap['Y'] = 7;
|
mapProActionReplay['0'] = 0; mapProActionReplay['1'] = 1; mapProActionReplay['2'] = 2; mapProActionReplay['3'] = 3;
|
||||||
asciiMap['E'] = 8; asciiMap['O'] = 9; asciiMap['X'] = 10; asciiMap['U'] = 11;
|
mapProActionReplay['4'] = 4; mapProActionReplay['5'] = 5; mapProActionReplay['6'] = 6; mapProActionReplay['7'] = 7;
|
||||||
asciiMap['K'] = 12; asciiMap['S'] = 13; asciiMap['V'] = 14; asciiMap['N'] = 15;
|
mapProActionReplay['8'] = 8; mapProActionReplay['9'] = 9; mapProActionReplay['A'] = 10; mapProActionReplay['B'] = 11;
|
||||||
|
mapProActionReplay['C'] = 12; mapProActionReplay['D'] = 13; mapProActionReplay['E'] = 14; mapProActionReplay['F'] = 15;
|
||||||
|
|
||||||
|
foreach(n, mapGameGenie) n = ~0;
|
||||||
|
mapGameGenie['A'] = 0; mapGameGenie['P'] = 1; mapGameGenie['Z'] = 2; mapGameGenie['L'] = 3;
|
||||||
|
mapGameGenie['G'] = 4; mapGameGenie['I'] = 5; mapGameGenie['T'] = 6; mapGameGenie['Y'] = 7;
|
||||||
|
mapGameGenie['E'] = 8; mapGameGenie['O'] = 9; mapGameGenie['X'] = 10; mapGameGenie['U'] = 11;
|
||||||
|
mapGameGenie['K'] = 12; mapGameGenie['S'] = 13; mapGameGenie['V'] = 14; mapGameGenie['N'] = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string code = code_;
|
||||||
|
code.upper();
|
||||||
unsigned length = code.length(), bits = 0;
|
unsigned length = code.length(), bits = 0;
|
||||||
for(unsigned n = 0; n < length; n++) if(asciiMap[code[n]] > 15) return false;
|
|
||||||
|
|
||||||
if(code.length() == 6) {
|
if(code.wildcard("????:??")) {
|
||||||
for(unsigned n = 0; n < 6; n++) bits |= asciiMap[code[n]] << (20 - n * 4);
|
code = { substr(code, 0, 4), substr(code, 5, 2) };
|
||||||
|
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
|
bits = hex(code);
|
||||||
|
addr = (bits >> 8) & 0xffff;
|
||||||
|
data = (bits >> 0) & 0xff;
|
||||||
|
comp = ~0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(code.wildcard("????:??:??")) {
|
||||||
|
code = { substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2) };
|
||||||
|
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
|
bits = hex(code);
|
||||||
|
addr = (bits >> 16) & 0xffff;
|
||||||
|
data = (bits >> 8) & 0xff;
|
||||||
|
comp = (bits >> 0) & 0xff;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(length == 6) {
|
||||||
|
for(unsigned n = 0; n < 6; n++) if(mapGameGenie[code[n]] > 15) return false;
|
||||||
|
for(unsigned n = 0; n < 6; n++) bits |= mapGameGenie[code[n]] << (20 - n * 4);
|
||||||
unsigned addrTable[] = { 10, 9, 8, 7, 2, 1, 0, 19, 14, 13, 12, 11, 6, 5, 4 };
|
unsigned addrTable[] = { 10, 9, 8, 7, 2, 1, 0, 19, 14, 13, 12, 11, 6, 5, 4 };
|
||||||
unsigned dataTable[] = { 23, 18, 17, 16, 3, 22, 21, 20 };
|
unsigned dataTable[] = { 23, 18, 17, 16, 3, 22, 21, 20 };
|
||||||
|
|
||||||
@@ -31,8 +60,9 @@ bool Cheat::decode(const string &code, unsigned &addr, unsigned &data, unsigned
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code.length() == 8) {
|
if(length == 8) {
|
||||||
for(unsigned n = 0; n < 8; n++) bits |= asciiMap[code[n]] << (28 - n * 4);
|
for(unsigned n = 0; n < 8; n++) if(mapGameGenie[code[n]] > 15) return false;
|
||||||
|
for(unsigned n = 0; n < 8; n++) bits |= mapGameGenie[code[n]] << (28 - n * 4);
|
||||||
unsigned addrTable[] = { 18, 17, 16, 15, 10, 9, 8, 27, 22, 21, 20, 19, 14, 13, 12 };
|
unsigned addrTable[] = { 18, 17, 16, 15, 10, 9, 8, 27, 22, 21, 20, 19, 14, 13, 12 };
|
||||||
unsigned dataTable[] = { 31, 26, 25, 24, 3, 30, 29, 28 };
|
unsigned dataTable[] = { 31, 26, 25, 24, 3, 30, 29, 28 };
|
||||||
unsigned compTable[] = { 7, 2, 1, 0, 11, 6, 5,4 };
|
unsigned compTable[] = { 7, 2, 1, 0, 11, 6, 5,4 };
|
||||||
|
@@ -13,15 +13,16 @@ Bus bus;
|
|||||||
|
|
||||||
uint8 Bus::read(uint16 addr) {
|
uint8 Bus::read(uint16 addr) {
|
||||||
uint8 data = cartridge.prg_read(addr);
|
uint8 data = cartridge.prg_read(addr);
|
||||||
if(addr <= 0x1fff) return cpu.ram_read(addr);
|
if(addr <= 0x1fff) data = cpu.ram_read(addr);
|
||||||
if(addr <= 0x3fff) return ppu.read(addr);
|
else if(addr <= 0x3fff) data = ppu.read(addr);
|
||||||
if(addr <= 0x4017) return cpu.read(addr);
|
else if(addr <= 0x4017) data = cpu.read(addr);
|
||||||
|
|
||||||
if(cheat.override[addr]) {
|
if(cheat.override[addr]) {
|
||||||
for(unsigned n = 0; n < cheat.size(); n++) {
|
for(unsigned n = 0; n < cheat.size(); n++) {
|
||||||
if(cheat[n].addr == addr) {
|
if(cheat[n].addr == addr) {
|
||||||
if(cheat[n].comp > 255 || cheat[n].comp == data) {
|
if(cheat[n].comp > 255 || cheat[n].comp == data) {
|
||||||
return cheat[n].data;
|
data = cheat[n].data;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
namespace NES {
|
namespace NES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bnes";
|
static const char Name[] = "bnes";
|
||||||
static const char Version[] = "000.10";
|
static const char Version[] = "000.11";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -144,7 +144,7 @@ void Window::append(Layout &layout) {
|
|||||||
((Sizable&)layout).state.window = this;
|
((Sizable&)layout).state.window = this;
|
||||||
((Sizable&)layout).state.layout = 0;
|
((Sizable&)layout).state.layout = 0;
|
||||||
p.append(layout);
|
p.append(layout);
|
||||||
layout.synchronize();
|
layout.synchronizeLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ void Window::append(Widget &widget) {
|
|||||||
if(state.widget.append(widget)) {
|
if(state.widget.append(widget)) {
|
||||||
((Sizable&)widget).state.window = this;
|
((Sizable&)widget).state.window = this;
|
||||||
p.append(widget);
|
p.append(widget);
|
||||||
synchronize();
|
synchronizeLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ void Window::setWidgetFont(const string &font) {
|
|||||||
return p.setWidgetFont(font);
|
return p.setWidgetFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::synchronize() {
|
void Window::synchronizeLayout() {
|
||||||
setGeometry(geometry());
|
setGeometry(geometry());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +509,7 @@ void Layout::append(Sizable &sizable) {
|
|||||||
|
|
||||||
if(dynamic_cast<Layout*>(&sizable)) {
|
if(dynamic_cast<Layout*>(&sizable)) {
|
||||||
Layout &layout = (Layout&)sizable;
|
Layout &layout = (Layout&)sizable;
|
||||||
layout.synchronize();
|
layout.synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dynamic_cast<Widget*>(&sizable)) {
|
if(dynamic_cast<Widget*>(&sizable)) {
|
||||||
@@ -517,7 +517,7 @@ void Layout::append(Sizable &sizable) {
|
|||||||
if(sizable.window()) sizable.window()->append(widget);
|
if(sizable.window()) sizable.window()->append(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(window()) window()->synchronize();
|
if(window()) window()->synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layout::remove(Sizable &sizable) {
|
void Layout::remove(Sizable &sizable) {
|
||||||
@@ -529,7 +529,7 @@ void Layout::remove(Sizable &sizable) {
|
|||||||
sizable.state.layout = 0;
|
sizable.state.layout = 0;
|
||||||
sizable.state.window = 0;
|
sizable.state.window = 0;
|
||||||
|
|
||||||
if(window()) window()->synchronize();
|
if(window()) window()->synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::Layout():
|
Layout::Layout():
|
||||||
|
@@ -152,7 +152,7 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
|
|||||||
void setTitle(const nall::string &text);
|
void setTitle(const nall::string &text);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void setWidgetFont(const nall::string &font);
|
void setWidgetFont(const nall::string &font);
|
||||||
void synchronize();
|
void synchronizeLayout();
|
||||||
|
|
||||||
Window();
|
Window();
|
||||||
~Window();
|
~Window();
|
||||||
@@ -256,7 +256,7 @@ struct Layout : private nall::base_from_member<pLayout&>, Sizable {
|
|||||||
virtual void append(Sizable &sizable);
|
virtual void append(Sizable &sizable);
|
||||||
virtual void remove(Sizable &sizable);
|
virtual void remove(Sizable &sizable);
|
||||||
virtual void reset() {}
|
virtual void reset() {}
|
||||||
virtual void synchronize() = 0;
|
virtual void synchronizeLayout() = 0;
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
Layout(pLayout &p);
|
Layout(pLayout &p);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
void FixedLayout::append(Sizable &sizable, const Geometry &geometry) {
|
void FixedLayout::append(Sizable &sizable, const Geometry &geometry) {
|
||||||
children.append({ &sizable, geometry });
|
children.append({ &sizable, geometry });
|
||||||
synchronize();
|
synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedLayout::append(Sizable &sizable) {
|
void FixedLayout::append(Sizable &sizable) {
|
||||||
@@ -55,7 +55,7 @@ void FixedLayout::setVisible(bool visible) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedLayout::synchronize() {
|
void FixedLayout::synchronizeLayout() {
|
||||||
foreach(child, children) {
|
foreach(child, children) {
|
||||||
Layout::append(*child.sizable);
|
Layout::append(*child.sizable);
|
||||||
child.sizable->setGeometry(child.geometry);
|
child.sizable->setGeometry(child.geometry);
|
||||||
|
@@ -8,7 +8,7 @@ struct FixedLayout : Layout {
|
|||||||
void setEnabled(bool enabled = true);
|
void setEnabled(bool enabled = true);
|
||||||
void setGeometry(const Geometry &geometry);
|
void setGeometry(const Geometry &geometry);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void synchronize();
|
void synchronizeLayout();
|
||||||
bool visible();
|
bool visible();
|
||||||
FixedLayout();
|
FixedLayout();
|
||||||
~FixedLayout();
|
~FixedLayout();
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
void HorizontalLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) {
|
void HorizontalLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) {
|
||||||
foreach(child, children) if(child.sizable == &sizable) return;
|
foreach(child, children) if(child.sizable == &sizable) return;
|
||||||
children.append({ &sizable, width, height, spacing });
|
children.append({ &sizable, width, height, spacing });
|
||||||
synchronize();
|
synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HorizontalLayout::append(Sizable &sizable) {
|
void HorizontalLayout::append(Sizable &sizable) {
|
||||||
foreach(child, children) if(child.sizable == &sizable) return;
|
foreach(child, children) if(child.sizable == &sizable) return;
|
||||||
Layout::append(sizable);
|
Layout::append(sizable);
|
||||||
if(window()) window()->synchronize();
|
if(window()) window()->synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HorizontalLayout::enabled() {
|
bool HorizontalLayout::enabled() {
|
||||||
@@ -114,7 +114,7 @@ void HorizontalLayout::setVisible(bool visible) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HorizontalLayout::synchronize() {
|
void HorizontalLayout::synchronizeLayout() {
|
||||||
foreach(child, children) Layout::append(*child.sizable);
|
foreach(child, children) Layout::append(*child.sizable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ struct HorizontalLayout : public Layout {
|
|||||||
void setGeometry(const Geometry &geometry);
|
void setGeometry(const Geometry &geometry);
|
||||||
void setMargin(unsigned margin);
|
void setMargin(unsigned margin);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void synchronize();
|
void synchronizeLayout();
|
||||||
bool visible();
|
bool visible();
|
||||||
HorizontalLayout();
|
HorizontalLayout();
|
||||||
~HorizontalLayout();
|
~HorizontalLayout();
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
void VerticalLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) {
|
void VerticalLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) {
|
||||||
foreach(child, children) if(child.sizable == &sizable) return;
|
foreach(child, children) if(child.sizable == &sizable) return;
|
||||||
children.append({ &sizable, width, height, spacing });
|
children.append({ &sizable, width, height, spacing });
|
||||||
synchronize();
|
synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerticalLayout::append(Sizable &sizable) {
|
void VerticalLayout::append(Sizable &sizable) {
|
||||||
foreach(child, children) if(child.sizable == &sizable) return;
|
foreach(child, children) if(child.sizable == &sizable) return;
|
||||||
Layout::append(sizable);
|
Layout::append(sizable);
|
||||||
if(window()) window()->synchronize();
|
if(window()) window()->synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerticalLayout::enabled() {
|
bool VerticalLayout::enabled() {
|
||||||
@@ -118,7 +118,7 @@ void VerticalLayout::setVisible(bool visible) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerticalLayout::synchronize() {
|
void VerticalLayout::synchronizeLayout() {
|
||||||
foreach(child, children) Layout::append(*child.sizable);
|
foreach(child, children) Layout::append(*child.sizable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ struct VerticalLayout : public Layout {
|
|||||||
void setGeometry(const Geometry &geometry);
|
void setGeometry(const Geometry &geometry);
|
||||||
void setMargin(unsigned margin);
|
void setMargin(unsigned margin);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void synchronize();
|
void synchronizeLayout();
|
||||||
bool visible();
|
bool visible();
|
||||||
VerticalLayout();
|
VerticalLayout();
|
||||||
~VerticalLayout();
|
~VerticalLayout();
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||||
**
|
**
|
||||||
** Created: Thu Sep 8 17:34:23 2011
|
** Created: Fri Sep 16 21:12:56 2011
|
||||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
void pComboBox::append(const string &text) {
|
void pComboBox::append(const string &text) {
|
||||||
|
locked = true;
|
||||||
qtComboBox->addItem(QString::fromUtf8(text));
|
qtComboBox->addItem(QString::fromUtf8(text));
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry pComboBox::minimumGeometry() {
|
Geometry pComboBox::minimumGeometry() {
|
||||||
@@ -10,7 +12,9 @@ Geometry pComboBox::minimumGeometry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pComboBox::reset() {
|
void pComboBox::reset() {
|
||||||
|
locked = true;
|
||||||
while(qtComboBox->count()) qtComboBox->removeItem(0);
|
while(qtComboBox->count()) qtComboBox->removeItem(0);
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned pComboBox::selection() {
|
unsigned pComboBox::selection() {
|
||||||
@@ -45,7 +49,6 @@ void pComboBox::orphan() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pComboBox::onChange() {
|
void pComboBox::onChange() {
|
||||||
if(locked == true) return;
|
|
||||||
comboBox.state.selection = selection();
|
comboBox.state.selection = selection();
|
||||||
if(comboBox.onChange) comboBox.onChange();
|
if(locked == false && comboBox.onChange) comboBox.onChange();
|
||||||
}
|
}
|
||||||
|
@@ -71,19 +71,21 @@ bool Cheat::decode(const string &code, unsigned &addr, unsigned &data) {
|
|||||||
|
|
||||||
#define ischr(n) ((n >= '0' && n <= '9') || (n >= 'a' && n <= 'f'))
|
#define ischr(n) ((n >= '0' && n <= '9') || (n >= 'a' && n <= 'f'))
|
||||||
|
|
||||||
if(strlen(t) == 8 || (strlen(t) == 9 && t[6] == ':')) {
|
if(t.wildcard("??????:??")) {
|
||||||
//Pro Action Replay
|
//Pro Action Replay
|
||||||
if(strlen(t) == 9 && t[6] == ':') t = { substr(t, 0, 6), substr(t, 7) }; //strip ':'
|
t = { substr(t, 0, 6), substr(t, 7, 2) };
|
||||||
for(unsigned i = 0; i < 8; i++) if(!ischr(t[i])) return false; //validate input
|
for(unsigned n = 0; n < 8; n++) if(!ischr(t[n])) return false; //validate input
|
||||||
unsigned r = hex(t);
|
unsigned r = hex(t);
|
||||||
|
|
||||||
addr = r >> 8;
|
addr = r >> 8;
|
||||||
data = r & 0xff;
|
data = r & 0xff;
|
||||||
return true;
|
return true;
|
||||||
} else if(strlen(t) == 9 && t[4] == '-') {
|
}
|
||||||
|
|
||||||
|
if(t.wildcard("????" "-" "????")) {
|
||||||
//Game Genie
|
//Game Genie
|
||||||
t = { substr(t, 0, 4), substr(t, 5) }; //strip '-'
|
t = { substr(t, 0, 4), substr(t, 5, 4) };
|
||||||
for(unsigned i = 0; i < 8; i++) if(!ischr(t[i])) return false; //validate input
|
for(unsigned n = 0; n < 8; n++) if(!ischr(t[n])) return false; //validate input
|
||||||
t.transform("df4709156bc8a23e", "0123456789abcdef");
|
t.transform("df4709156bc8a23e", "0123456789abcdef");
|
||||||
unsigned r = hex(t);
|
unsigned r = hex(t);
|
||||||
static unsigned bits[] = { 13, 12, 11, 10, 5, 4, 3, 2, 23, 22, 21, 20, 1, 0, 15, 14, 19, 18, 17, 16, 9, 8, 7, 6 };
|
static unsigned bits[] = { 13, 12, 11, 10, 5, 4, 3, 2, 23, 22, 21, 20, 1, 0, 15, 14, 19, 18, 17, 16, 9, 8, 7, 6 };
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "082.14";
|
static const char Version[] = "082.15";
|
||||||
static const unsigned SerializerVersion = 22;
|
static const unsigned SerializerVersion = 22;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ include $(snes)/Makefile
|
|||||||
include $(gameboy)/Makefile
|
include $(gameboy)/Makefile
|
||||||
name := batch
|
name := batch
|
||||||
|
|
||||||
ui_objects := ui-main ui-config ui-interface ui-utility
|
ui_objects := ui-main ui-config ui-interface ui-input ui-utility
|
||||||
ui_objects += ui-general ui-settings ui-tools
|
ui_objects += ui-general ui-settings ui-tools
|
||||||
ui_objects += phoenix ruby
|
ui_objects += phoenix ruby
|
||||||
ui_objects += $(if $(call streq,$(platform),win),resource)
|
ui_objects += $(if $(call streq,$(platform),win),resource)
|
||||||
@@ -70,6 +70,7 @@ objects := $(patsubst %,obj/%.o,$(objects))
|
|||||||
obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/)
|
obj/ui-main.o: $(ui)/main.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-config.o: $(ui)/config/config.cpp $(call rwildcard,$(ui)/)
|
obj/ui-config.o: $(ui)/config/config.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-interface.o: $(ui)/interface/interface.cpp $(call rwildcard,$(ui)/)
|
obj/ui-interface.o: $(ui)/interface/interface.cpp $(call rwildcard,$(ui)/)
|
||||||
|
obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/)
|
obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/)
|
obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/)
|
obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/)
|
||||||
|
@@ -21,6 +21,7 @@ using namespace ruby;
|
|||||||
|
|
||||||
#include "config/config.hpp"
|
#include "config/config.hpp"
|
||||||
#include "interface/interface.hpp"
|
#include "interface/interface.hpp"
|
||||||
|
#include "input/input.hpp"
|
||||||
#include "utility/utility.hpp"
|
#include "utility/utility.hpp"
|
||||||
#include "general/general.hpp"
|
#include "general/general.hpp"
|
||||||
#include "settings/settings.hpp"
|
#include "settings/settings.hpp"
|
||||||
@@ -35,6 +36,7 @@ struct Application {
|
|||||||
string title;
|
string title;
|
||||||
string normalFont;
|
string normalFont;
|
||||||
string boldFont;
|
string boldFont;
|
||||||
|
string titleFont;
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
Application(int argc, char **argv);
|
Application(int argc, char **argv);
|
||||||
|
@@ -19,6 +19,8 @@ MainWindow::MainWindow() {
|
|||||||
snesPower.setText("Power Cycle");
|
snesPower.setText("Power Cycle");
|
||||||
snesReset.setText("Reset");
|
snesReset.setText("Reset");
|
||||||
snesCartridgeUnload.setText("Unload Cartridge");
|
snesCartridgeUnload.setText("Unload Cartridge");
|
||||||
|
snesPort1.setText("Controller Port 1");
|
||||||
|
snesPort2.setText("Controller Port 2");
|
||||||
|
|
||||||
gameBoyMenu.setText("Game Boy");
|
gameBoyMenu.setText("Game Boy");
|
||||||
gameBoyPower.setText("Power Cycle");
|
gameBoyPower.setText("Power Cycle");
|
||||||
@@ -26,7 +28,7 @@ MainWindow::MainWindow() {
|
|||||||
|
|
||||||
settingsMenu.setText("Settings");
|
settingsMenu.setText("Settings");
|
||||||
settingsSynchronizeVideo.setText("Synchronize Video");
|
settingsSynchronizeVideo.setText("Synchronize Video");
|
||||||
settingsSynchronizeVideo.setChecked(false);
|
settingsSynchronizeVideo.setChecked();
|
||||||
settingsSynchronizeAudio.setText("Synchronize Audio");
|
settingsSynchronizeAudio.setText("Synchronize Audio");
|
||||||
settingsSynchronizeAudio.setChecked();
|
settingsSynchronizeAudio.setChecked();
|
||||||
settingsMuteAudio.setText("Mute Audio");
|
settingsMuteAudio.setText("Mute Audio");
|
||||||
@@ -67,8 +69,11 @@ MainWindow::MainWindow() {
|
|||||||
append(snesMenu);
|
append(snesMenu);
|
||||||
snesMenu.append(snesPower);
|
snesMenu.append(snesPower);
|
||||||
snesMenu.append(snesReset);
|
snesMenu.append(snesReset);
|
||||||
snesMenu.append(snesSeparator);
|
snesMenu.append(snesSeparator1);
|
||||||
snesMenu.append(snesCartridgeUnload);
|
snesMenu.append(snesCartridgeUnload);
|
||||||
|
snesMenu.append(snesSeparator2);
|
||||||
|
snesMenu.append(snesPort1);
|
||||||
|
snesMenu.append(snesPort2);
|
||||||
|
|
||||||
append(gameBoyMenu);
|
append(gameBoyMenu);
|
||||||
gameBoyMenu.append(gameBoyPower);
|
gameBoyMenu.append(gameBoyPower);
|
||||||
|
@@ -16,8 +16,11 @@ struct MainWindow : Window {
|
|||||||
Menu snesMenu;
|
Menu snesMenu;
|
||||||
Item snesPower;
|
Item snesPower;
|
||||||
Item snesReset;
|
Item snesReset;
|
||||||
Separator snesSeparator;
|
Separator snesSeparator1;
|
||||||
Item snesCartridgeUnload;
|
Item snesCartridgeUnload;
|
||||||
|
Separator snesSeparator2;
|
||||||
|
Menu snesPort1;
|
||||||
|
Menu snesPort2;
|
||||||
|
|
||||||
Menu gameBoyMenu;
|
Menu gameBoyMenu;
|
||||||
Item gameBoyPower;
|
Item gameBoyPower;
|
||||||
|
52
bsnes/ui/input/gameboy.cpp
Executable file
52
bsnes/ui/input/gameboy.cpp
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
int16_t GameBoyController::poll(unsigned n) {
|
||||||
|
switch(n) {
|
||||||
|
case 0: return up.poll() & !down.poll();
|
||||||
|
case 1: return down.poll() & !up.poll();
|
||||||
|
case 2: return left.poll() & !right.poll();
|
||||||
|
case 3: return right.poll() & !left.poll();
|
||||||
|
case 4: return b.poll();
|
||||||
|
case 5: return a.poll();
|
||||||
|
case 6: return select.poll();
|
||||||
|
case 7: return start.poll();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameBoyController::GameBoyController() {
|
||||||
|
name = "Controller";
|
||||||
|
|
||||||
|
up.name = "Up";
|
||||||
|
down.name = "Down";
|
||||||
|
left.name = "Left";
|
||||||
|
right.name = "Right";
|
||||||
|
b.name = "B";
|
||||||
|
a.name = "A";
|
||||||
|
select.name = "Select";
|
||||||
|
start.name = "Start";
|
||||||
|
|
||||||
|
up.mapping = "KB0::Up";
|
||||||
|
down.mapping = "KB0::Down";
|
||||||
|
left.mapping = "KB0::Left";
|
||||||
|
right.mapping = "KB0::Right";
|
||||||
|
b.mapping = "KB0::Z";
|
||||||
|
a.mapping = "KB0::X";
|
||||||
|
select.mapping = "KB0::Apostrophe";
|
||||||
|
start.mapping = "KB0::Return";
|
||||||
|
|
||||||
|
append(up); append(down); append(left); append(right);
|
||||||
|
append(b); append(a); append(select); append(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
GameBoyDevice::GameBoyDevice() {
|
||||||
|
name = "Device";
|
||||||
|
append(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
GameBoyInput::GameBoyInput() {
|
||||||
|
name = "Game Boy";
|
||||||
|
append(device);
|
||||||
|
}
|
19
bsnes/ui/input/gameboy.hpp
Executable file
19
bsnes/ui/input/gameboy.hpp
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
struct GameBoyController : TertiaryInput {
|
||||||
|
DigitalInput up, down, left, right;
|
||||||
|
DigitalInput b, a, select, start;
|
||||||
|
|
||||||
|
int16_t poll(unsigned n);
|
||||||
|
GameBoyController();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GameBoyDevice : SecondaryInput {
|
||||||
|
GameBoyController controller;
|
||||||
|
|
||||||
|
GameBoyDevice();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GameBoyInput : PrimaryInput {
|
||||||
|
GameBoyDevice device;
|
||||||
|
|
||||||
|
GameBoyInput();
|
||||||
|
};
|
184
bsnes/ui/input/input.cpp
Executable file
184
bsnes/ui/input/input.cpp
Executable file
@@ -0,0 +1,184 @@
|
|||||||
|
#include "../base.hpp"
|
||||||
|
#include "nes.cpp"
|
||||||
|
#include "snes.cpp"
|
||||||
|
#include "gameboy.cpp"
|
||||||
|
#include "user-interface.cpp"
|
||||||
|
InputManager *inputManager = 0;
|
||||||
|
|
||||||
|
void AbstractInput::attach(const string &primaryName, const string &secondaryName, const string &tertiaryName) {
|
||||||
|
string name = { primaryName, "::", secondaryName, "::", tertiaryName, "::", this->name };
|
||||||
|
name.replace(" ", "");
|
||||||
|
inputManager->config.attach(mapping, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractInput::bind() {
|
||||||
|
if(mapping.endswith(".Up")) type = Type::HatUp;
|
||||||
|
else if(mapping.endswith(".Down")) type = Type::HatDown;
|
||||||
|
else if(mapping.endswith(".Left")) type = Type::HatLeft;
|
||||||
|
else if(mapping.endswith(".Right")) type = Type::HatRight;
|
||||||
|
else if(mapping.endswith(".Lo")) type = Type::AxisLo;
|
||||||
|
else if(mapping.endswith(".Hi")) type = Type::AxisHi;
|
||||||
|
else if(mapping.beginswith("JP") && mapping.position("Axis")) type = Type::Axis;
|
||||||
|
else if(mapping.beginswith("MS") && mapping.endswith("axis")) type = Type::Axis;
|
||||||
|
else type = Type::Button;
|
||||||
|
|
||||||
|
string decode = mapping;
|
||||||
|
if(auto position = decode.position(".")) decode[position()] = 0;
|
||||||
|
scancode = Scancode::decode(decode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t AbstractInput::poll() {
|
||||||
|
return inputManager->scancode[inputManager->activeScancode][scancode];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool AnalogInput::bind(int16_t scancode, int16_t value) {
|
||||||
|
string encode = Scancode::encode(scancode);
|
||||||
|
|
||||||
|
if(Mouse::isAnyAxis(scancode)) {
|
||||||
|
for(unsigned n = 0; n < Mouse::Count; n++) {
|
||||||
|
if(scancode == mouse(n)[Mouse::Xaxis]) { encode.append(".Xaxis"); goto bind; }
|
||||||
|
if(scancode == mouse(n)[Mouse::Yaxis]) { encode.append(".Yaxis"); goto bind; }
|
||||||
|
if(scancode == mouse(n)[Mouse::Zaxis]) { encode.append(".Zaxis"); goto bind; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Joypad::isAnyAxis(scancode)) {
|
||||||
|
goto bind;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bind:
|
||||||
|
mapping = encode;
|
||||||
|
this->scancode = scancode;
|
||||||
|
this->type = Type::Axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool DigitalInput::bind(int16_t scancode, int16_t value) {
|
||||||
|
string encode = Scancode::encode(scancode);
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
if(Keyboard::isAnyKey(scancode) || Keyboard::isAnyModifier(scancode) || Joypad::isAnyButton(scancode)) {
|
||||||
|
if(value == 0) return false;
|
||||||
|
type = Type::Button;
|
||||||
|
goto bind;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Joypad::isAnyHat(scancode)) {
|
||||||
|
if(value & Joypad::HatUp ) { type = Type::HatUp; encode.append(".Up" ); goto bind; }
|
||||||
|
if(value & Joypad::HatDown ) { type = Type::HatDown; encode.append(".Down" ); goto bind; }
|
||||||
|
if(value & Joypad::HatLeft ) { type = Type::HatLeft; encode.append(".Left" ); goto bind; }
|
||||||
|
if(value & Joypad::HatRight) { type = Type::HatRight; encode.append(".Right"); goto bind; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Joypad::isAnyAxis(scancode)) {
|
||||||
|
if(value < -12288) { type = Type::AxisLo; encode.append(".Lo"); goto bind; }
|
||||||
|
if(value > +24576) { type = Type::AxisHi; encode.append(".Hi"); goto bind; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bind:
|
||||||
|
mapping = encode;
|
||||||
|
this->scancode = scancode;
|
||||||
|
this->type = type;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t DigitalInput::poll() {
|
||||||
|
int16_t value = AbstractInput::poll();
|
||||||
|
switch(type) {
|
||||||
|
case Type::Button: return (bool)(value);
|
||||||
|
case Type::HatUp: return (bool)(value & Joypad::HatUp);
|
||||||
|
case Type::HatDown: return (bool)(value & Joypad::HatDown);
|
||||||
|
case Type::HatLeft: return (bool)(value & Joypad::HatLeft);
|
||||||
|
case Type::HatRight: return (bool)(value & Joypad::HatRight);
|
||||||
|
case Type::AxisLo: return (bool)(value < -16384);
|
||||||
|
case Type::AxisHi: return (bool)(value > +16384);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void TertiaryInput::attach(const string &primaryName, const string &secondaryName) {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).attach(primaryName, secondaryName, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TertiaryInput::bind() {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t TertiaryInput::poll(unsigned n) {
|
||||||
|
return operator[](n).poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void SecondaryInput::attach(const string &primaryName) {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).attach(primaryName, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecondaryInput::bind() {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void PrimaryInput::attach() {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).attach(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrimaryInput::bind() {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void InputManager::scan() {
|
||||||
|
activeScancode = !activeScancode;
|
||||||
|
input.poll(scancode[activeScancode]);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < Scancode::Limit; n++) {
|
||||||
|
if(scancode[!activeScancode][n] != scancode[activeScancode][n]) {
|
||||||
|
inputSettings->inputEvent(n, scancode[activeScancode][n]);
|
||||||
|
userInterface.inputEvent(n, scancode[activeScancode][n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputManager::InputManager() {
|
||||||
|
inputManager = this;
|
||||||
|
|
||||||
|
inputList.append(nes);
|
||||||
|
inputList.append(snes);
|
||||||
|
inputList.append(gameBoy);
|
||||||
|
inputList.append(userInterface);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < inputList.size(); n++) inputList[n].attach();
|
||||||
|
config.load(string{ application->userpath, "input.cfg" });
|
||||||
|
config.save(string{ application->userpath, "input.cfg" });
|
||||||
|
for(unsigned n = 0; n < inputList.size(); n++) inputList[n].bind();
|
||||||
|
|
||||||
|
activeScancode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputManager::~InputManager() {
|
||||||
|
config.save(string{ application->userpath, "input.cfg" });
|
||||||
|
}
|
65
bsnes/ui/input/input.hpp
Executable file
65
bsnes/ui/input/input.hpp
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
struct AbstractInput {
|
||||||
|
enum class Type : unsigned { Button, Axis, HatUp, HatDown, HatLeft, HatRight, AxisLo, AxisHi } type;
|
||||||
|
string name;
|
||||||
|
string mapping;
|
||||||
|
unsigned scancode;
|
||||||
|
|
||||||
|
virtual void attach(const string &primaryName, const string &secondaryName, const string &tertiaryName);
|
||||||
|
virtual void bind();
|
||||||
|
virtual bool bind(int16_t scancode, int16_t value) = 0;
|
||||||
|
virtual int16_t poll();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnalogInput : AbstractInput {
|
||||||
|
bool bind(int16_t scancode, int16_t value);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DigitalInput : AbstractInput {
|
||||||
|
bool bind(int16_t scancode, int16_t value);
|
||||||
|
int16_t poll();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TertiaryInput : reference_array<AbstractInput&> {
|
||||||
|
string name;
|
||||||
|
|
||||||
|
virtual void attach(const string &primaryName, const string &secondaryName);
|
||||||
|
virtual void bind();
|
||||||
|
virtual int16_t poll(unsigned n);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SecondaryInput : reference_array<TertiaryInput&> {
|
||||||
|
string name;
|
||||||
|
|
||||||
|
virtual void attach(const string &primaryName);
|
||||||
|
virtual void bind();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PrimaryInput : reference_array<SecondaryInput&> {
|
||||||
|
string name;
|
||||||
|
|
||||||
|
virtual void attach();
|
||||||
|
virtual void bind();
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "nes.hpp"
|
||||||
|
#include "snes.hpp"
|
||||||
|
#include "gameboy.hpp"
|
||||||
|
#include "user-interface.hpp"
|
||||||
|
|
||||||
|
struct InputManager {
|
||||||
|
configuration config;
|
||||||
|
int16_t scancode[2][Scancode::Limit];
|
||||||
|
bool activeScancode;
|
||||||
|
|
||||||
|
reference_array<PrimaryInput&> inputList;
|
||||||
|
NesInput nes;
|
||||||
|
SnesInput snes;
|
||||||
|
GameBoyInput gameBoy;
|
||||||
|
UserInterfaceInput userInterface;
|
||||||
|
|
||||||
|
void scan();
|
||||||
|
InputManager();
|
||||||
|
~InputManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern InputManager *inputManager;
|
60
bsnes/ui/input/nes.cpp
Executable file
60
bsnes/ui/input/nes.cpp
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
int16_t NesGamepad::poll(unsigned n) {
|
||||||
|
switch(n) {
|
||||||
|
case 0: return b.poll();
|
||||||
|
case 1: return a.poll();
|
||||||
|
case 2: return select.poll();
|
||||||
|
case 3: return start.poll();
|
||||||
|
case 4: return up.poll() & !down.poll();
|
||||||
|
case 5: return down.poll() & !up.poll();
|
||||||
|
case 6: return left.poll() & !right.poll();
|
||||||
|
case 7: return right.poll() & !left.poll();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NesGamepad::NesGamepad() {
|
||||||
|
name = "Gamepad";
|
||||||
|
|
||||||
|
up.name = "Up";
|
||||||
|
down.name = "Down";
|
||||||
|
left.name = "Left";
|
||||||
|
right.name = "Right";
|
||||||
|
b.name = "B";
|
||||||
|
a.name = "A";
|
||||||
|
select.name = "Select";
|
||||||
|
start.name = "Start";
|
||||||
|
|
||||||
|
up.mapping = "KB0::Up";
|
||||||
|
down.mapping = "KB0::Down";
|
||||||
|
left.mapping = "KB0::Left";
|
||||||
|
right.mapping = "KB0::Right";
|
||||||
|
b.mapping = "KB0::Z";
|
||||||
|
a.mapping = "KB0::X";
|
||||||
|
select.mapping = "KB0::Apostrophe";
|
||||||
|
start.mapping = "KB0::Return";
|
||||||
|
|
||||||
|
append(up); append(down); append(left); append(right);
|
||||||
|
append(b); append(a); append(select); append(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
NesPort1Input::NesPort1Input() {
|
||||||
|
name = "Controller Port 1";
|
||||||
|
append(gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
NesPort2Input::NesPort2Input() {
|
||||||
|
name = "Controller Port 2";
|
||||||
|
append(gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
NesInput::NesInput() {
|
||||||
|
name = "NES";
|
||||||
|
append(port1);
|
||||||
|
append(port2);
|
||||||
|
}
|
26
bsnes/ui/input/nes.hpp
Executable file
26
bsnes/ui/input/nes.hpp
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
struct NesGamepad : TertiaryInput {
|
||||||
|
DigitalInput up, down, left, right;
|
||||||
|
DigitalInput b, a, select, start;
|
||||||
|
|
||||||
|
int16_t poll(unsigned n);
|
||||||
|
NesGamepad();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NesPort1Input : SecondaryInput {
|
||||||
|
NesGamepad gamepad;
|
||||||
|
|
||||||
|
NesPort1Input();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NesPort2Input : SecondaryInput {
|
||||||
|
NesGamepad gamepad;
|
||||||
|
|
||||||
|
NesPort2Input();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NesInput : PrimaryInput {
|
||||||
|
NesPort1Input port1;
|
||||||
|
NesPort2Input port2;
|
||||||
|
|
||||||
|
NesInput();
|
||||||
|
};
|
73
bsnes/ui/input/snes.cpp
Executable file
73
bsnes/ui/input/snes.cpp
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
int16_t SnesGamepad::poll(unsigned n) {
|
||||||
|
switch((SNES::Input::JoypadID)n) {
|
||||||
|
case SNES::Input::JoypadID::Up: return up.poll() & !down.poll();
|
||||||
|
case SNES::Input::JoypadID::Down: return down.poll() & !up.poll();
|
||||||
|
case SNES::Input::JoypadID::Left: return left.poll() & !right.poll();
|
||||||
|
case SNES::Input::JoypadID::Right: return right.poll() & !left.poll();
|
||||||
|
case SNES::Input::JoypadID::B: return b.poll();
|
||||||
|
case SNES::Input::JoypadID::A: return a.poll();
|
||||||
|
case SNES::Input::JoypadID::Y: return y.poll();
|
||||||
|
case SNES::Input::JoypadID::X: return x.poll();
|
||||||
|
case SNES::Input::JoypadID::L: return l.poll();
|
||||||
|
case SNES::Input::JoypadID::R: return r.poll();
|
||||||
|
case SNES::Input::JoypadID::Select: return select.poll();
|
||||||
|
case SNES::Input::JoypadID::Start: return start.poll();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SnesGamepad::SnesGamepad() {
|
||||||
|
name = "Gamepad";
|
||||||
|
|
||||||
|
up.name = "Up";
|
||||||
|
down.name = "Down";
|
||||||
|
left.name = "Left";
|
||||||
|
right.name = "Right";
|
||||||
|
b.name = "B";
|
||||||
|
a.name = "A";
|
||||||
|
y.name = "Y";
|
||||||
|
x.name = "X";
|
||||||
|
l.name = "L";
|
||||||
|
r.name = "R";
|
||||||
|
select.name = "Select";
|
||||||
|
start.name = "Start";
|
||||||
|
|
||||||
|
up.mapping = "KB0::Up";
|
||||||
|
down.mapping = "KB0::Down";
|
||||||
|
left.mapping = "KB0::Left";
|
||||||
|
right.mapping = "KB0::Right";
|
||||||
|
b.mapping = "KB0::Z";
|
||||||
|
a.mapping = "KB0::X";
|
||||||
|
y.mapping = "KB0::A";
|
||||||
|
x.mapping = "KB0::S";
|
||||||
|
l.mapping = "KB0::D";
|
||||||
|
r.mapping = "KB0::C";
|
||||||
|
select.mapping = "KB0::Apostrophe";
|
||||||
|
start.mapping = "KB0::Return";
|
||||||
|
|
||||||
|
append(up); append(down); append(left); append(right);
|
||||||
|
append(b); append(a); append(y); append(x);
|
||||||
|
append(l); append(r); append(select); append(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
SnesPort1Input::SnesPort1Input() {
|
||||||
|
name = "Controller Port 1";
|
||||||
|
append(gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
SnesPort2Input::SnesPort2Input() {
|
||||||
|
name = "Controller Port 2";
|
||||||
|
append(gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
SnesInput::SnesInput() {
|
||||||
|
name = "SNES";
|
||||||
|
append(port1);
|
||||||
|
append(port2);
|
||||||
|
}
|
27
bsnes/ui/input/snes.hpp
Executable file
27
bsnes/ui/input/snes.hpp
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
struct SnesGamepad : TertiaryInput {
|
||||||
|
DigitalInput up, down, left, right;
|
||||||
|
DigitalInput b, a, y, x;
|
||||||
|
DigitalInput l, r, select, start;
|
||||||
|
|
||||||
|
int16_t poll(unsigned n);
|
||||||
|
SnesGamepad();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SnesPort1Input : SecondaryInput {
|
||||||
|
SnesGamepad gamepad;
|
||||||
|
|
||||||
|
SnesPort1Input();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SnesPort2Input : SecondaryInput {
|
||||||
|
SnesGamepad gamepad;
|
||||||
|
|
||||||
|
SnesPort2Input();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SnesInput : PrimaryInput {
|
||||||
|
SnesPort1Input port1;
|
||||||
|
SnesPort2Input port2;
|
||||||
|
|
||||||
|
SnesInput();
|
||||||
|
};
|
53
bsnes/ui/input/user-interface.cpp
Executable file
53
bsnes/ui/input/user-interface.cpp
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
void HotkeyGeneral::inputEvent(int16_t scancode, int16_t value) {
|
||||||
|
if(scancode == toggleFullScreen.scancode && value) {
|
||||||
|
utility->toggleFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scancode == turboMode.scancode) {
|
||||||
|
static bool Vsync, Async;
|
||||||
|
if(value) {
|
||||||
|
Vsync = any_cast<bool>(video.get(Video::Synchronize));
|
||||||
|
Async = any_cast<bool>(audio.get(Audio::Synchronize));
|
||||||
|
video.set(Video::Synchronize, false);
|
||||||
|
audio.set(Audio::Synchronize, false);
|
||||||
|
} else {
|
||||||
|
video.set(Video::Synchronize, Vsync);
|
||||||
|
audio.set(Audio::Synchronize, Async);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HotkeyGeneral::HotkeyGeneral() {
|
||||||
|
name = "General";
|
||||||
|
|
||||||
|
toggleFullScreen.name = "Toggle Fullscreen";
|
||||||
|
turboMode.name = "Turbo Mode";
|
||||||
|
|
||||||
|
toggleFullScreen.mapping = "KB0::F11";
|
||||||
|
turboMode.mapping = "KB0::Tilde";
|
||||||
|
|
||||||
|
append(toggleFullScreen);
|
||||||
|
append(turboMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void HotkeyInput::inputEvent(int16_t scancode, int16_t value) {
|
||||||
|
general.inputEvent(scancode, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
HotkeyInput::HotkeyInput() {
|
||||||
|
name = "Hotkeys";
|
||||||
|
append(general);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void UserInterfaceInput::inputEvent(int16_t scancode, int16_t value) {
|
||||||
|
hotkey.inputEvent(scancode, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInterfaceInput::UserInterfaceInput() {
|
||||||
|
name = "User Interface";
|
||||||
|
append(hotkey);
|
||||||
|
}
|
21
bsnes/ui/input/user-interface.hpp
Executable file
21
bsnes/ui/input/user-interface.hpp
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
struct HotkeyGeneral : TertiaryInput {
|
||||||
|
DigitalInput toggleFullScreen;
|
||||||
|
DigitalInput turboMode;
|
||||||
|
|
||||||
|
void inputEvent(int16_t scancode, int16_t value);
|
||||||
|
HotkeyGeneral();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotkeyInput : SecondaryInput {
|
||||||
|
HotkeyGeneral general;
|
||||||
|
|
||||||
|
void inputEvent(int16_t scancode, int16_t value);
|
||||||
|
HotkeyInput();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UserInterfaceInput : PrimaryInput {
|
||||||
|
HotkeyInput hotkey;
|
||||||
|
|
||||||
|
void inputEvent(int16_t scancode, int16_t value);
|
||||||
|
UserInterfaceInput();
|
||||||
|
};
|
@@ -62,16 +62,5 @@ void InterfaceGameBoy::audioSample(int16_t csample, int16_t lsample, int16_t rsa
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InterfaceGameBoy::inputPoll(unsigned id) {
|
bool InterfaceGameBoy::inputPoll(unsigned id) {
|
||||||
switch((GameBoy::Input)id) {
|
return inputManager->gameBoy.device.controller.poll(id);
|
||||||
case GameBoy::Input::Up: return interface->inputState[keyboard(0)[Keyboard::Up]];
|
|
||||||
case GameBoy::Input::Down: return interface->inputState[keyboard(0)[Keyboard::Down]];
|
|
||||||
case GameBoy::Input::Left: return interface->inputState[keyboard(0)[Keyboard::Left]];
|
|
||||||
case GameBoy::Input::Right: return interface->inputState[keyboard(0)[Keyboard::Right]];
|
|
||||||
case GameBoy::Input::B: return interface->inputState[keyboard(0)[Keyboard::Z]];
|
|
||||||
case GameBoy::Input::A: return interface->inputState[keyboard(0)[Keyboard::X]];
|
|
||||||
case GameBoy::Input::Select: return interface->inputState[keyboard(0)[Keyboard::Apostrophe]];
|
|
||||||
case GameBoy::Input::Start: return interface->inputState[keyboard(0)[Keyboard::Return]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
@@ -149,13 +149,6 @@ Interface::Interface() {
|
|||||||
//internal
|
//internal
|
||||||
|
|
||||||
void Interface::input_poll() {
|
void Interface::input_poll() {
|
||||||
bool fullScreen = inputState[keyboard(0)[Keyboard::F11]];
|
|
||||||
|
|
||||||
input.poll(inputState);
|
|
||||||
|
|
||||||
if(!fullScreen && inputState[keyboard(0)[Keyboard::F11]]) {
|
|
||||||
utility->toggleFullScreen();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::video_refresh() {
|
void Interface::video_refresh() {
|
||||||
|
@@ -31,7 +31,6 @@ struct Interface : property<Interface> {
|
|||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
int16_t inputState[Scancode::Limit];
|
|
||||||
void input_poll();
|
void input_poll();
|
||||||
void video_refresh();
|
void video_refresh();
|
||||||
|
|
||||||
|
@@ -45,19 +45,7 @@ void InterfaceNES::audioSample(int16_t sample) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int16_t InterfaceNES::inputPoll(bool port, unsigned device, unsigned id) {
|
int16_t InterfaceNES::inputPoll(bool port, unsigned device, unsigned id) {
|
||||||
if(port == 0 && device == 0) {
|
if(port == 0 && device == 0) return inputManager->nes.port1.gamepad.poll(id);
|
||||||
switch(id) {
|
|
||||||
case 0: return interface->inputState[keyboard(0)[Keyboard::X]];
|
|
||||||
case 1: return interface->inputState[keyboard(0)[Keyboard::Z]];
|
|
||||||
case 2: return interface->inputState[keyboard(0)[Keyboard::Apostrophe]];
|
|
||||||
case 3: return interface->inputState[keyboard(0)[Keyboard::Return]];
|
|
||||||
case 4: return interface->inputState[keyboard(0)[Keyboard::Up]];
|
|
||||||
case 5: return interface->inputState[keyboard(0)[Keyboard::Down]];
|
|
||||||
case 6: return interface->inputState[keyboard(0)[Keyboard::Left]];
|
|
||||||
case 7: return interface->inputState[keyboard(0)[Keyboard::Right]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -78,23 +78,7 @@ void InterfaceSNES::audioSample(int16_t lsample, int16_t rsample) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int16_t InterfaceSNES::inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
|
int16_t InterfaceSNES::inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
|
||||||
if(port == 0 && device == SNES::Input::Device::Joypad) {
|
if(port == 0 && device == SNES::Input::Device::Joypad) return inputManager->snes.port1.gamepad.poll(id);
|
||||||
switch((SNES::Input::JoypadID)id) {
|
|
||||||
case SNES::Input::JoypadID::Up: return interface->inputState[keyboard(0)[Keyboard::Up]];
|
|
||||||
case SNES::Input::JoypadID::Down: return interface->inputState[keyboard(0)[Keyboard::Down]];
|
|
||||||
case SNES::Input::JoypadID::Left: return interface->inputState[keyboard(0)[Keyboard::Left]];
|
|
||||||
case SNES::Input::JoypadID::Right: return interface->inputState[keyboard(0)[Keyboard::Right]];
|
|
||||||
case SNES::Input::JoypadID::B: return interface->inputState[keyboard(0)[Keyboard::Z]];
|
|
||||||
case SNES::Input::JoypadID::A: return interface->inputState[keyboard(0)[Keyboard::X]];
|
|
||||||
case SNES::Input::JoypadID::Y: return interface->inputState[keyboard(0)[Keyboard::A]];
|
|
||||||
case SNES::Input::JoypadID::X: return interface->inputState[keyboard(0)[Keyboard::S]];
|
|
||||||
case SNES::Input::JoypadID::L: return interface->inputState[keyboard(0)[Keyboard::D]];
|
|
||||||
case SNES::Input::JoypadID::R: return interface->inputState[keyboard(0)[Keyboard::C]];
|
|
||||||
case SNES::Input::JoypadID::Select: return interface->inputState[keyboard(0)[Keyboard::Apostrophe]];
|
|
||||||
case SNES::Input::JoypadID::Start: return interface->inputState[keyboard(0)[Keyboard::Return]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ Application *application = 0;
|
|||||||
nall::DSP dspaudio;
|
nall::DSP dspaudio;
|
||||||
|
|
||||||
void Application::run() {
|
void Application::run() {
|
||||||
interface->input_poll();
|
inputManager->scan();
|
||||||
|
|
||||||
if(interface->loaded() == false) {
|
if(interface->loaded() == false) {
|
||||||
usleep(20 * 1000);
|
usleep(20 * 1000);
|
||||||
@@ -22,9 +22,16 @@ Application::Application(int argc, char **argv) : quit(false) {
|
|||||||
realpath = path;
|
realpath = path;
|
||||||
unused = ::userpath(path);
|
unused = ::userpath(path);
|
||||||
userpath = path;
|
userpath = path;
|
||||||
|
#if defined(PLATFORM_WIN)
|
||||||
|
userpath.append("batch/");
|
||||||
|
#else
|
||||||
|
userpath.append(".config/batch/");
|
||||||
|
#endif
|
||||||
|
mkdir(userpath, 0755);
|
||||||
}
|
}
|
||||||
config = new Config;
|
config = new Config;
|
||||||
interface = new Interface;
|
interface = new Interface;
|
||||||
|
inputManager = new InputManager;
|
||||||
utility = new Utility;
|
utility = new Utility;
|
||||||
|
|
||||||
title = "batch";
|
title = "batch";
|
||||||
@@ -33,10 +40,12 @@ Application::Application(int argc, char **argv) : quit(false) {
|
|||||||
string videoDriver = "Direct3D", audioDriver = "XAudio2", inputDriver = "RawInput";
|
string videoDriver = "Direct3D", audioDriver = "XAudio2", inputDriver = "RawInput";
|
||||||
normalFont = "Tahoma, 8";
|
normalFont = "Tahoma, 8";
|
||||||
boldFont = "Tahoma, 8, Bold";
|
boldFont = "Tahoma, 8, Bold";
|
||||||
|
titleFont = "Tahoma, 16, Bold";
|
||||||
#else
|
#else
|
||||||
string videoDriver = "OpenGL", audioDriver = "PulseAudio", inputDriver = "SDL";
|
string videoDriver = "OpenGL", audioDriver = "PulseAudio", inputDriver = "SDL";
|
||||||
normalFont = "Sans, 8";
|
normalFont = "Sans, 8";
|
||||||
boldFont = "Sans, 8, Bold";
|
boldFont = "Sans, 8, Bold";
|
||||||
|
titleFont = "Sans, 16, Bold";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mainWindow = new MainWindow;
|
mainWindow = new MainWindow;
|
||||||
@@ -49,7 +58,7 @@ Application::Application(int argc, char **argv) : quit(false) {
|
|||||||
|
|
||||||
video.driver(videoDriver);
|
video.driver(videoDriver);
|
||||||
video.set(Video::Handle, mainWindow->viewport.handle());
|
video.set(Video::Handle, mainWindow->viewport.handle());
|
||||||
video.set(Video::Synchronize, false);
|
video.set(Video::Synchronize, true);
|
||||||
video.set(Video::Filter, 0u);
|
video.set(Video::Filter, 0u);
|
||||||
video.init();
|
video.init();
|
||||||
|
|
||||||
@@ -87,6 +96,7 @@ Application::~Application() {
|
|||||||
delete fileBrowser;
|
delete fileBrowser;
|
||||||
delete mainWindow;
|
delete mainWindow;
|
||||||
delete utility;
|
delete utility;
|
||||||
|
delete inputManager;
|
||||||
delete interface;
|
delete interface;
|
||||||
delete config;
|
delete config;
|
||||||
}
|
}
|
||||||
|
88
bsnes/ui/settings/input.cpp
Executable file
88
bsnes/ui/settings/input.cpp
Executable file
@@ -0,0 +1,88 @@
|
|||||||
|
InputSettings *inputSettings = 0;
|
||||||
|
|
||||||
|
InputSettings::InputSettings() : activeInput(0) {
|
||||||
|
title.setFont(application->titleFont);
|
||||||
|
title.setText("Input Settings");
|
||||||
|
inputList.setHeaderText("Name", "Mapping");
|
||||||
|
inputList.setHeaderVisible();
|
||||||
|
clearButton.setText("Clear");
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < inputManager->inputList.size(); n++) {
|
||||||
|
primary.append(inputManager->inputList[n].name);
|
||||||
|
}
|
||||||
|
primaryChange();
|
||||||
|
|
||||||
|
append(title, ~0, 0, 5);
|
||||||
|
append(selectionLayout, ~0, 0, 5);
|
||||||
|
selectionLayout.append(primary, ~0, 0, 5);
|
||||||
|
selectionLayout.append(secondary, ~0, 0, 5);
|
||||||
|
selectionLayout.append(tertiary, ~0, 0);
|
||||||
|
append(inputList, ~0, ~0, 5);
|
||||||
|
append(controlLayout, ~0, 0);
|
||||||
|
controlLayout.append(spacer, ~0, 0);
|
||||||
|
controlLayout.append(clearButton, 80, 0);
|
||||||
|
|
||||||
|
primary.onChange = { &InputSettings::primaryChange, this };
|
||||||
|
secondary.onChange = { &InputSettings::secondaryChange, this };
|
||||||
|
tertiary.onChange = { &InputSettings::tertiaryChange, this };
|
||||||
|
inputList.onChange = { &InputSettings::synchronize, this };
|
||||||
|
inputList.onActivate = { &InputSettings::assignInputBegin, this };
|
||||||
|
|
||||||
|
synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSettings::synchronize() {
|
||||||
|
clearButton.setEnabled(inputList.selected());
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSettings::primaryChange() {
|
||||||
|
secondary.reset();
|
||||||
|
tertiary.reset();
|
||||||
|
PrimaryInput &input = inputManager->inputList[primary.selection()];
|
||||||
|
for(unsigned n = 0; n < input.size(); n++) {
|
||||||
|
secondary.append(input[n].name);
|
||||||
|
}
|
||||||
|
secondaryChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSettings::secondaryChange() {
|
||||||
|
tertiary.reset();
|
||||||
|
PrimaryInput &pinput = inputManager->inputList[primary.selection()];
|
||||||
|
SecondaryInput &input = pinput[secondary.selection()];
|
||||||
|
for(unsigned n = 0; n < input.size(); n++) {
|
||||||
|
tertiary.append(input[n].name);
|
||||||
|
}
|
||||||
|
tertiaryChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSettings::tertiaryChange() {
|
||||||
|
inputList.reset();
|
||||||
|
PrimaryInput &pinput = inputManager->inputList[primary.selection()];
|
||||||
|
SecondaryInput &sinput = pinput[secondary.selection()];
|
||||||
|
TertiaryInput &input = sinput[tertiary.selection()];
|
||||||
|
for(unsigned n = 0; n < input.size(); n++) {
|
||||||
|
inputList.append(input[n].name, input[n].mapping);
|
||||||
|
}
|
||||||
|
synchronize();
|
||||||
|
inputList.autoSizeColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSettings::assignInputBegin() {
|
||||||
|
PrimaryInput &pinput = inputManager->inputList[primary.selection()];
|
||||||
|
SecondaryInput &sinput = pinput[secondary.selection()];
|
||||||
|
TertiaryInput &tinput = sinput[tertiary.selection()];
|
||||||
|
activeInput = &tinput[inputList.selection()];
|
||||||
|
|
||||||
|
settingsWindow->layout.setEnabled(false);
|
||||||
|
settingsWindow->setStatusText({ "Set asssignment for [", tinput.name, "::", activeInput->name, "] ..." });
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSettings::inputEvent(int16_t scancode, int16_t value) {
|
||||||
|
if(activeInput == 0) return;
|
||||||
|
if(activeInput->bind(scancode, value) == false) return;
|
||||||
|
|
||||||
|
activeInput = 0;
|
||||||
|
tertiaryChange();
|
||||||
|
settingsWindow->setStatusText("");
|
||||||
|
settingsWindow->layout.setEnabled(true);
|
||||||
|
}
|
25
bsnes/ui/settings/input.hpp
Executable file
25
bsnes/ui/settings/input.hpp
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
struct InputSettings : VerticalLayout {
|
||||||
|
Label title;
|
||||||
|
HorizontalLayout selectionLayout;
|
||||||
|
ComboBox primary;
|
||||||
|
ComboBox secondary;
|
||||||
|
ComboBox tertiary;
|
||||||
|
ListView inputList;
|
||||||
|
HorizontalLayout controlLayout;
|
||||||
|
Widget spacer;
|
||||||
|
Button clearButton;
|
||||||
|
|
||||||
|
InputSettings();
|
||||||
|
|
||||||
|
void synchronize();
|
||||||
|
void primaryChange();
|
||||||
|
void secondaryChange();
|
||||||
|
void tertiaryChange();
|
||||||
|
void assignInputBegin();
|
||||||
|
void inputEvent(int16_t scancode, int16_t value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AbstractInput *activeInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern InputSettings *inputSettings;
|
@@ -1,7 +1,24 @@
|
|||||||
#include "../base.hpp"
|
#include "../base.hpp"
|
||||||
|
#include "input.cpp"
|
||||||
SettingsWindow *settingsWindow = 0;
|
SettingsWindow *settingsWindow = 0;
|
||||||
|
|
||||||
SettingsWindow::SettingsWindow() {
|
SettingsWindow::SettingsWindow() {
|
||||||
setTitle("Configuration Settings");
|
setTitle("Configuration Settings");
|
||||||
setGeometry({ 128, 128, 640, 360 });
|
setGeometry({ 128, 128, 640, 360 });
|
||||||
|
setStatusFont(application->boldFont);
|
||||||
|
setStatusVisible();
|
||||||
|
|
||||||
|
panelList.append("Input");
|
||||||
|
|
||||||
|
inputSettings = new InputSettings;
|
||||||
|
|
||||||
|
append(layout);
|
||||||
|
layout.setMargin(5);
|
||||||
|
layout.append(panelList, 120, ~0, 5);
|
||||||
|
|
||||||
|
layout.append(*inputSettings, ~0, ~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsWindow::~SettingsWindow() {
|
||||||
|
delete inputSettings;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
|
#include "input.hpp"
|
||||||
|
|
||||||
struct SettingsWindow : Window {
|
struct SettingsWindow : Window {
|
||||||
|
HorizontalLayout layout;
|
||||||
|
ListView panelList;
|
||||||
|
|
||||||
SettingsWindow();
|
SettingsWindow();
|
||||||
|
~SettingsWindow();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SettingsWindow *settingsWindow;
|
extern SettingsWindow *settingsWindow;
|
||||||
|
@@ -19,7 +19,7 @@ void Utility::setMode(Interface::Mode mode) {
|
|||||||
mainWindow->setTitle({ notdir(interface->baseName), " - ", NES::Info::Name, " v", NES::Info::Version });
|
mainWindow->setTitle({ notdir(interface->baseName), " - ", NES::Info::Name, " v", NES::Info::Version });
|
||||||
mainWindow->nesMenu.setVisible(true);
|
mainWindow->nesMenu.setVisible(true);
|
||||||
dspaudio.setChannels(1);
|
dspaudio.setChannels(1);
|
||||||
dspaudio.setFrequency(315.0 / 88.8 * 6000000.0 / 12.0);
|
dspaudio.setFrequency(315.0 / 88.0 * 6000000.0 / 12.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(mode == Interface::Mode::SNES) {
|
else if(mode == Interface::Mode::SNES) {
|
||||||
|
Reference in New Issue
Block a user