mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v056 release.
This release adds a lot of new user interface features, and polishes Super Game Boy support. Note that many pixel shaders need to be coded specifically for bsnes, eg ones designed for Pete's OpenGL2 plugin will not work. I will maintain a pixelshaders archive on the bsnes download page with a collection of working shaders. Right now, there are three: HDR TV, Scale2x and HQ2x; written by guest(r) and Pete, and ported by myself. Changelog: - lowered Game Boy audio volume so that it matches SNES audio volume - fixed Super Game Boy multi-player support - fixed Super Game Boy swapped player bug - compressed Game Boy cartridges can now be loaded - added save state support for Super Game Boy games - blocked illegal Super Game Boy packets, fixes Zelda DX, Akumajou Dracula, etc palette issues - main window once again shrinks on size changes - joypads can now control the file loading window (support is very rudimentary) - cleaned up video and audio sliders, increased audio input frequency range for 59hz monitors - rewrote all of the input capture system from scratch - added dozens of additional GUI hotkey bindings to resize the main window, control synchronization, control speed, etc - it is now possible to map keyboard modifiers (shift, control, alt, super) to any input or hotkey; eg alt+enter = fullscreen - merged all input capture windows into the main settings panel - added turbo button support; hold down turbo buttons to send a 30hz input pulse - added asciiPad controller emulation; contains off/turbo/auto fire toggles and slow-motion mode - asciiPad support allows for quick switching between keyboard and gamepad input - merged scanline filter into the user interface (under Video Settings) to allow it to work on all filters; including the NTSC filter - killed off an evil QString <> string intermediary class called utf8; string class can convert to and from QString directly now - added fast BS-X, Sufami Turbo and Game Boy cartridge loading: use the filter list under "Load Cartridge" to bypass the BIOS selection screen - added pixel shader support to the OpenGL driver on Windows and Linux; note that it only really works well on Linux at the moment - added proper Vsync support to the OpenGL driver on Windows and Linux using GL extensions; again this really only works well on Linux - added unique path memory for shaders, folders, cartridges, BS-X, Sufami Turbo and Game Boy images - upgraded to Qt 4.6.0 release candidate 1; fixes an issue with the first checkbox in lists not updating when clicked
This commit is contained in:
parent
4c66de6f27
commit
66067f0015
|
@ -1,4 +1,4 @@
|
|||
static const char bsnesVersion[] = "0.055";
|
||||
static const char bsnesVersion[] = "0.056";
|
||||
static const char bsnesTitle[] = "bsnes";
|
||||
static const unsigned bsnesSaveStateVersion = 3;
|
||||
|
||||
|
|
|
@ -15,7 +15,11 @@ void SuperGameBoy::enter() {
|
|||
while(true) {
|
||||
unsigned samples = sgb_run(samplebuffer, 16);
|
||||
for(unsigned i = 0; i < samples; i++) {
|
||||
audio.coprocessor_sample(samplebuffer[i] >> 0, samplebuffer[i] >> 16);
|
||||
int16 left = samplebuffer[i] >> 0;
|
||||
int16 right = samplebuffer[i] >> 16;
|
||||
|
||||
//SNES audio is notoriously quiet; lower Game Boy samples to match SGB sound effects
|
||||
audio.coprocessor_sample(left / 3, right / 3);
|
||||
}
|
||||
scheduler.addclocks_cop(samples * 10);
|
||||
scheduler.sync_copcpu();
|
||||
|
@ -65,18 +69,19 @@ void SuperGameBoy::write(unsigned addr, uint8 data) {
|
|||
|
||||
void SuperGameBoy::init() {
|
||||
if(open("supergameboy")) {
|
||||
sgb_rom = sym("sgb_rom");
|
||||
sgb_ram = sym("sgb_ram");
|
||||
sgb_rtc = sym("sgb_rtc");
|
||||
sgb_init = sym("sgb_init");
|
||||
sgb_term = sym("sgb_term");
|
||||
sgb_power = sym("sgb_power");
|
||||
sgb_reset = sym("sgb_reset");
|
||||
sgb_row = sym("sgb_row");
|
||||
sgb_read = sym("sgb_read");
|
||||
sgb_write = sym("sgb_write");
|
||||
sgb_run = sym("sgb_run");
|
||||
sgb_save = sym("sgb_save");
|
||||
sgb_rom = sym("sgb_rom");
|
||||
sgb_ram = sym("sgb_ram");
|
||||
sgb_rtc = sym("sgb_rtc");
|
||||
sgb_init = sym("sgb_init");
|
||||
sgb_term = sym("sgb_term");
|
||||
sgb_power = sym("sgb_power");
|
||||
sgb_reset = sym("sgb_reset");
|
||||
sgb_row = sym("sgb_row");
|
||||
sgb_read = sym("sgb_read");
|
||||
sgb_write = sym("sgb_write");
|
||||
sgb_run = sym("sgb_run");
|
||||
sgb_save = sym("sgb_save");
|
||||
sgb_serialize = sym("sgb_serialize");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,4 +119,9 @@ void SuperGameBoy::unload() {
|
|||
if(sgb_term) sgb_term();
|
||||
}
|
||||
|
||||
void SuperGameBoy::serialize(serializer &s) {
|
||||
s.integer(row);
|
||||
if(sgb_serialize) sgb_serialize(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ public:
|
|||
void reset();
|
||||
void unload();
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint32_t samplebuffer[4096];
|
||||
unsigned row;
|
||||
|
@ -32,6 +34,7 @@ private:
|
|||
function<void (uint16, uint8)> sgb_write;
|
||||
function<unsigned (uint32_t*, unsigned)> sgb_run;
|
||||
function<void ()> sgb_save;
|
||||
function<void (serializer&)> sgb_serialize;
|
||||
};
|
||||
|
||||
extern SuperGameBoy supergameboy;
|
||||
|
|
|
@ -6,258 +6,381 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall {
|
||||
enum { input_none = 0 };
|
||||
|
||||
template<int number = -1> struct keyboard {
|
||||
enum {
|
||||
none = keyboard<number - 1>::limit,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
a, b, c, d, e, f, g, h, i, j, k, l, m,
|
||||
n, o, p, q, r, s, t, u, v, w, x, y, z,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
limit,
|
||||
};
|
||||
struct Keyboard;
|
||||
Keyboard& keyboard(unsigned = 0);
|
||||
|
||||
static const char KeyboardScancodeName[][64] = {
|
||||
"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
||||
"PrintScreen", "ScrollLock", "Pause", "Tilde",
|
||||
"Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0",
|
||||
"Dash", "Equal", "Backspace",
|
||||
"Insert", "Delete", "Home", "End", "PageUp", "PageDown",
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
||||
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
||||
"LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash",
|
||||
"Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0",
|
||||
"Point", "Enter", "Add", "Subtract", "Multiply", "Divide",
|
||||
"NumLock", "CapsLock",
|
||||
"Up", "Down", "Left", "Right",
|
||||
"Tab", "Return", "Spacebar", "Menu",
|
||||
"Shift", "Control", "Alt", "Super",
|
||||
};
|
||||
|
||||
struct Keyboard {
|
||||
const unsigned ID;
|
||||
enum { Base = 1 };
|
||||
enum { Count = 8, Size = 128 };
|
||||
|
||||
enum Scancode {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
PrintScreen, ScrollLock, Pause, Tilde,
|
||||
Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
|
||||
Dash, Equal, Backspace,
|
||||
Insert, Delete, Home, End, PageUp, PageDown,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M,
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
|
||||
Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
|
||||
Point, Enter, Add, Subtract, Multiply, Divide,
|
||||
NumLock, CapsLock,
|
||||
Up, Down, Left, Right,
|
||||
Tab, Return, Spacebar, Menu,
|
||||
Shift, Control, Alt, Super,
|
||||
Limit,
|
||||
};
|
||||
|
||||
template<> struct keyboard<-1> {
|
||||
enum { count = 16 };
|
||||
enum {
|
||||
none,
|
||||
escape, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
|
||||
print_screen, scroll_lock, pause, tilde,
|
||||
num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0,
|
||||
dash, equal, backspace,
|
||||
insert, delete_, home, end, page_up, page_down,
|
||||
a, b, c, d, e, f, g, h, i, j, k, l, m,
|
||||
n, o, p, q, r, s, t, u, v, w, x, y, z,
|
||||
lbracket, rbracket, backslash, semicolon, apostrophe, comma, period, slash,
|
||||
pad_1, pad_2, pad_3, pad_4, pad_5, pad_6, pad_7, pad_8, pad_9, pad_0,
|
||||
point, enter, add, subtract, multiply, divide,
|
||||
num_lock, caps_lock,
|
||||
up, down, left, right,
|
||||
tab, return_, spacebar,
|
||||
lctrl, rctrl, lalt, ralt, lshift, rshift, lsuper, rsuper, menu,
|
||||
length, //number of syms per keyboard
|
||||
limit = 0,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned keyboard_number, unsigned keyboard_enum) {
|
||||
if(keyboard_number >= count) return input_none;
|
||||
return limit + keyboard_number * length + keyboard_enum;
|
||||
static signed numberDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).belongsTo(scancode)) return i;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct mouse {
|
||||
enum { buttons = 8 };
|
||||
enum {
|
||||
none = mouse<number - 1>::limit,
|
||||
x, y, z,
|
||||
button,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct mouse<-1> {
|
||||
enum { count = 16, buttons = 8 };
|
||||
enum {
|
||||
none,
|
||||
x, y, z,
|
||||
button,
|
||||
length = button + buttons - none, //number of syms per mouse
|
||||
limit = keyboard<keyboard<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned mouse_number, unsigned mouse_enum) {
|
||||
if(mouse_number >= count) return input_none;
|
||||
return limit + mouse_number * length + mouse_enum;
|
||||
}
|
||||
};
|
||||
|
||||
template<int number = -1> struct joypad {
|
||||
enum { hats = 8, axes = 32, buttons = 96 };
|
||||
enum {
|
||||
none = joypad<number - 1>::limit,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
limit = button + buttons,
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct joypad<-1> {
|
||||
enum { count = 16, hats = 8, axes = 32, buttons = 96 };
|
||||
enum { hat_center = 0, hat_up = 1, hat_right = 2, hat_down = 4, hat_left = 8 };
|
||||
enum {
|
||||
none,
|
||||
hat,
|
||||
axis = hat + hats,
|
||||
button = axis + axes,
|
||||
length = button + buttons - none, //number of syms per joypad
|
||||
limit = mouse<mouse<>::count - 1>::limit,
|
||||
};
|
||||
|
||||
static uint16_t index(unsigned joypad_number, unsigned joypad_enum) {
|
||||
if(joypad_number >= count) return input_none;
|
||||
return limit + joypad_number * length + joypad_enum;
|
||||
}
|
||||
};
|
||||
|
||||
enum { input_limit = joypad<joypad<>::count - 1>::limit };
|
||||
|
||||
static const char keysym[][64] = {
|
||||
"none",
|
||||
"escape", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
|
||||
"print_screen", "scroll_lock", "pause", "tilde",
|
||||
"num_1", "num_2", "num_3", "num_4", "num_5", "num_6", "num_7", "num_8", "num_9", "num_0",
|
||||
"dash", "equal", "backspace",
|
||||
"insert", "delete", "home", "end", "page_up", "page_down",
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"lbracket", "rbracket", "backslash", "semicolon", "apostrophe", "comma", "period", "slash",
|
||||
"pad_1", "pad_2", "pad_3", "pad_4", "pad_5", "pad_6", "pad_7", "pad_8", "pad_9", "pad_0",
|
||||
"point", "enter", "add", "subtract", "multiply", "divide",
|
||||
"num_lock", "caps_lock",
|
||||
"up", "down", "left", "right",
|
||||
"tab", "return", "spacebar",
|
||||
"lctrl", "rctrl", "lalt", "ralt", "lshift", "rshift", "lsuper", "rsuper", "menu",
|
||||
"limit",
|
||||
};
|
||||
|
||||
static const char* input_find(uint16_t key) {
|
||||
static char buffer[64];
|
||||
|
||||
for(unsigned k = 0; k < keyboard<>::count; k++) {
|
||||
if(key >= keyboard<>::index(k, keyboard<>::none) && key < keyboard<>::index(k, keyboard<>::length)) {
|
||||
sprintf(buffer, "keyboard%.2d.%s", k, keysym[key - keyboard<>::index(k, keyboard<>::none)]);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned m = 0; m < mouse<>::count; m++) {
|
||||
if(key == mouse<>::index(m, mouse<>::x)) { sprintf(buffer, "mouse%.2d.x", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::y)) { sprintf(buffer, "mouse%.2d.y", m); return buffer; }
|
||||
if(key == mouse<>::index(m, mouse<>::z)) { sprintf(buffer, "mouse%.2d.z", m); return buffer; }
|
||||
|
||||
if(key >= mouse<>::index(m, mouse<>::button + 0)
|
||||
&& key < mouse<>::index(m, mouse<>::button + mouse<>::buttons)) {
|
||||
sprintf(buffer, "mouse%.2d.button%.2d", m, key - mouse<>::index(m, mouse<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0; j < joypad<>::count; j++) {
|
||||
if(key >= joypad<>::index(j, joypad<>::hat + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::hat + joypad<>::hats)) {
|
||||
sprintf(buffer, "joypad%.2d.hat%.2d", j, key - joypad<>::index(j, joypad<>::hat));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::axis + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::axis + joypad<>::axes)) {
|
||||
sprintf(buffer, "joypad%.2d.axis%.2d", j, key - joypad<>::index(j, joypad<>::axis));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
if(key >= joypad<>::index(j, joypad<>::button + 0)
|
||||
&& key < joypad<>::index(j, joypad<>::button + joypad<>::buttons)) {
|
||||
sprintf(buffer, "joypad%.2d.button%.2d", j, key - joypad<>::index(j, joypad<>::button));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return "none";
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char* input_find(char *out, uint16_t key) {
|
||||
strcpy(out, input_find(key));
|
||||
return out;
|
||||
static signed keyDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint16_t input_find(const char *key) {
|
||||
if(!memcmp(key, "keyboard", 8)) {
|
||||
key += 8;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t k = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(k >= keyboard<>::count) return input_none;
|
||||
key += 2;
|
||||
static signed modifierDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(*key++ != '.') return input_none;
|
||||
static bool isAnyKey(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isKey(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
if(!strcmp(key, keysym[i])) return keyboard<>::index(k, i);
|
||||
static bool isAnyModifier(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(keyboard(i).isModifier(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
string s(name);
|
||||
if(!strbegin(name, "KB")) return 0;
|
||||
ltrim(s, "KB");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == KeyboardScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string encode(uint16_t code) const {
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
|
||||
index = code - (Base + Size * i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return string() << "KB" << ID << "::" << KeyboardScancodeName[index];
|
||||
}
|
||||
|
||||
if(!memcmp(key, "mouse", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t m = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(m >= mouse<>::count) return input_none;
|
||||
key += 2;
|
||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||
uint16_t key(unsigned id) const { return Base + Size * ID + id; }
|
||||
bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); }
|
||||
bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); }
|
||||
bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); }
|
||||
|
||||
if(!strcmp(key, ".x")) return mouse<>::index(m, mouse<>::x);
|
||||
if(!strcmp(key, ".y")) return mouse<>::index(m, mouse<>::y);
|
||||
if(!strcmp(key, ".z")) return mouse<>::index(m, mouse<>::z);
|
||||
Keyboard(unsigned ID_) : ID(ID_) {}
|
||||
};
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= mouse<>::buttons) return input_none;
|
||||
return mouse<>::index(m, mouse<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
if(!memcmp(key, "joypad", 6)) {
|
||||
key += 6;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t j = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(j >= joypad<>::count) return input_none;
|
||||
key += 2;
|
||||
|
||||
if(!memcmp(key, ".hat", 4)) {
|
||||
key += 4;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t hat = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(hat >= joypad<>::hats) return input_none;
|
||||
return joypad<>::index(j, joypad<>::hat + hat);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".axis", 5)) {
|
||||
key += 5;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t axis = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(axis >= joypad<>::axes) return input_none;
|
||||
return joypad<>::index(j, joypad<>::axis + axis);
|
||||
}
|
||||
|
||||
if(!memcmp(key, ".button", 7)) {
|
||||
key += 7;
|
||||
if(!*key || !*(key + 1)) return input_none;
|
||||
uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0');
|
||||
if(button >= joypad<>::buttons) return input_none;
|
||||
return joypad<>::index(j, joypad<>::button + button);
|
||||
}
|
||||
|
||||
return input_none;
|
||||
}
|
||||
|
||||
return input_none;
|
||||
inline Keyboard& keyboard(unsigned id) {
|
||||
static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7);
|
||||
switch(id) { default:
|
||||
case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3;
|
||||
case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7;
|
||||
}
|
||||
}
|
||||
|
||||
static const char MouseScancodeName[][64] = {
|
||||
"Xaxis", "Yaxis", "Zaxis",
|
||||
"Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
|
||||
};
|
||||
|
||||
struct Mouse;
|
||||
Mouse& mouse(unsigned = 0);
|
||||
|
||||
struct Mouse {
|
||||
const unsigned ID;
|
||||
enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count };
|
||||
enum { Count = 8, Size = 16 };
|
||||
enum { Axes = 3, Buttons = 8 };
|
||||
|
||||
enum Scancode {
|
||||
Xaxis, Yaxis, Zaxis,
|
||||
Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7,
|
||||
Limit,
|
||||
};
|
||||
|
||||
static signed numberDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).belongsTo(scancode)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed axisDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed buttonDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool isAnyAxis(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isAxis(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isAnyButton(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(mouse(i).isButton(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
string s(name);
|
||||
if(!strbegin(name, "MS")) return 0;
|
||||
ltrim(s, "MS");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == MouseScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string encode(uint16_t code) const {
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
|
||||
index = code - (Base + Size * i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return string() << "MS" << ID << "::" << MouseScancodeName[index];
|
||||
}
|
||||
|
||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||
uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; }
|
||||
uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; }
|
||||
bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); }
|
||||
bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); }
|
||||
bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); }
|
||||
|
||||
Mouse(unsigned ID_) : ID(ID_) {}
|
||||
};
|
||||
|
||||
inline Mouse& mouse(unsigned id) {
|
||||
static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7);
|
||||
switch(id) { default:
|
||||
case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3;
|
||||
case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7;
|
||||
}
|
||||
}
|
||||
|
||||
static const char JoypadScancodeName[][64] = {
|
||||
"Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7",
|
||||
"Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7",
|
||||
"Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15",
|
||||
"Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
|
||||
"Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15",
|
||||
"Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23",
|
||||
"Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31",
|
||||
};
|
||||
|
||||
struct Joypad;
|
||||
Joypad& joypad(unsigned = 0);
|
||||
|
||||
struct Joypad {
|
||||
const unsigned ID;
|
||||
enum { Base = Mouse::Base + Mouse::Size * Mouse::Count };
|
||||
enum { Count = 8, Size = 64 };
|
||||
enum { Hats = 8, Axes = 16, Buttons = 32 };
|
||||
|
||||
enum Scancode {
|
||||
Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7,
|
||||
Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7,
|
||||
Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15,
|
||||
Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7,
|
||||
Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15,
|
||||
Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23,
|
||||
Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31,
|
||||
Limit,
|
||||
};
|
||||
|
||||
enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 };
|
||||
|
||||
static signed numberDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).belongsTo(scancode)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed hatDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed axisDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static signed buttonDecode(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool isAnyHat(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isHat(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isAnyAxis(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isAxis(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isAnyButton(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(joypad(i).isButton(scancode)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
string s(name);
|
||||
if(!strbegin(name, "JP")) return 0;
|
||||
ltrim(s, "JP");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == JoypadScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string encode(uint16_t code) const {
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < Count; i++) {
|
||||
if(code >= Base + Size * i && code < Base + Size * (i + 1)) {
|
||||
index = code - (Base + Size * i);
|
||||
}
|
||||
}
|
||||
return string() << "JP" << ID << "::" << JoypadScancodeName[index];
|
||||
}
|
||||
|
||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||
uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; }
|
||||
uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; }
|
||||
uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; }
|
||||
bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); }
|
||||
bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); }
|
||||
bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); }
|
||||
bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); }
|
||||
|
||||
Joypad(unsigned ID_) : ID(ID_) {}
|
||||
};
|
||||
|
||||
inline Joypad& joypad(unsigned id) {
|
||||
static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7);
|
||||
switch(id) { default:
|
||||
case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3;
|
||||
case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7;
|
||||
}
|
||||
}
|
||||
|
||||
struct Scancode {
|
||||
enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count };
|
||||
|
||||
static uint16_t decode(const char *name) {
|
||||
uint16_t code;
|
||||
code = Keyboard::decode(name);
|
||||
if(code) return code;
|
||||
code = Mouse::decode(name);
|
||||
if(code) return code;
|
||||
code = Joypad::decode(name);
|
||||
if(code) return code;
|
||||
return None;
|
||||
}
|
||||
|
||||
static string encode(uint16_t code) {
|
||||
for(unsigned i = 0; i < Keyboard::Count; i++) {
|
||||
if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code);
|
||||
}
|
||||
for(unsigned i = 0; i < Mouse::Count; i++) {
|
||||
if(mouse(i).belongsTo(code)) return mouse(i).encode(code);
|
||||
}
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(joypad(i).belongsTo(code)) return joypad(i).encode(code);
|
||||
}
|
||||
return "None";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,12 @@ namespace nall {
|
|||
|
||||
class serializer {
|
||||
public:
|
||||
enum mode_t { Load, Save, Size };
|
||||
|
||||
mode_t mode() const {
|
||||
return imode;
|
||||
}
|
||||
|
||||
const uint8_t* data() const {
|
||||
return idata;
|
||||
}
|
||||
|
@ -37,9 +43,9 @@ namespace nall {
|
|||
//this is rather dangerous, and not cross-platform safe;
|
||||
//but there is no standardized way to export FP-values
|
||||
uint8_t *p = (uint8_t*)&value;
|
||||
if(mode == Save) {
|
||||
if(imode == Save) {
|
||||
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
|
||||
} else if(mode == Load) {
|
||||
} else if(imode == Load) {
|
||||
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
|
||||
} else {
|
||||
isize += size;
|
||||
|
@ -48,12 +54,12 @@ namespace nall {
|
|||
|
||||
template<typename T> void integer(T &value) {
|
||||
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
|
||||
if(mode == Save) {
|
||||
if(imode == Save) {
|
||||
for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
|
||||
} else if(mode == Load) {
|
||||
} else if(imode == Load) {
|
||||
value = 0;
|
||||
for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3);
|
||||
} else if(mode == Size) {
|
||||
} else if(imode == Size) {
|
||||
isize += size;
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +76,7 @@ namespace nall {
|
|||
serializer& operator=(const serializer &s) {
|
||||
if(idata) delete[] idata;
|
||||
|
||||
mode = s.mode;
|
||||
imode = s.imode;
|
||||
idata = new uint8_t[s.icapacity];
|
||||
isize = s.isize;
|
||||
icapacity = s.icapacity;
|
||||
|
@ -84,20 +90,20 @@ namespace nall {
|
|||
}
|
||||
|
||||
serializer() {
|
||||
mode = Size;
|
||||
imode = Size;
|
||||
idata = 0;
|
||||
isize = 0;
|
||||
}
|
||||
|
||||
serializer(unsigned capacity) {
|
||||
mode = Save;
|
||||
imode = Save;
|
||||
idata = new uint8_t[capacity]();
|
||||
isize = 0;
|
||||
icapacity = capacity;
|
||||
}
|
||||
|
||||
serializer(const uint8_t *data, unsigned capacity) {
|
||||
mode = Load;
|
||||
imode = Load;
|
||||
idata = new uint8_t[capacity];
|
||||
isize = 0;
|
||||
icapacity = capacity;
|
||||
|
@ -109,7 +115,7 @@ namespace nall {
|
|||
}
|
||||
|
||||
private:
|
||||
enum mode_t { Load, Save, Size } mode;
|
||||
mode_t imode;
|
||||
uint8_t *idata;
|
||||
unsigned isize;
|
||||
unsigned icapacity;
|
||||
|
|
|
@ -80,6 +80,11 @@ namespace nall {
|
|||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
#if defined(QT_CORE_LIB)
|
||||
public:
|
||||
inline operator QString() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class lstring : public vector<string> {
|
||||
|
|
|
@ -20,6 +20,11 @@ namespace nall {
|
|||
operator[](size()).assign(to_string<T>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if defined(QT_CORE_LIB)
|
||||
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
|
||||
string::operator QString() const { return QString::fromUtf8(*this); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,129 +19,126 @@ public:
|
|||
bool acquired() { return false; }
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
KeyMap keys;
|
||||
GetKeys(keys);
|
||||
uint8_t *keymap = (uint8_t*)keys;
|
||||
|
||||
#define map(id, name) table[keyboard<0>::name] = (bool)(keymap[id >> 3] & (1 << (id & 7)))
|
||||
map(0x35, escape);
|
||||
#define map(id, name) table[keyboard(0)[name]] = (bool)(keymap[id >> 3] & (1 << (id & 7)))
|
||||
map(0x35, Keyboard::Escape);
|
||||
|
||||
map(0x7a, f1);
|
||||
map(0x78, f2);
|
||||
map(0x63, f3);
|
||||
map(0x76, f4);
|
||||
map(0x60, f5);
|
||||
map(0x61, f6);
|
||||
map(0x62, f7);
|
||||
map(0x64, f8);
|
||||
map(0x65, f9);
|
||||
map(0x6d, f10);
|
||||
map(0x67, f11);
|
||||
//map(0x??, f12);
|
||||
map(0x7a, Keyboard::F1);
|
||||
map(0x78, Keyboard::F2);
|
||||
map(0x63, Keyboard::F3);
|
||||
map(0x76, Keyboard::F4);
|
||||
map(0x60, Keyboard::F5);
|
||||
map(0x61, Keyboard::F6);
|
||||
map(0x62, Keyboard::F7);
|
||||
map(0x64, Keyboard::F8);
|
||||
map(0x65, Keyboard::F9);
|
||||
map(0x6d, Keyboard::F10);
|
||||
map(0x67, Keyboard::F11);
|
||||
//map(0x??, Keyboard::F12);
|
||||
|
||||
map(0x69, print_screen);
|
||||
//map(0x??, scroll_lock);
|
||||
map(0x71, pause);
|
||||
map(0x69, Keyboard::PrintScreen);
|
||||
//map(0x??, Keyboard::ScrollLock);
|
||||
map(0x71, Keyboard::Pause);
|
||||
|
||||
map(0x32, tilde);
|
||||
map(0x12, num_1);
|
||||
map(0x13, num_2);
|
||||
map(0x14, num_3);
|
||||
map(0x15, num_4);
|
||||
map(0x17, num_5);
|
||||
map(0x16, num_6);
|
||||
map(0x1a, num_7);
|
||||
map(0x1c, num_8);
|
||||
map(0x19, num_9);
|
||||
map(0x1d, num_0);
|
||||
map(0x32, Keyboard::Tilde);
|
||||
map(0x12, Keyboard::Num1);
|
||||
map(0x13, Keyboard::Num2);
|
||||
map(0x14, Keyboard::Num3);
|
||||
map(0x15, Keyboard::Num4);
|
||||
map(0x17, Keyboard::Num5);
|
||||
map(0x16, Keyboard::Num6);
|
||||
map(0x1a, Keyboard::Num7);
|
||||
map(0x1c, Keyboard::Num8);
|
||||
map(0x19, Keyboard::Num9);
|
||||
map(0x1d, Keyboard::Num0);
|
||||
|
||||
map(0x1b, dash);
|
||||
map(0x18, equal);
|
||||
map(0x33, backspace);
|
||||
map(0x1b, Keyboard::Dash);
|
||||
map(0x18, Keyboard::Equal);
|
||||
map(0x33, Keyboard::Backspace);
|
||||
|
||||
map(0x72, insert);
|
||||
map(0x75, delete_);
|
||||
map(0x73, home);
|
||||
map(0x77, end);
|
||||
map(0x74, page_up);
|
||||
map(0x79, page_down);
|
||||
map(0x72, Keyboard::Insert);
|
||||
map(0x75, Keyboard::Delete);
|
||||
map(0x73, Keyboard::Home);
|
||||
map(0x77, Keyboard::End);
|
||||
map(0x74, Keyboard::PageUp);
|
||||
map(0x79, Keyboard::PageDown);
|
||||
|
||||
map(0x00, a);
|
||||
map(0x0b, b);
|
||||
map(0x08, c);
|
||||
map(0x02, d);
|
||||
map(0x0e, e);
|
||||
map(0x03, f);
|
||||
map(0x05, g);
|
||||
map(0x04, h);
|
||||
map(0x22, i);
|
||||
map(0x26, j);
|
||||
map(0x28, k);
|
||||
map(0x25, l);
|
||||
map(0x2e, m);
|
||||
map(0x2d, n);
|
||||
map(0x1f, o);
|
||||
map(0x23, p);
|
||||
map(0x0c, q);
|
||||
map(0x0f, r);
|
||||
map(0x01, s);
|
||||
map(0x11, t);
|
||||
map(0x20, u);
|
||||
map(0x09, v);
|
||||
map(0x0d, w);
|
||||
map(0x07, x);
|
||||
map(0x10, y);
|
||||
map(0x06, z);
|
||||
map(0x00, Keyboard::A);
|
||||
map(0x0b, Keyboard::B);
|
||||
map(0x08, Keyboard::C);
|
||||
map(0x02, Keyboard::D);
|
||||
map(0x0e, Keyboard::E);
|
||||
map(0x03, Keyboard::F);
|
||||
map(0x05, Keyboard::G);
|
||||
map(0x04, Keyboard::H);
|
||||
map(0x22, Keyboard::I);
|
||||
map(0x26, Keyboard::J);
|
||||
map(0x28, Keyboard::K);
|
||||
map(0x25, Keyboard::L);
|
||||
map(0x2e, Keyboard::M);
|
||||
map(0x2d, Keyboard::N);
|
||||
map(0x1f, Keyboard::O);
|
||||
map(0x23, Keyboard::P);
|
||||
map(0x0c, Keyboard::Q);
|
||||
map(0x0f, Keyboard::R);
|
||||
map(0x01, Keyboard::S);
|
||||
map(0x11, Keyboard::T);
|
||||
map(0x20, Keyboard::U);
|
||||
map(0x09, Keyboard::V);
|
||||
map(0x0d, Keyboard::W);
|
||||
map(0x07, Keyboard::X);
|
||||
map(0x10, Keyboard::Y);
|
||||
map(0x06, Keyboard::Z);
|
||||
|
||||
map(0x21, lbracket);
|
||||
map(0x1e, rbracket);
|
||||
map(0x2a, backslash);
|
||||
map(0x29, semicolon);
|
||||
map(0x27, apostrophe);
|
||||
map(0x2b, comma);
|
||||
map(0x2f, period);
|
||||
map(0x2c, slash);
|
||||
map(0x21, Keyboard::LeftBracket);
|
||||
map(0x1e, Keyboard::RightBracket);
|
||||
map(0x2a, Keyboard::Backslash);
|
||||
map(0x29, Keyboard::Semicolon);
|
||||
map(0x27, Keyboard::Apostrophe);
|
||||
map(0x2b, Keyboard::Comma);
|
||||
map(0x2f, Keyboard::Period);
|
||||
map(0x2c, Keyboard::Slash);
|
||||
|
||||
map(0x52, pad_0);
|
||||
map(0x53, pad_1);
|
||||
map(0x54, pad_2);
|
||||
map(0x55, pad_3);
|
||||
map(0x56, pad_4);
|
||||
map(0x57, pad_5);
|
||||
map(0x58, pad_6);
|
||||
map(0x59, pad_7);
|
||||
map(0x5b, pad_8);
|
||||
map(0x5c, pad_9);
|
||||
map(0x53, Keyboard::Keypad1);
|
||||
map(0x54, Keyboard::Keypad2);
|
||||
map(0x55, Keyboard::Keypad3);
|
||||
map(0x56, Keyboard::Keypad4);
|
||||
map(0x57, Keyboard::Keypad5);
|
||||
map(0x58, Keyboard::Keypad6);
|
||||
map(0x59, Keyboard::Keypad7);
|
||||
map(0x5b, Keyboard::Keypad8);
|
||||
map(0x5c, Keyboard::Keypad9);
|
||||
map(0x52, Keyboard::Keypad0);
|
||||
|
||||
map(0x45, add);
|
||||
map(0x4e, subtract);
|
||||
map(0x43, multiply);
|
||||
map(0x4b, divide);
|
||||
map(0x4c, enter);
|
||||
//map(0x??, Keyboard::Point);
|
||||
map(0x4c, Keyboard::Enter);
|
||||
map(0x45, Keyboard::Add);
|
||||
map(0x4e, Keyboard::Subtract);
|
||||
map(0x43, Keyboard::Multiply);
|
||||
map(0x4b, Keyboard::Divide);
|
||||
|
||||
map(0x47, num_lock);
|
||||
//map(0x39, caps_lock);
|
||||
map(0x47, Keyboard::NumLock);
|
||||
//map(0x39, Keyboard::CapsLock);
|
||||
|
||||
map(0x7e, up);
|
||||
map(0x7d, down);
|
||||
map(0x7b, left);
|
||||
map(0x7c, right);
|
||||
map(0x7e, Keyboard::Up);
|
||||
map(0x7d, Keyboard::Down);
|
||||
map(0x7b, Keyboard::Left);
|
||||
map(0x7c, Keyboard::Right);
|
||||
|
||||
map(0x30, tab);
|
||||
map(0x24, return_);
|
||||
map(0x31, spacebar);
|
||||
map(0x30, Keyboard::Tab);
|
||||
map(0x24, Keyboard::Return);
|
||||
map(0x31, Keyboard::Spacebar);
|
||||
//map(0x??, Keyboard::Menu);
|
||||
|
||||
map(0x3b, lctrl);
|
||||
//map(0x3b, rctrl);
|
||||
map(0x3a, lalt);
|
||||
//map(0x3a, ralt);
|
||||
map(0x38, lshift);
|
||||
//map(0x38, rshift);
|
||||
map(0x37, lsuper);
|
||||
//map(0x37, rsuper);
|
||||
//map(0x??, menu);
|
||||
map(0x38, Keyboard::Shift);
|
||||
map(0x3b, Keyboard::Control);
|
||||
map(0x3a, Keyboard::Alt);
|
||||
map(0x37, Keyboard::Super);
|
||||
#undef map
|
||||
|
||||
return true;
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
LPDIRECTINPUT8 context;
|
||||
LPDIRECTINPUTDEVICE8 keyboard;
|
||||
LPDIRECTINPUTDEVICE8 mouse;
|
||||
LPDIRECTINPUTDEVICE8 gamepad[joypad<>::count];
|
||||
LPDIRECTINPUTDEVICE8 gamepad[Joypad::Count];
|
||||
bool mouseacquired;
|
||||
} device;
|
||||
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
}
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
//========
|
||||
//Keyboard
|
||||
|
@ -60,122 +60,122 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
table[keyboard<0>::escape] = (bool)(state[0x01] & 0x80);
|
||||
table[keyboard<0>::f1 ] = (bool)(state[0x3b] & 0x80);
|
||||
table[keyboard<0>::f2 ] = (bool)(state[0x3c] & 0x80);
|
||||
table[keyboard<0>::f3 ] = (bool)(state[0x3d] & 0x80);
|
||||
table[keyboard<0>::f4 ] = (bool)(state[0x3e] & 0x80);
|
||||
table[keyboard<0>::f5 ] = (bool)(state[0x3f] & 0x80);
|
||||
table[keyboard<0>::f6 ] = (bool)(state[0x40] & 0x80);
|
||||
table[keyboard<0>::f7 ] = (bool)(state[0x41] & 0x80);
|
||||
table[keyboard<0>::f8 ] = (bool)(state[0x42] & 0x80);
|
||||
table[keyboard<0>::f9 ] = (bool)(state[0x43] & 0x80);
|
||||
table[keyboard<0>::f10 ] = (bool)(state[0x44] & 0x80);
|
||||
table[keyboard<0>::f11 ] = (bool)(state[0x57] & 0x80);
|
||||
table[keyboard<0>::f12 ] = (bool)(state[0x58] & 0x80);
|
||||
#define key(id) table[keyboard(0)[id]]
|
||||
|
||||
table[keyboard<0>::print_screen] = (bool)(state[0xb7] & 0x80);
|
||||
table[keyboard<0>::scroll_lock ] = (bool)(state[0x46] & 0x80);
|
||||
table[keyboard<0>::pause ] = (bool)(state[0xc5] & 0x80);
|
||||
table[keyboard<0>::tilde ] = (bool)(state[0x29] & 0x80);
|
||||
key(Keyboard::Escape) = (bool)(state[0x01] & 0x80);
|
||||
key(Keyboard::F1 ) = (bool)(state[0x3b] & 0x80);
|
||||
key(Keyboard::F2 ) = (bool)(state[0x3c] & 0x80);
|
||||
key(Keyboard::F3 ) = (bool)(state[0x3d] & 0x80);
|
||||
key(Keyboard::F4 ) = (bool)(state[0x3e] & 0x80);
|
||||
key(Keyboard::F5 ) = (bool)(state[0x3f] & 0x80);
|
||||
key(Keyboard::F6 ) = (bool)(state[0x40] & 0x80);
|
||||
key(Keyboard::F7 ) = (bool)(state[0x41] & 0x80);
|
||||
key(Keyboard::F8 ) = (bool)(state[0x42] & 0x80);
|
||||
key(Keyboard::F9 ) = (bool)(state[0x43] & 0x80);
|
||||
key(Keyboard::F10 ) = (bool)(state[0x44] & 0x80);
|
||||
key(Keyboard::F11 ) = (bool)(state[0x57] & 0x80);
|
||||
key(Keyboard::F12 ) = (bool)(state[0x58] & 0x80);
|
||||
|
||||
table[keyboard<0>::num_1] = (bool)(state[0x02] & 0x80);
|
||||
table[keyboard<0>::num_2] = (bool)(state[0x03] & 0x80);
|
||||
table[keyboard<0>::num_3] = (bool)(state[0x04] & 0x80);
|
||||
table[keyboard<0>::num_4] = (bool)(state[0x05] & 0x80);
|
||||
table[keyboard<0>::num_5] = (bool)(state[0x06] & 0x80);
|
||||
table[keyboard<0>::num_6] = (bool)(state[0x07] & 0x80);
|
||||
table[keyboard<0>::num_7] = (bool)(state[0x08] & 0x80);
|
||||
table[keyboard<0>::num_8] = (bool)(state[0x09] & 0x80);
|
||||
table[keyboard<0>::num_9] = (bool)(state[0x0a] & 0x80);
|
||||
table[keyboard<0>::num_0] = (bool)(state[0x0b] & 0x80);
|
||||
key(Keyboard::PrintScreen) = (bool)(state[0xb7] & 0x80);
|
||||
key(Keyboard::ScrollLock ) = (bool)(state[0x46] & 0x80);
|
||||
key(Keyboard::Pause ) = (bool)(state[0xc5] & 0x80);
|
||||
key(Keyboard::Tilde ) = (bool)(state[0x29] & 0x80);
|
||||
|
||||
table[keyboard<0>::dash ] = (bool)(state[0x0c] & 0x80);
|
||||
table[keyboard<0>::equal ] = (bool)(state[0x0d] & 0x80);
|
||||
table[keyboard<0>::backspace] = (bool)(state[0x0e] & 0x80);
|
||||
key(Keyboard::Num1) = (bool)(state[0x02] & 0x80);
|
||||
key(Keyboard::Num2) = (bool)(state[0x03] & 0x80);
|
||||
key(Keyboard::Num3) = (bool)(state[0x04] & 0x80);
|
||||
key(Keyboard::Num4) = (bool)(state[0x05] & 0x80);
|
||||
key(Keyboard::Num5) = (bool)(state[0x06] & 0x80);
|
||||
key(Keyboard::Num6) = (bool)(state[0x07] & 0x80);
|
||||
key(Keyboard::Num7) = (bool)(state[0x08] & 0x80);
|
||||
key(Keyboard::Num8) = (bool)(state[0x09] & 0x80);
|
||||
key(Keyboard::Num9) = (bool)(state[0x0a] & 0x80);
|
||||
key(Keyboard::Num0) = (bool)(state[0x0b] & 0x80);
|
||||
|
||||
table[keyboard<0>::insert ] = (bool)(state[0xd2] & 0x80);
|
||||
table[keyboard<0>::delete_ ] = (bool)(state[0xd3] & 0x80);
|
||||
table[keyboard<0>::home ] = (bool)(state[0xc7] & 0x80);
|
||||
table[keyboard<0>::end ] = (bool)(state[0xcf] & 0x80);
|
||||
table[keyboard<0>::page_up ] = (bool)(state[0xc9] & 0x80);
|
||||
table[keyboard<0>::page_down] = (bool)(state[0xd1] & 0x80);
|
||||
key(Keyboard::Dash ) = (bool)(state[0x0c] & 0x80);
|
||||
key(Keyboard::Equal ) = (bool)(state[0x0d] & 0x80);
|
||||
key(Keyboard::Backspace) = (bool)(state[0x0e] & 0x80);
|
||||
|
||||
table[keyboard<0>::a] = (bool)(state[0x1e] & 0x80);
|
||||
table[keyboard<0>::b] = (bool)(state[0x30] & 0x80);
|
||||
table[keyboard<0>::c] = (bool)(state[0x2e] & 0x80);
|
||||
table[keyboard<0>::d] = (bool)(state[0x20] & 0x80);
|
||||
table[keyboard<0>::e] = (bool)(state[0x12] & 0x80);
|
||||
table[keyboard<0>::f] = (bool)(state[0x21] & 0x80);
|
||||
table[keyboard<0>::g] = (bool)(state[0x22] & 0x80);
|
||||
table[keyboard<0>::h] = (bool)(state[0x23] & 0x80);
|
||||
table[keyboard<0>::i] = (bool)(state[0x17] & 0x80);
|
||||
table[keyboard<0>::j] = (bool)(state[0x24] & 0x80);
|
||||
table[keyboard<0>::k] = (bool)(state[0x25] & 0x80);
|
||||
table[keyboard<0>::l] = (bool)(state[0x26] & 0x80);
|
||||
table[keyboard<0>::m] = (bool)(state[0x32] & 0x80);
|
||||
table[keyboard<0>::n] = (bool)(state[0x31] & 0x80);
|
||||
table[keyboard<0>::o] = (bool)(state[0x18] & 0x80);
|
||||
table[keyboard<0>::p] = (bool)(state[0x19] & 0x80);
|
||||
table[keyboard<0>::q] = (bool)(state[0x10] & 0x80);
|
||||
table[keyboard<0>::r] = (bool)(state[0x13] & 0x80);
|
||||
table[keyboard<0>::s] = (bool)(state[0x1f] & 0x80);
|
||||
table[keyboard<0>::t] = (bool)(state[0x14] & 0x80);
|
||||
table[keyboard<0>::u] = (bool)(state[0x16] & 0x80);
|
||||
table[keyboard<0>::v] = (bool)(state[0x2f] & 0x80);
|
||||
table[keyboard<0>::w] = (bool)(state[0x11] & 0x80);
|
||||
table[keyboard<0>::x] = (bool)(state[0x2d] & 0x80);
|
||||
table[keyboard<0>::y] = (bool)(state[0x15] & 0x80);
|
||||
table[keyboard<0>::z] = (bool)(state[0x2c] & 0x80);
|
||||
key(Keyboard::Insert ) = (bool)(state[0xd2] & 0x80);
|
||||
key(Keyboard::Delete ) = (bool)(state[0xd3] & 0x80);
|
||||
key(Keyboard::Home ) = (bool)(state[0xc7] & 0x80);
|
||||
key(Keyboard::End ) = (bool)(state[0xcf] & 0x80);
|
||||
key(Keyboard::PageUp ) = (bool)(state[0xc9] & 0x80);
|
||||
key(Keyboard::PageDown) = (bool)(state[0xd1] & 0x80);
|
||||
|
||||
table[keyboard<0>::lbracket ] = (bool)(state[0x1a] & 0x80);
|
||||
table[keyboard<0>::rbracket ] = (bool)(state[0x1b] & 0x80);
|
||||
table[keyboard<0>::backslash ] = (bool)(state[0x2b] & 0x80);
|
||||
table[keyboard<0>::semicolon ] = (bool)(state[0x27] & 0x80);
|
||||
table[keyboard<0>::apostrophe] = (bool)(state[0x28] & 0x80);
|
||||
table[keyboard<0>::comma ] = (bool)(state[0x33] & 0x80);
|
||||
table[keyboard<0>::period ] = (bool)(state[0x34] & 0x80);
|
||||
table[keyboard<0>::slash ] = (bool)(state[0x35] & 0x80);
|
||||
key(Keyboard::A) = (bool)(state[0x1e] & 0x80);
|
||||
key(Keyboard::B) = (bool)(state[0x30] & 0x80);
|
||||
key(Keyboard::C) = (bool)(state[0x2e] & 0x80);
|
||||
key(Keyboard::D) = (bool)(state[0x20] & 0x80);
|
||||
key(Keyboard::E) = (bool)(state[0x12] & 0x80);
|
||||
key(Keyboard::F) = (bool)(state[0x21] & 0x80);
|
||||
key(Keyboard::G) = (bool)(state[0x22] & 0x80);
|
||||
key(Keyboard::H) = (bool)(state[0x23] & 0x80);
|
||||
key(Keyboard::I) = (bool)(state[0x17] & 0x80);
|
||||
key(Keyboard::J) = (bool)(state[0x24] & 0x80);
|
||||
key(Keyboard::K) = (bool)(state[0x25] & 0x80);
|
||||
key(Keyboard::L) = (bool)(state[0x26] & 0x80);
|
||||
key(Keyboard::M) = (bool)(state[0x32] & 0x80);
|
||||
key(Keyboard::N) = (bool)(state[0x31] & 0x80);
|
||||
key(Keyboard::O) = (bool)(state[0x18] & 0x80);
|
||||
key(Keyboard::P) = (bool)(state[0x19] & 0x80);
|
||||
key(Keyboard::Q) = (bool)(state[0x10] & 0x80);
|
||||
key(Keyboard::R) = (bool)(state[0x13] & 0x80);
|
||||
key(Keyboard::S) = (bool)(state[0x1f] & 0x80);
|
||||
key(Keyboard::T) = (bool)(state[0x14] & 0x80);
|
||||
key(Keyboard::U) = (bool)(state[0x16] & 0x80);
|
||||
key(Keyboard::V) = (bool)(state[0x2f] & 0x80);
|
||||
key(Keyboard::W) = (bool)(state[0x11] & 0x80);
|
||||
key(Keyboard::X) = (bool)(state[0x2d] & 0x80);
|
||||
key(Keyboard::Y) = (bool)(state[0x15] & 0x80);
|
||||
key(Keyboard::Z) = (bool)(state[0x2c] & 0x80);
|
||||
|
||||
table[keyboard<0>::pad_0] = (bool)(state[0x4f] & 0x80);
|
||||
table[keyboard<0>::pad_1] = (bool)(state[0x50] & 0x80);
|
||||
table[keyboard<0>::pad_2] = (bool)(state[0x51] & 0x80);
|
||||
table[keyboard<0>::pad_3] = (bool)(state[0x4b] & 0x80);
|
||||
table[keyboard<0>::pad_4] = (bool)(state[0x4c] & 0x80);
|
||||
table[keyboard<0>::pad_5] = (bool)(state[0x4d] & 0x80);
|
||||
table[keyboard<0>::pad_6] = (bool)(state[0x47] & 0x80);
|
||||
table[keyboard<0>::pad_7] = (bool)(state[0x48] & 0x80);
|
||||
table[keyboard<0>::pad_8] = (bool)(state[0x49] & 0x80);
|
||||
table[keyboard<0>::pad_9] = (bool)(state[0x52] & 0x80);
|
||||
table[keyboard<0>::point] = (bool)(state[0x53] & 0x80);
|
||||
key(Keyboard::LeftBracket ) = (bool)(state[0x1a] & 0x80);
|
||||
key(Keyboard::RightBracket) = (bool)(state[0x1b] & 0x80);
|
||||
key(Keyboard::Backslash ) = (bool)(state[0x2b] & 0x80);
|
||||
key(Keyboard::Semicolon ) = (bool)(state[0x27] & 0x80);
|
||||
key(Keyboard::Apostrophe ) = (bool)(state[0x28] & 0x80);
|
||||
key(Keyboard::Comma ) = (bool)(state[0x33] & 0x80);
|
||||
key(Keyboard::Period ) = (bool)(state[0x34] & 0x80);
|
||||
key(Keyboard::Slash ) = (bool)(state[0x35] & 0x80);
|
||||
|
||||
table[keyboard<0>::add] = (bool)(state[0x4e] & 0x80);
|
||||
table[keyboard<0>::subtract] = (bool)(state[0x4a] & 0x80);
|
||||
table[keyboard<0>::multiply] = (bool)(state[0x37] & 0x80);
|
||||
table[keyboard<0>::divide] = (bool)(state[0xb5] & 0x80);
|
||||
table[keyboard<0>::enter] = (bool)(state[0x9c] & 0x80);
|
||||
key(Keyboard::Keypad0) = (bool)(state[0x4f] & 0x80);
|
||||
key(Keyboard::Keypad1) = (bool)(state[0x50] & 0x80);
|
||||
key(Keyboard::Keypad2) = (bool)(state[0x51] & 0x80);
|
||||
key(Keyboard::Keypad3) = (bool)(state[0x4b] & 0x80);
|
||||
key(Keyboard::Keypad4) = (bool)(state[0x4c] & 0x80);
|
||||
key(Keyboard::Keypad5) = (bool)(state[0x4d] & 0x80);
|
||||
key(Keyboard::Keypad6) = (bool)(state[0x47] & 0x80);
|
||||
key(Keyboard::Keypad7) = (bool)(state[0x48] & 0x80);
|
||||
key(Keyboard::Keypad8) = (bool)(state[0x49] & 0x80);
|
||||
key(Keyboard::Keypad9) = (bool)(state[0x52] & 0x80);
|
||||
key(Keyboard::Point ) = (bool)(state[0x53] & 0x80);
|
||||
|
||||
table[keyboard<0>::num_lock ] = (bool)(state[0x45] & 0x80);
|
||||
table[keyboard<0>::caps_lock] = (bool)(state[0x3a] & 0x80);
|
||||
key(Keyboard::Add ) = (bool)(state[0x4e] & 0x80);
|
||||
key(Keyboard::Subtract) = (bool)(state[0x4a] & 0x80);
|
||||
key(Keyboard::Multiply) = (bool)(state[0x37] & 0x80);
|
||||
key(Keyboard::Divide ) = (bool)(state[0xb5] & 0x80);
|
||||
key(Keyboard::Enter ) = (bool)(state[0x9c] & 0x80);
|
||||
|
||||
table[keyboard<0>::up ] = (bool)(state[0xc8] & 0x80);
|
||||
table[keyboard<0>::down ] = (bool)(state[0xd0] & 0x80);
|
||||
table[keyboard<0>::left ] = (bool)(state[0xcb] & 0x80);
|
||||
table[keyboard<0>::right] = (bool)(state[0xcd] & 0x80);
|
||||
key(Keyboard::NumLock ) = (bool)(state[0x45] & 0x80);
|
||||
key(Keyboard::CapsLock) = (bool)(state[0x3a] & 0x80);
|
||||
|
||||
table[keyboard<0>::tab ] = (bool)(state[0x0f] & 0x80);
|
||||
table[keyboard<0>::return_ ] = (bool)(state[0x1c] & 0x80);
|
||||
table[keyboard<0>::spacebar] = (bool)(state[0x39] & 0x80);
|
||||
key(Keyboard::Up ) = (bool)(state[0xc8] & 0x80);
|
||||
key(Keyboard::Down ) = (bool)(state[0xd0] & 0x80);
|
||||
key(Keyboard::Left ) = (bool)(state[0xcb] & 0x80);
|
||||
key(Keyboard::Right) = (bool)(state[0xcd] & 0x80);
|
||||
|
||||
table[keyboard<0>::lctrl ] = (bool)(state[0x1d] & 0x80);
|
||||
table[keyboard<0>::rctrl ] = (bool)(state[0x9d] & 0x80);
|
||||
table[keyboard<0>::lalt ] = (bool)(state[0x38] & 0x80);
|
||||
table[keyboard<0>::ralt ] = (bool)(state[0xb8] & 0x80);
|
||||
table[keyboard<0>::lshift] = (bool)(state[0x2a] & 0x80);
|
||||
table[keyboard<0>::rshift] = (bool)(state[0x36] & 0x80);
|
||||
table[keyboard<0>::lsuper] = (bool)(state[0xdb] & 0x80);
|
||||
table[keyboard<0>::rsuper] = (bool)(state[0xdc] & 0x80);
|
||||
table[keyboard<0>::menu ] = (bool)(state[0xdd] & 0x80);
|
||||
key(Keyboard::Tab ) = (bool)(state[0x0f] & 0x80);
|
||||
key(Keyboard::Return ) = (bool)(state[0x1c] & 0x80);
|
||||
key(Keyboard::Spacebar) = (bool)(state[0x39] & 0x80);
|
||||
key(Keyboard::Menu ) = (bool)(state[0xdd] & 0x80);
|
||||
|
||||
key(Keyboard::Shift ) = (bool)(state[0x2a] & 0x80) || (bool)(state[0x36] & 0x80);
|
||||
key(Keyboard::Control) = (bool)(state[0x1d] & 0x80) || (bool)(state[0x9d] & 0x80);
|
||||
key(Keyboard::Alt ) = (bool)(state[0x38] & 0x80) || (bool)(state[0xb8] & 0x80);
|
||||
key(Keyboard::Super ) = (bool)(state[0xdb] & 0x80) || (bool)(state[0xdc] & 0x80);
|
||||
|
||||
#undef key
|
||||
}
|
||||
|
||||
//=====
|
||||
|
@ -191,27 +191,26 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
table[mouse<0>::x] = state.lX;
|
||||
table[mouse<0>::y] = state.lY;
|
||||
table[mouse<0>::z] = state.lZ / WHEEL_DELTA;
|
||||
for(unsigned n = 0; n < mouse<>::buttons; n++) {
|
||||
table[mouse<0>::button + n] = (bool)state.rgbButtons[n];
|
||||
table[mouse(0).axis(0)] = state.lX;
|
||||
table[mouse(0).axis(1)] = state.lY;
|
||||
table[mouse(0).axis(2)] = state.lZ / WHEEL_DELTA;
|
||||
for(unsigned n = 0; n < Mouse::Buttons; n++) {
|
||||
table[mouse(0).button(n)] = (bool)state.rgbButtons[n];
|
||||
}
|
||||
|
||||
//on Windows, 0 = left, 1 = right, 2 = middle
|
||||
//swap middle and right buttons for consistency with Linux
|
||||
int16_t temp = table[mouse<0>::button + 1];
|
||||
table[mouse<0>::button + 1] = table[mouse<0>::button + 2];
|
||||
table[mouse<0>::button + 2] = temp;
|
||||
int16_t temp = table[mouse(0).button(1)];
|
||||
table[mouse(0).button(1)] = table[mouse(0).button(2)];
|
||||
table[mouse(0).button(2)] = temp;
|
||||
}
|
||||
|
||||
//=========
|
||||
//Joypad(s)
|
||||
//=========
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(!device.gamepad[i]) continue;
|
||||
unsigned index = joypad<>::index(i, joypad<>::none);
|
||||
|
||||
if(FAILED(device.gamepad[i]->Poll())) {
|
||||
device.gamepad[i]->Acquire();
|
||||
|
@ -222,30 +221,30 @@ public:
|
|||
device.gamepad[i]->GetDeviceState(sizeof(DIJOYSTATE2), &state);
|
||||
|
||||
//POV hats
|
||||
for(unsigned n = 0; n < min((unsigned)joypad<>::hats, 4); n++) {
|
||||
for(unsigned n = 0; n < min((unsigned)Joypad::Hats, 4); n++) {
|
||||
//POV value is in clockwise-hundredth degree units.
|
||||
unsigned pov = state.rgdwPOV[n];
|
||||
//some drivers report a centered POV hat as -1U, others as 65535U.
|
||||
//>= 36000 will match both, as well as invalid ranges.
|
||||
if(pov < 36000) {
|
||||
if(pov >= 31500 || pov <= 4500) table[index + joypad<>::hat + n] |= joypad<>::hat_up;
|
||||
if(pov >= 4500 && pov <= 13500) table[index + joypad<>::hat + n] |= joypad<>::hat_right;
|
||||
if(pov >= 13500 && pov <= 22500) table[index + joypad<>::hat + n] |= joypad<>::hat_down;
|
||||
if(pov >= 22500 && pov <= 31500) table[index + joypad<>::hat + n] |= joypad<>::hat_left;
|
||||
if(pov >= 31500 || pov <= 4500) table[joypad(i).hat(n)] |= Joypad::HatUp;
|
||||
if(pov >= 4500 && pov <= 13500) table[joypad(i).hat(n)] |= Joypad::HatRight;
|
||||
if(pov >= 13500 && pov <= 22500) table[joypad(i).hat(n)] |= Joypad::HatDown;
|
||||
if(pov >= 22500 && pov <= 31500) table[joypad(i).hat(n)] |= Joypad::HatLeft;
|
||||
}
|
||||
}
|
||||
|
||||
//axes
|
||||
table[index + joypad<>::axis + 0] = state.lX;
|
||||
table[index + joypad<>::axis + 1] = state.lY;
|
||||
table[index + joypad<>::axis + 2] = state.lZ;
|
||||
table[index + joypad<>::axis + 3] = state.lRx;
|
||||
table[index + joypad<>::axis + 4] = state.lRy;
|
||||
table[index + joypad<>::axis + 5] = state.lRz;
|
||||
table[joypad(i).axis(0)] = state.lX;
|
||||
table[joypad(i).axis(1)] = state.lY;
|
||||
table[joypad(i).axis(2)] = state.lZ;
|
||||
table[joypad(i).axis(3)] = state.lRx;
|
||||
table[joypad(i).axis(4)] = state.lRy;
|
||||
table[joypad(i).axis(5)] = state.lRz;
|
||||
|
||||
//buttons
|
||||
for(unsigned n = 0; n < min((unsigned)joypad<>::buttons, 128); n++) {
|
||||
table[index + joypad<>::button + n] = (bool)state.rgbButtons[n];
|
||||
for(unsigned n = 0; n < min((unsigned)Joypad::Buttons, 128); n++) {
|
||||
table[joypad(i).button(n)] = (bool)state.rgbButtons[n];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,8 +253,8 @@ public:
|
|||
|
||||
bool init_joypad(const DIDEVICEINSTANCE *instance) {
|
||||
unsigned n;
|
||||
for(n = 0; n < joypad<>::count; n++) { if(!device.gamepad[n]) break; }
|
||||
if(n >= joypad<>::count) return DIENUM_STOP;
|
||||
for(n = 0; n < Joypad::Count; n++) { if(!device.gamepad[n]) break; }
|
||||
if(n >= Joypad::Count) return DIENUM_STOP;
|
||||
|
||||
if(FAILED(device.context->CreateDevice(instance->guidInstance, &device.gamepad[n], 0))) {
|
||||
return DIENUM_CONTINUE; //continue and try next gamepad
|
||||
|
@ -270,7 +269,7 @@ public:
|
|||
|
||||
bool init_axis(const DIDEVICEOBJECTINSTANCE *instance) {
|
||||
signed n;
|
||||
for(n = joypad<>::count - 1; n >= 0; n--) { if(device.gamepad[n]) break; }
|
||||
for(n = Joypad::Count - 1; n >= 0; n--) { if(device.gamepad[n]) break; }
|
||||
if(n < 0) return DIENUM_STOP;
|
||||
|
||||
DIPROPRANGE range;
|
||||
|
@ -289,7 +288,7 @@ public:
|
|||
device.context = 0;
|
||||
device.keyboard = 0;
|
||||
device.mouse = 0;
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
|
||||
device.mouseacquired = false;
|
||||
|
||||
DirectInput8Create(GetModuleHandle(0), 0x0800, IID_IDirectInput8, (void**)&device.context, 0);
|
||||
|
@ -322,7 +321,7 @@ public:
|
|||
device.mouse = 0;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(device.gamepad[i]) {
|
||||
device.gamepad[i]->Unacquire();
|
||||
device.gamepad[i]->Release();
|
||||
|
@ -366,7 +365,7 @@ public:
|
|||
device.context = 0;
|
||||
device.keyboard = 0;
|
||||
device.mouse = 0;
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
|
||||
device.mouseacquired = false;
|
||||
|
||||
settings.handle = 0;
|
||||
|
|
|
@ -39,139 +39,151 @@ public:
|
|||
};
|
||||
|
||||
struct Keyboard : Device {
|
||||
bool state[keyboard<>::length];
|
||||
bool state[nall::Keyboard::Size];
|
||||
|
||||
void update(RAWINPUT *input) {
|
||||
unsigned code = input->data.keyboard.MakeCode;
|
||||
unsigned flags = input->data.keyboard.Flags;
|
||||
|
||||
#define map(id, flag, name) if(code == id) state[name] = (bool)(flags == flag);
|
||||
map(0x0001, 0, keyboard<>::escape)
|
||||
map(0x003b, 0, keyboard<>::f1)
|
||||
map(0x003c, 0, keyboard<>::f2)
|
||||
map(0x003d, 0, keyboard<>::f3)
|
||||
map(0x003e, 0, keyboard<>::f4)
|
||||
map(0x003f, 0, keyboard<>::f5)
|
||||
map(0x0040, 0, keyboard<>::f6)
|
||||
map(0x0041, 0, keyboard<>::f7)
|
||||
map(0x0042, 0, keyboard<>::f8)
|
||||
map(0x0043, 0, keyboard<>::f9)
|
||||
map(0x0044, 0, keyboard<>::f10)
|
||||
map(0x0057, 0, keyboard<>::f11)
|
||||
map(0x0058, 0, keyboard<>::f12)
|
||||
map(0x0001, 0, nall::Keyboard::Escape)
|
||||
map(0x003b, 0, nall::Keyboard::F1)
|
||||
map(0x003c, 0, nall::Keyboard::F2)
|
||||
map(0x003d, 0, nall::Keyboard::F3)
|
||||
map(0x003e, 0, nall::Keyboard::F4)
|
||||
map(0x003f, 0, nall::Keyboard::F5)
|
||||
map(0x0040, 0, nall::Keyboard::F6)
|
||||
map(0x0041, 0, nall::Keyboard::F7)
|
||||
map(0x0042, 0, nall::Keyboard::F8)
|
||||
map(0x0043, 0, nall::Keyboard::F9)
|
||||
map(0x0044, 0, nall::Keyboard::F10)
|
||||
map(0x0057, 0, nall::Keyboard::F11)
|
||||
map(0x0058, 0, nall::Keyboard::F12)
|
||||
|
||||
map(0x0037, 2, keyboard<>::print_screen)
|
||||
map(0x0046, 0, keyboard<>::scroll_lock)
|
||||
map(0x001d, 4, keyboard<>::pause)
|
||||
map(0x0029, 0, keyboard<>::tilde)
|
||||
map(0x0037, 2, nall::Keyboard::PrintScreen)
|
||||
map(0x0046, 0, nall::Keyboard::ScrollLock)
|
||||
map(0x001d, 4, nall::Keyboard::Pause)
|
||||
map(0x0029, 0, nall::Keyboard::Tilde)
|
||||
|
||||
map(0x0002, 0, keyboard<>::num_1)
|
||||
map(0x0003, 0, keyboard<>::num_2)
|
||||
map(0x0004, 0, keyboard<>::num_3)
|
||||
map(0x0005, 0, keyboard<>::num_4)
|
||||
map(0x0006, 0, keyboard<>::num_5)
|
||||
map(0x0007, 0, keyboard<>::num_6)
|
||||
map(0x0008, 0, keyboard<>::num_7)
|
||||
map(0x0009, 0, keyboard<>::num_8)
|
||||
map(0x000a, 0, keyboard<>::num_9)
|
||||
map(0x000b, 0, keyboard<>::num_0)
|
||||
map(0x0002, 0, nall::Keyboard::Num1)
|
||||
map(0x0003, 0, nall::Keyboard::Num2)
|
||||
map(0x0004, 0, nall::Keyboard::Num3)
|
||||
map(0x0005, 0, nall::Keyboard::Num4)
|
||||
map(0x0006, 0, nall::Keyboard::Num5)
|
||||
map(0x0007, 0, nall::Keyboard::Num6)
|
||||
map(0x0008, 0, nall::Keyboard::Num7)
|
||||
map(0x0009, 0, nall::Keyboard::Num8)
|
||||
map(0x000a, 0, nall::Keyboard::Num9)
|
||||
map(0x000b, 0, nall::Keyboard::Num0)
|
||||
|
||||
map(0x000c, 0, keyboard<>::dash)
|
||||
map(0x000d, 0, keyboard<>::equal)
|
||||
map(0x000e, 0, keyboard<>::backspace)
|
||||
map(0x000c, 0, nall::Keyboard::Dash)
|
||||
map(0x000d, 0, nall::Keyboard::Equal)
|
||||
map(0x000e, 0, nall::Keyboard::Backspace)
|
||||
|
||||
map(0x0052, 2, keyboard<>::insert)
|
||||
map(0x0053, 2, keyboard<>::delete_)
|
||||
map(0x0047, 2, keyboard<>::home)
|
||||
map(0x004f, 2, keyboard<>::end)
|
||||
map(0x0049, 2, keyboard<>::page_up)
|
||||
map(0x0051, 2, keyboard<>::page_down)
|
||||
map(0x0052, 2, nall::Keyboard::Insert)
|
||||
map(0x0053, 2, nall::Keyboard::Delete)
|
||||
map(0x0047, 2, nall::Keyboard::Home)
|
||||
map(0x004f, 2, nall::Keyboard::End)
|
||||
map(0x0049, 2, nall::Keyboard::PageUp)
|
||||
map(0x0051, 2, nall::Keyboard::PageDown)
|
||||
|
||||
map(0x001e, 0, keyboard<>::a)
|
||||
map(0x0030, 0, keyboard<>::b)
|
||||
map(0x002e, 0, keyboard<>::c)
|
||||
map(0x0020, 0, keyboard<>::d)
|
||||
map(0x0012, 0, keyboard<>::e)
|
||||
map(0x0021, 0, keyboard<>::f)
|
||||
map(0x0022, 0, keyboard<>::g)
|
||||
map(0x0023, 0, keyboard<>::h)
|
||||
map(0x0017, 0, keyboard<>::i)
|
||||
map(0x0024, 0, keyboard<>::j)
|
||||
map(0x0025, 0, keyboard<>::k)
|
||||
map(0x0026, 0, keyboard<>::l)
|
||||
map(0x0032, 0, keyboard<>::m)
|
||||
map(0x0031, 0, keyboard<>::n)
|
||||
map(0x0018, 0, keyboard<>::o)
|
||||
map(0x0019, 0, keyboard<>::p)
|
||||
map(0x0010, 0, keyboard<>::q)
|
||||
map(0x0013, 0, keyboard<>::r)
|
||||
map(0x001f, 0, keyboard<>::s)
|
||||
map(0x0014, 0, keyboard<>::t)
|
||||
map(0x0016, 0, keyboard<>::u)
|
||||
map(0x002f, 0, keyboard<>::v)
|
||||
map(0x0011, 0, keyboard<>::w)
|
||||
map(0x002d, 0, keyboard<>::x)
|
||||
map(0x0015, 0, keyboard<>::y)
|
||||
map(0x002c, 0, keyboard<>::z)
|
||||
map(0x001e, 0, nall::Keyboard::A)
|
||||
map(0x0030, 0, nall::Keyboard::B)
|
||||
map(0x002e, 0, nall::Keyboard::C)
|
||||
map(0x0020, 0, nall::Keyboard::D)
|
||||
map(0x0012, 0, nall::Keyboard::E)
|
||||
map(0x0021, 0, nall::Keyboard::F)
|
||||
map(0x0022, 0, nall::Keyboard::G)
|
||||
map(0x0023, 0, nall::Keyboard::H)
|
||||
map(0x0017, 0, nall::Keyboard::I)
|
||||
map(0x0024, 0, nall::Keyboard::J)
|
||||
map(0x0025, 0, nall::Keyboard::K)
|
||||
map(0x0026, 0, nall::Keyboard::L)
|
||||
map(0x0032, 0, nall::Keyboard::M)
|
||||
map(0x0031, 0, nall::Keyboard::N)
|
||||
map(0x0018, 0, nall::Keyboard::O)
|
||||
map(0x0019, 0, nall::Keyboard::P)
|
||||
map(0x0010, 0, nall::Keyboard::Q)
|
||||
map(0x0013, 0, nall::Keyboard::R)
|
||||
map(0x001f, 0, nall::Keyboard::S)
|
||||
map(0x0014, 0, nall::Keyboard::T)
|
||||
map(0x0016, 0, nall::Keyboard::U)
|
||||
map(0x002f, 0, nall::Keyboard::V)
|
||||
map(0x0011, 0, nall::Keyboard::W)
|
||||
map(0x002d, 0, nall::Keyboard::X)
|
||||
map(0x0015, 0, nall::Keyboard::Y)
|
||||
map(0x002c, 0, nall::Keyboard::Z)
|
||||
|
||||
map(0x001a, 0, keyboard<>::lbracket)
|
||||
map(0x001b, 0, keyboard<>::rbracket)
|
||||
map(0x002b, 0, keyboard<>::backslash)
|
||||
map(0x0027, 0, keyboard<>::semicolon)
|
||||
map(0x0028, 0, keyboard<>::apostrophe)
|
||||
map(0x0033, 0, keyboard<>::comma)
|
||||
map(0x0034, 0, keyboard<>::period)
|
||||
map(0x0035, 0, keyboard<>::slash)
|
||||
map(0x001a, 0, nall::Keyboard::LeftBracket)
|
||||
map(0x001b, 0, nall::Keyboard::RightBracket)
|
||||
map(0x002b, 0, nall::Keyboard::Backslash)
|
||||
map(0x0027, 0, nall::Keyboard::Semicolon)
|
||||
map(0x0028, 0, nall::Keyboard::Apostrophe)
|
||||
map(0x0033, 0, nall::Keyboard::Comma)
|
||||
map(0x0034, 0, nall::Keyboard::Period)
|
||||
map(0x0035, 0, nall::Keyboard::Slash)
|
||||
|
||||
map(0x004f, 0, keyboard<>::pad_1)
|
||||
map(0x0050, 0, keyboard<>::pad_2)
|
||||
map(0x0051, 0, keyboard<>::pad_3)
|
||||
map(0x004b, 0, keyboard<>::pad_4)
|
||||
map(0x004c, 0, keyboard<>::pad_5)
|
||||
map(0x004d, 0, keyboard<>::pad_6)
|
||||
map(0x0047, 0, keyboard<>::pad_7)
|
||||
map(0x0048, 0, keyboard<>::pad_8)
|
||||
map(0x0049, 0, keyboard<>::pad_9)
|
||||
map(0x0052, 0, keyboard<>::pad_0)
|
||||
map(0x004f, 0, nall::Keyboard::Keypad1)
|
||||
map(0x0050, 0, nall::Keyboard::Keypad2)
|
||||
map(0x0051, 0, nall::Keyboard::Keypad3)
|
||||
map(0x004b, 0, nall::Keyboard::Keypad4)
|
||||
map(0x004c, 0, nall::Keyboard::Keypad5)
|
||||
map(0x004d, 0, nall::Keyboard::Keypad6)
|
||||
map(0x0047, 0, nall::Keyboard::Keypad7)
|
||||
map(0x0048, 0, nall::Keyboard::Keypad8)
|
||||
map(0x0049, 0, nall::Keyboard::Keypad9)
|
||||
map(0x0052, 0, nall::Keyboard::Keypad0)
|
||||
|
||||
map(0x0053, 0, keyboard<>::point)
|
||||
map(0x001c, 2, keyboard<>::enter)
|
||||
map(0x004e, 0, keyboard<>::add)
|
||||
map(0x004a, 0, keyboard<>::subtract)
|
||||
map(0x0037, 0, keyboard<>::multiply)
|
||||
map(0x0035, 2, keyboard<>::divide)
|
||||
map(0x0053, 0, nall::Keyboard::Point)
|
||||
map(0x001c, 2, nall::Keyboard::Enter)
|
||||
map(0x004e, 0, nall::Keyboard::Add)
|
||||
map(0x004a, 0, nall::Keyboard::Subtract)
|
||||
map(0x0037, 0, nall::Keyboard::Multiply)
|
||||
map(0x0035, 2, nall::Keyboard::Divide)
|
||||
|
||||
map(0x0045, 0, keyboard<>::num_lock)
|
||||
map(0x003a, 0, keyboard<>::caps_lock)
|
||||
map(0x0045, 0, nall::Keyboard::NumLock)
|
||||
map(0x003a, 0, nall::Keyboard::CapsLock)
|
||||
|
||||
//pause signals 0x1d:4 + 0x45:0, whereas num_lock signals only 0x45:0.
|
||||
//this makes it impractical to detect both pause+num_lock independently.
|
||||
//workaround: always detect pause; detect num_lock only when pause is released.
|
||||
if(state[keyboard<>::pause]) state[keyboard<>::num_lock] = false;
|
||||
//Pause signals 0x1d:4 + 0x45:0, whereas NumLock signals only 0x45:0.
|
||||
//this makes it impractical to detect both Pause+NumLock independently.
|
||||
//workaround: always detect Pause; detect NumLock only when Pause is released.
|
||||
if(state[nall::Keyboard::Pause]) state[nall::Keyboard::NumLock] = false;
|
||||
|
||||
map(0x0048, 2, keyboard<>::up)
|
||||
map(0x0050, 2, keyboard<>::down)
|
||||
map(0x004b, 2, keyboard<>::left)
|
||||
map(0x004d, 2, keyboard<>::right)
|
||||
map(0x0048, 2, nall::Keyboard::Up)
|
||||
map(0x0050, 2, nall::Keyboard::Down)
|
||||
map(0x004b, 2, nall::Keyboard::Left)
|
||||
map(0x004d, 2, nall::Keyboard::Right)
|
||||
|
||||
map(0x000f, 0, keyboard<>::tab)
|
||||
map(0x001c, 0, keyboard<>::return_)
|
||||
map(0x0039, 0, keyboard<>::spacebar)
|
||||
map(0x000f, 0, nall::Keyboard::Tab)
|
||||
map(0x001c, 0, nall::Keyboard::Return)
|
||||
map(0x0039, 0, nall::Keyboard::Spacebar)
|
||||
map(0x005d, 2, nall::Keyboard::Menu)
|
||||
|
||||
map(0x001d, 0, keyboard<>::lctrl)
|
||||
map(0x001d, 2, keyboard<>::rctrl)
|
||||
map(0x0038, 0, keyboard<>::lalt)
|
||||
map(0x0038, 2, keyboard<>::ralt)
|
||||
map(0x002a, 0, keyboard<>::lshift)
|
||||
map(0x0036, 0, keyboard<>::rshift)
|
||||
map(0x005b, 2, keyboard<>::lsuper)
|
||||
map(0x005c, 2, keyboard<>::rsuper)
|
||||
map(0x005d, 2, keyboard<>::menu)
|
||||
//merge left and right modifiers to one ID
|
||||
if(code == 0x002a && flags == 0) state[nall::Keyboard::Shift] = 1; //left shift
|
||||
if(code == 0x002a && flags == 1) state[nall::Keyboard::Shift] = 0;
|
||||
if(code == 0x0036 && flags == 0) state[nall::Keyboard::Shift] = 1; //right shift
|
||||
if(code == 0x0036 && flags == 1) state[nall::Keyboard::Shift] = 0;
|
||||
|
||||
if(code == 0x001d && flags == 0) state[nall::Keyboard::Control] = 1; //left control
|
||||
if(code == 0x001d && flags == 1) state[nall::Keyboard::Control] = 0;
|
||||
if(code == 0x001d && flags == 2) state[nall::Keyboard::Control] = 1; //right control
|
||||
if(code == 0x001d && flags == 3) state[nall::Keyboard::Control] = 0;
|
||||
|
||||
if(code == 0x0038 && flags == 0) state[nall::Keyboard::Alt] = 1; //left alt
|
||||
if(code == 0x0038 && flags == 1) state[nall::Keyboard::Alt] = 0;
|
||||
if(code == 0x0038 && flags == 2) state[nall::Keyboard::Alt] = 1; //right alt
|
||||
if(code == 0x0038 && flags == 3) state[nall::Keyboard::Alt] = 0;
|
||||
|
||||
if(code == 0x005b && flags == 2) state[nall::Keyboard::Super] = 1; //left super
|
||||
if(code == 0x005b && flags == 3) state[nall::Keyboard::Super] = 0;
|
||||
if(code == 0x005c && flags == 2) state[nall::Keyboard::Super] = 1; //right super
|
||||
if(code == 0x005c && flags == 3) state[nall::Keyboard::Super] = 0;
|
||||
#undef map
|
||||
}
|
||||
|
||||
Keyboard() {
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) state[i] = false;
|
||||
for(unsigned i = 0; i < nall::Keyboard::Size; i++) state[i] = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -390,11 +402,11 @@ public:
|
|||
bool button[10];
|
||||
|
||||
void poll(XINPUT_STATE &state) {
|
||||
hat = joypad<>::hat_center;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) hat |= joypad<>::hat_up;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) hat |= joypad<>::hat_right;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) hat |= joypad<>::hat_down;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) hat |= joypad<>::hat_left;
|
||||
hat = Joypad::HatCenter;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) hat |= Joypad::HatUp;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) hat |= Joypad::HatRight;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) hat |= Joypad::HatDown;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) hat |= Joypad::HatLeft;
|
||||
|
||||
axis[0] = (int16_t)state.Gamepad.sThumbLX;
|
||||
axis[1] = (int16_t)state.Gamepad.sThumbLY;
|
||||
|
@ -426,7 +438,7 @@ public:
|
|||
}
|
||||
|
||||
Gamepad() {
|
||||
hat = joypad<>::hat_center;
|
||||
hat = Joypad::HatCenter;
|
||||
for(unsigned n = 0; n < 6; n++) axis[n] = 0;
|
||||
for(unsigned n = 0; n < 10; n++) button[n] = false;
|
||||
}
|
||||
|
@ -490,7 +502,7 @@ public:
|
|||
void poll(DIJOYSTATE2 &state) {
|
||||
//POV hats
|
||||
for(unsigned n = 0; n < 4; n++) {
|
||||
hat[n] = joypad<>::hat_center;
|
||||
hat[n] = Joypad::HatCenter;
|
||||
|
||||
//POV value is in clockwise-hundredth degree units
|
||||
unsigned pov = state.rgdwPOV[n];
|
||||
|
@ -499,10 +511,10 @@ public:
|
|||
//>= 36000 will match both, as well as invalid ranges.
|
||||
if(pov >= 36000) continue;
|
||||
|
||||
if(pov >= 31500 || pov <= 4500) hat[n] |= joypad<>::hat_up;
|
||||
if(pov >= 4500 && pov <= 13500) hat[n] |= joypad<>::hat_right;
|
||||
if(pov >= 13500 && pov <= 22500) hat[n] |= joypad<>::hat_down;
|
||||
if(pov >= 22500 && pov <= 31500) hat[n] |= joypad<>::hat_left;
|
||||
if(pov >= 31500 || pov <= 4500) hat[n] |= Joypad::HatUp;
|
||||
if(pov >= 4500 && pov <= 13500) hat[n] |= Joypad::HatRight;
|
||||
if(pov >= 13500 && pov <= 22500) hat[n] |= Joypad::HatDown;
|
||||
if(pov >= 22500 && pov <= 31500) hat[n] |= Joypad::HatLeft;
|
||||
}
|
||||
|
||||
//axes
|
||||
|
@ -521,7 +533,7 @@ public:
|
|||
|
||||
Gamepad() {
|
||||
handle = 0;
|
||||
for(unsigned n = 0; n < 4; n++) hat[n] = joypad<>::hat_center;
|
||||
for(unsigned n = 0; n < 4; n++) hat[n] = Joypad::HatCenter;
|
||||
for(unsigned n = 0; n < 6; n++) axis[n] = 0;
|
||||
for(unsigned n = 0; n < 128; n++) button[n] = false;
|
||||
}
|
||||
|
@ -672,33 +684,29 @@ public:
|
|||
}
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
WaitForSingleObject(rawinput.mutex, INFINITE);
|
||||
|
||||
//=========
|
||||
//Keyboards
|
||||
//=========
|
||||
for(unsigned i = 0; i < min(rawinput.lkeyboard.size(), (unsigned)keyboard<>::count); i++) {
|
||||
unsigned index = keyboard<>::index(i, keyboard<>::none);
|
||||
|
||||
for(unsigned n = 0; n < keyboard<>::length; n++) {
|
||||
table[index + n] = rawinput.lkeyboard[i].state[n];
|
||||
for(unsigned i = 0; i < min(rawinput.lkeyboard.size(), (unsigned)Keyboard::Count); i++) {
|
||||
for(unsigned n = 0; n < nall::Keyboard::Size; n++) {
|
||||
table[keyboard(i).key(n)] = rawinput.lkeyboard[i].state[n];
|
||||
}
|
||||
}
|
||||
|
||||
//====
|
||||
//Mice
|
||||
//====
|
||||
for(unsigned i = 0; i < min(rawinput.lmouse.size(), (unsigned)mouse<>::count); i++) {
|
||||
unsigned index = mouse<>::index(i, mouse<>::none);
|
||||
for(unsigned i = 0; i < min(rawinput.lmouse.size(), (unsigned)Mouse::Count); i++) {
|
||||
table[mouse(i).axis(0)] = rawinput.lmouse[i].xDistance;
|
||||
table[mouse(i).axis(1)] = rawinput.lmouse[i].yDistance;
|
||||
table[mouse(i).axis(2)] = rawinput.lmouse[i].zDistance;
|
||||
|
||||
table[index + mouse<>::x] = rawinput.lmouse[i].xDistance;
|
||||
table[index + mouse<>::y] = rawinput.lmouse[i].yDistance;
|
||||
table[index + mouse<>::z] = rawinput.lmouse[i].zDistance;
|
||||
|
||||
for(unsigned n = 0; n < min(5U, (unsigned)mouse<>::buttons); n++) {
|
||||
table[index + mouse<>::button + n] = (bool)(rawinput.lmouse[i].buttonState & (1 << n));
|
||||
for(unsigned n = 0; n < min(5U, (unsigned)Mouse::Buttons); n++) {
|
||||
table[mouse(i).button(n)] = (bool)(rawinput.lmouse[i].buttonState & (1 << n));
|
||||
}
|
||||
|
||||
rawinput.lmouse[i].sync();
|
||||
|
@ -713,17 +721,16 @@ public:
|
|||
//==================
|
||||
xinput.poll();
|
||||
for(unsigned i = 0; i < xinput.lgamepad.size(); i++) {
|
||||
if(joy >= joypad<>::count) break;
|
||||
unsigned index = joypad<>::index(joy++, joypad<>::none);
|
||||
if(joy >= Joypad::Count) break;
|
||||
|
||||
table[index + joypad<>::hat + 0] = xinput.lgamepad[i].hat;
|
||||
table[joypad(i).hat(0)] = xinput.lgamepad[i].hat;
|
||||
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)joypad<>::axes); axis++) {
|
||||
table[index + joypad<>::axis + axis] = xinput.lgamepad[i].axis[axis];
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) {
|
||||
table[joypad(i).axis(axis)] = xinput.lgamepad[i].axis[axis];
|
||||
}
|
||||
|
||||
for(unsigned button = 0; button < min(10U, (unsigned)joypad<>::buttons); button++) {
|
||||
table[index + joypad<>::button + button] = xinput.lgamepad[i].button[button];
|
||||
for(unsigned button = 0; button < min(10U, (unsigned)Joypad::Buttons); button++) {
|
||||
table[joypad(i).button(button)] = xinput.lgamepad[i].button[button];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,19 +739,18 @@ public:
|
|||
//=======================
|
||||
dinput.poll();
|
||||
for(unsigned i = 0; i < dinput.lgamepad.size(); i++) {
|
||||
if(joy >= joypad<>::count) break;
|
||||
unsigned index = joypad<>::index(joy++, joypad<>::none);
|
||||
if(joy >= Joypad::Count) break;
|
||||
|
||||
for(unsigned hat = 0; hat < min(4U, (unsigned)joypad<>::hats); hat++) {
|
||||
table[index + joypad<>::hat + hat] = dinput.lgamepad[i].hat[hat];
|
||||
for(unsigned hat = 0; hat < min(4U, (unsigned)Joypad::Hats); hat++) {
|
||||
table[joypad(i).hat(hat)] = dinput.lgamepad[i].hat[hat];
|
||||
}
|
||||
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)joypad<>::axes); axis++) {
|
||||
table[index + joypad<>::axis + axis] = dinput.lgamepad[i].axis[axis];
|
||||
for(unsigned axis = 0; axis < min(6U, (unsigned)Joypad::Axes); axis++) {
|
||||
table[joypad(i).axis(axis)] = dinput.lgamepad[i].axis[axis];
|
||||
}
|
||||
|
||||
for(unsigned button = 0; button < min(128U, (unsigned)joypad<>::buttons); button++) {
|
||||
table[index + joypad<>::button + button] = dinput.lgamepad[i].button[button];
|
||||
for(unsigned button = 0; button < min(128U, (unsigned)Joypad::Buttons); button++) {
|
||||
table[joypad(i).button(button)] = dinput.lgamepad[i].button[button];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ struct pInputSDL {
|
|||
Display *display;
|
||||
Window rootwindow;
|
||||
Cursor InvisibleCursor;
|
||||
SDL_Joystick *gamepad[joypad<>::count];
|
||||
SDL_Joystick *gamepad[Joypad::Count];
|
||||
|
||||
unsigned screenwidth, screenheight;
|
||||
unsigned relativex, relativey;
|
||||
|
@ -91,20 +91,13 @@ struct pInputSDL {
|
|||
}
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, nall::input_limit * sizeof(int16_t));
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
|
||||
//========
|
||||
//Keyboard
|
||||
//========
|
||||
|
||||
char state[32];
|
||||
XQueryKeymap(device.display, state);
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
uint8_t code = keycode[i];
|
||||
if(code == 0) continue; //unmapped
|
||||
table[i] = (bool)(state[code >> 3] & (1 << (code & 7)));
|
||||
}
|
||||
x_poll(table);
|
||||
|
||||
//=====
|
||||
//Mouse
|
||||
|
@ -123,56 +116,55 @@ struct pInputSDL {
|
|||
XGetWindowAttributes(device.display, settings.handle, &attributes);
|
||||
|
||||
//absolute -> relative conversion
|
||||
table[mouse<0>::x] = (int16_t)(root_x_return - device.screenwidth / 2);
|
||||
table[mouse<0>::y] = (int16_t)(root_y_return - device.screenheight / 2);
|
||||
table[mouse(0).axis(0)] = (int16_t)(root_x_return - device.screenwidth / 2);
|
||||
table[mouse(0).axis(1)] = (int16_t)(root_y_return - device.screenheight / 2);
|
||||
|
||||
if(table[mouse<0>::x] != 0 || table[mouse<0>::y] != 0) {
|
||||
if(table[mouse(0).axis(0)] != 0 || table[mouse(0).axis(1)] != 0) {
|
||||
//if mouse movement occurred, re-center mouse for next poll
|
||||
XWarpPointer(device.display, None, device.rootwindow, 0, 0, 0, 0, device.screenwidth / 2, device.screenheight / 2);
|
||||
}
|
||||
} else {
|
||||
table[mouse<0>::x] = (int16_t)(root_x_return - device.relativex);
|
||||
table[mouse<0>::y] = (int16_t)(root_y_return - device.relativey);
|
||||
table[mouse(0).axis(0)] = (int16_t)(root_x_return - device.relativex);
|
||||
table[mouse(0).axis(1)] = (int16_t)(root_y_return - device.relativey);
|
||||
|
||||
device.relativex = root_x_return;
|
||||
device.relativey = root_y_return;
|
||||
}
|
||||
|
||||
//manual device polling is limited to only five buttons ...
|
||||
table[mouse<0>::button + 0] = (bool)(mask_return & Button1Mask);
|
||||
table[mouse<0>::button + 1] = (bool)(mask_return & Button2Mask);
|
||||
table[mouse<0>::button + 2] = (bool)(mask_return & Button3Mask);
|
||||
table[mouse<0>::button + 3] = (bool)(mask_return & Button4Mask);
|
||||
table[mouse<0>::button + 4] = (bool)(mask_return & Button5Mask);
|
||||
table[mouse(0).button(0)] = (bool)(mask_return & Button1Mask);
|
||||
table[mouse(0).button(1)] = (bool)(mask_return & Button2Mask);
|
||||
table[mouse(0).button(2)] = (bool)(mask_return & Button3Mask);
|
||||
table[mouse(0).button(3)] = (bool)(mask_return & Button4Mask);
|
||||
table[mouse(0).button(4)] = (bool)(mask_return & Button5Mask);
|
||||
|
||||
//=========
|
||||
//Joypad(s)
|
||||
//=========
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(!device.gamepad[i]) continue;
|
||||
unsigned index = joypad<>::index(i, joypad<>::none);
|
||||
|
||||
//POV hats
|
||||
unsigned hats = min((unsigned)joypad<>::hats, SDL_JoystickNumHats(device.gamepad[i]));
|
||||
unsigned hats = min((unsigned)Joypad::Hats, SDL_JoystickNumHats(device.gamepad[i]));
|
||||
for(unsigned hat = 0; hat < hats; hat++) {
|
||||
uint8_t state = SDL_JoystickGetHat(device.gamepad[i], hat);
|
||||
if(state & SDL_HAT_UP ) table[index + joypad<>::hat + hat] |= joypad<>::hat_up;
|
||||
if(state & SDL_HAT_RIGHT) table[index + joypad<>::hat + hat] |= joypad<>::hat_right;
|
||||
if(state & SDL_HAT_DOWN ) table[index + joypad<>::hat + hat] |= joypad<>::hat_down;
|
||||
if(state & SDL_HAT_LEFT ) table[index + joypad<>::hat + hat] |= joypad<>::hat_left;
|
||||
if(state & SDL_HAT_UP ) table[joypad(i).hat(hat)] |= Joypad::HatUp;
|
||||
if(state & SDL_HAT_RIGHT) table[joypad(i).hat(hat)] |= Joypad::HatRight;
|
||||
if(state & SDL_HAT_DOWN ) table[joypad(i).hat(hat)] |= Joypad::HatDown;
|
||||
if(state & SDL_HAT_LEFT ) table[joypad(i).hat(hat)] |= Joypad::HatLeft;
|
||||
}
|
||||
|
||||
//axes
|
||||
unsigned axes = min((unsigned)joypad<>::axes, SDL_JoystickNumAxes(device.gamepad[i]));
|
||||
unsigned axes = min((unsigned)Joypad::Axes, SDL_JoystickNumAxes(device.gamepad[i]));
|
||||
for(unsigned axis = 0; axis < axes; axis++) {
|
||||
table[index + joypad<>::axis + axis] = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis);
|
||||
table[joypad(i).axis(axis)] = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis);
|
||||
}
|
||||
|
||||
//buttons
|
||||
for(unsigned button = 0; button < joypad<>::buttons; button++) {
|
||||
table[index + joypad<>::button + button] = (bool)SDL_JoystickGetButton(device.gamepad[i], button);
|
||||
for(unsigned button = 0; button < Joypad::Buttons; button++) {
|
||||
table[joypad(i).button(button)] = (bool)SDL_JoystickGetButton(device.gamepad[i], button);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +172,7 @@ struct pInputSDL {
|
|||
}
|
||||
|
||||
bool init() {
|
||||
init_keycodes();
|
||||
x_init();
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_JoystickEventState(SDL_IGNORE);
|
||||
|
||||
|
@ -208,7 +200,7 @@ struct pInputSDL {
|
|||
device.relativex = 0;
|
||||
device.relativey = 0;
|
||||
|
||||
unsigned joypads = min((unsigned)joypad<>::count, SDL_NumJoysticks());
|
||||
unsigned joypads = min((unsigned)Joypad::Count, SDL_NumJoysticks());
|
||||
for(unsigned i = 0; i < joypads; i++) device.gamepad[i] = SDL_JoystickOpen(i);
|
||||
|
||||
return true;
|
||||
|
@ -218,7 +210,7 @@ struct pInputSDL {
|
|||
unacquire();
|
||||
XFreeCursor(device.display, device.InvisibleCursor);
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
if(device.gamepad[i]) SDL_JoystickClose(device.gamepad[i]);
|
||||
device.gamepad[i] = 0;
|
||||
}
|
||||
|
@ -228,7 +220,7 @@ struct pInputSDL {
|
|||
}
|
||||
|
||||
pInputSDL() {
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) device.gamepad[i] = 0;
|
||||
settings.handle = 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,22 +29,13 @@ public:
|
|||
bool acquired() { return false; }
|
||||
|
||||
bool poll(int16_t *table) {
|
||||
memset(table, 0, input_limit * sizeof(int16_t));
|
||||
|
||||
char state[32];
|
||||
XQueryKeymap(display, state);
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::length; i++) {
|
||||
uint8_t code = keycode[i];
|
||||
if(code == 0) continue; //unmapped
|
||||
table[i] = (bool)(state[code >> 3] & (1 << (code & 7)));
|
||||
}
|
||||
|
||||
memset(table, 0, Scancode::Limit * sizeof(int16_t));
|
||||
x_poll(table);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init() {
|
||||
init_keycodes();
|
||||
x_init();
|
||||
display = XOpenDisplay(0);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,137 +1,263 @@
|
|||
//shared keycode lookup table + initialization routine:
|
||||
//#include inside a class interface to use
|
||||
uint8_t scancode[256];
|
||||
|
||||
//Xlib keycodes for each key can vary between platforms, so this header file
|
||||
//will lookup keycodes from static keysyms, and map them to nall/input.hpp's
|
||||
//keyboard identifiers.
|
||||
//
|
||||
//this allows input capture routine to iterate quickly over all keycodes and
|
||||
//map their states to ruby's input state table.
|
||||
enum XScancode {
|
||||
Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||
ScrollLock, Pause, Tilde,
|
||||
Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
|
||||
Dash, Equal, Backspace,
|
||||
Insert, Delete, Home, End, PageUp, PageDown,
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M,
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash,
|
||||
Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0,
|
||||
Point, Enter, Add, Subtract, Multiply, Divide,
|
||||
Up, Down, Left, Right,
|
||||
Tab, Return, Spacebar, Menu,
|
||||
LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, LeftSuper, RightSuper,
|
||||
};
|
||||
|
||||
uint8_t keycode[256];
|
||||
|
||||
void init_keycodes() {
|
||||
void x_poll(int16_t *table) {
|
||||
char state[32];
|
||||
Display *display = XOpenDisplay(0);
|
||||
memset(&keycode, 0, sizeof keycode);
|
||||
XQueryKeymap(display, state);
|
||||
XCloseDisplay(display);
|
||||
|
||||
#define assign(x, y) keycode[x] = XKeysymToKeycode(display, y)
|
||||
assign(keyboard<0>::escape, XK_Escape);
|
||||
#define key(id) table[keyboard(0)[id]]
|
||||
#define pressed(id) (bool)(state[scancode[id] >> 3] & (1 << (scancode[id] & 7)))
|
||||
|
||||
assign(keyboard<0>::f1, XK_F1);
|
||||
assign(keyboard<0>::f2, XK_F2);
|
||||
assign(keyboard<0>::f3, XK_F3);
|
||||
assign(keyboard<0>::f4, XK_F4);
|
||||
assign(keyboard<0>::f5, XK_F5);
|
||||
assign(keyboard<0>::f6, XK_F6);
|
||||
assign(keyboard<0>::f7, XK_F7);
|
||||
assign(keyboard<0>::f8, XK_F8);
|
||||
assign(keyboard<0>::f9, XK_F9);
|
||||
assign(keyboard<0>::f10, XK_F10);
|
||||
assign(keyboard<0>::f11, XK_F11);
|
||||
assign(keyboard<0>::f12, XK_F12);
|
||||
key(Keyboard::Escape) = pressed(Escape);
|
||||
|
||||
//assign(keyboard<0>::print_screen, XK_???);
|
||||
assign(keyboard<0>::scroll_lock, XK_Scroll_Lock);
|
||||
assign(keyboard<0>::pause, XK_Pause);
|
||||
key(Keyboard::F1) = pressed(F1);
|
||||
key(Keyboard::F2) = pressed(F2);
|
||||
key(Keyboard::F3) = pressed(F3);
|
||||
key(Keyboard::F4) = pressed(F4);
|
||||
key(Keyboard::F5) = pressed(F5);
|
||||
key(Keyboard::F6) = pressed(F6);
|
||||
key(Keyboard::F7) = pressed(F7);
|
||||
key(Keyboard::F8) = pressed(F8);
|
||||
key(Keyboard::F9) = pressed(F9);
|
||||
key(Keyboard::F10) = pressed(F10);
|
||||
key(Keyboard::F11) = pressed(F11);
|
||||
key(Keyboard::F12) = pressed(F12);
|
||||
|
||||
assign(keyboard<0>::tilde, XK_asciitilde);
|
||||
key(Keyboard::ScrollLock) = pressed(ScrollLock);
|
||||
key(Keyboard::Pause) = pressed(Pause);
|
||||
key(Keyboard::Tilde) = pressed(Tilde);
|
||||
|
||||
assign(keyboard<0>::num_0, XK_0);
|
||||
assign(keyboard<0>::num_1, XK_1);
|
||||
assign(keyboard<0>::num_2, XK_2);
|
||||
assign(keyboard<0>::num_3, XK_3);
|
||||
assign(keyboard<0>::num_4, XK_4);
|
||||
assign(keyboard<0>::num_5, XK_5);
|
||||
assign(keyboard<0>::num_6, XK_6);
|
||||
assign(keyboard<0>::num_7, XK_7);
|
||||
assign(keyboard<0>::num_8, XK_8);
|
||||
assign(keyboard<0>::num_9, XK_9);
|
||||
key(Keyboard::Num1) = pressed(Num1);
|
||||
key(Keyboard::Num2) = pressed(Num2);
|
||||
key(Keyboard::Num3) = pressed(Num3);
|
||||
key(Keyboard::Num4) = pressed(Num4);
|
||||
key(Keyboard::Num5) = pressed(Num5);
|
||||
key(Keyboard::Num6) = pressed(Num6);
|
||||
key(Keyboard::Num7) = pressed(Num7);
|
||||
key(Keyboard::Num8) = pressed(Num8);
|
||||
key(Keyboard::Num9) = pressed(Num9);
|
||||
key(Keyboard::Num0) = pressed(Num0);
|
||||
|
||||
assign(keyboard<0>::dash, XK_minus);
|
||||
assign(keyboard<0>::equal, XK_equal);
|
||||
assign(keyboard<0>::backspace, XK_BackSpace);
|
||||
key(Keyboard::Dash) = pressed(Dash);
|
||||
key(Keyboard::Equal) = pressed(Equal);
|
||||
key(Keyboard::Backspace) = pressed(Backspace);
|
||||
|
||||
assign(keyboard<0>::insert, XK_Insert);
|
||||
assign(keyboard<0>::delete_, XK_Delete);
|
||||
assign(keyboard<0>::home, XK_Home);
|
||||
assign(keyboard<0>::end, XK_End);
|
||||
assign(keyboard<0>::page_up, XK_Prior);
|
||||
assign(keyboard<0>::page_down, XK_Next);
|
||||
key(Keyboard::Insert) = pressed(Insert);
|
||||
key(Keyboard::Delete) = pressed(Delete);
|
||||
key(Keyboard::Home) = pressed(Home);
|
||||
key(Keyboard::End) = pressed(End);
|
||||
key(Keyboard::PageUp) = pressed(PageUp);
|
||||
key(Keyboard::PageDown) = pressed(PageDown);
|
||||
|
||||
assign(keyboard<0>::a, XK_A);
|
||||
assign(keyboard<0>::b, XK_B);
|
||||
assign(keyboard<0>::c, XK_C);
|
||||
assign(keyboard<0>::d, XK_D);
|
||||
assign(keyboard<0>::e, XK_E);
|
||||
assign(keyboard<0>::f, XK_F);
|
||||
assign(keyboard<0>::g, XK_G);
|
||||
assign(keyboard<0>::h, XK_H);
|
||||
assign(keyboard<0>::i, XK_I);
|
||||
assign(keyboard<0>::j, XK_J);
|
||||
assign(keyboard<0>::k, XK_K);
|
||||
assign(keyboard<0>::l, XK_L);
|
||||
assign(keyboard<0>::m, XK_M);
|
||||
assign(keyboard<0>::n, XK_N);
|
||||
assign(keyboard<0>::o, XK_O);
|
||||
assign(keyboard<0>::p, XK_P);
|
||||
assign(keyboard<0>::q, XK_Q);
|
||||
assign(keyboard<0>::r, XK_R);
|
||||
assign(keyboard<0>::s, XK_S);
|
||||
assign(keyboard<0>::t, XK_T);
|
||||
assign(keyboard<0>::u, XK_U);
|
||||
assign(keyboard<0>::v, XK_V);
|
||||
assign(keyboard<0>::w, XK_W);
|
||||
assign(keyboard<0>::x, XK_X);
|
||||
assign(keyboard<0>::y, XK_Y);
|
||||
assign(keyboard<0>::z, XK_Z);
|
||||
key(Keyboard::A) = pressed(A);
|
||||
key(Keyboard::B) = pressed(B);
|
||||
key(Keyboard::C) = pressed(C);
|
||||
key(Keyboard::D) = pressed(D);
|
||||
key(Keyboard::E) = pressed(E);
|
||||
key(Keyboard::F) = pressed(F);
|
||||
key(Keyboard::G) = pressed(G);
|
||||
key(Keyboard::H) = pressed(H);
|
||||
key(Keyboard::I) = pressed(I);
|
||||
key(Keyboard::J) = pressed(J);
|
||||
key(Keyboard::K) = pressed(K);
|
||||
key(Keyboard::L) = pressed(L);
|
||||
key(Keyboard::M) = pressed(M);
|
||||
key(Keyboard::N) = pressed(N);
|
||||
key(Keyboard::O) = pressed(O);
|
||||
key(Keyboard::P) = pressed(P);
|
||||
key(Keyboard::Q) = pressed(Q);
|
||||
key(Keyboard::R) = pressed(R);
|
||||
key(Keyboard::S) = pressed(S);
|
||||
key(Keyboard::T) = pressed(T);
|
||||
key(Keyboard::U) = pressed(U);
|
||||
key(Keyboard::V) = pressed(V);
|
||||
key(Keyboard::W) = pressed(W);
|
||||
key(Keyboard::X) = pressed(X);
|
||||
key(Keyboard::Y) = pressed(Y);
|
||||
key(Keyboard::Z) = pressed(Z);
|
||||
|
||||
assign(keyboard<0>::lbracket, XK_bracketleft);
|
||||
assign(keyboard<0>::rbracket, XK_bracketright);
|
||||
assign(keyboard<0>::backslash, XK_backslash);
|
||||
assign(keyboard<0>::semicolon, XK_semicolon);
|
||||
assign(keyboard<0>::apostrophe, XK_apostrophe);
|
||||
assign(keyboard<0>::comma, XK_comma);
|
||||
assign(keyboard<0>::period, XK_period);
|
||||
assign(keyboard<0>::slash, XK_slash);
|
||||
key(Keyboard::LeftBracket) = pressed(LeftBracket);
|
||||
key(Keyboard::RightBracket) = pressed(RightBracket);
|
||||
key(Keyboard::Backslash) = pressed(Backslash);
|
||||
key(Keyboard::Semicolon) = pressed(Semicolon);
|
||||
key(Keyboard::Apostrophe) = pressed(Apostrophe);
|
||||
key(Keyboard::Comma) = pressed(Comma);
|
||||
key(Keyboard::Period) = pressed(Period);
|
||||
key(Keyboard::Slash) = pressed(Slash);
|
||||
|
||||
assign(keyboard<0>::pad_0, XK_KP_0);
|
||||
assign(keyboard<0>::pad_1, XK_KP_1);
|
||||
assign(keyboard<0>::pad_2, XK_KP_2);
|
||||
assign(keyboard<0>::pad_3, XK_KP_3);
|
||||
assign(keyboard<0>::pad_4, XK_KP_4);
|
||||
assign(keyboard<0>::pad_5, XK_KP_5);
|
||||
assign(keyboard<0>::pad_6, XK_KP_6);
|
||||
assign(keyboard<0>::pad_7, XK_KP_7);
|
||||
assign(keyboard<0>::pad_8, XK_KP_8);
|
||||
assign(keyboard<0>::pad_9, XK_KP_9);
|
||||
key(Keyboard::Keypad1) = pressed(Keypad1);
|
||||
key(Keyboard::Keypad2) = pressed(Keypad2);
|
||||
key(Keyboard::Keypad3) = pressed(Keypad3);
|
||||
key(Keyboard::Keypad4) = pressed(Keypad4);
|
||||
key(Keyboard::Keypad5) = pressed(Keypad5);
|
||||
key(Keyboard::Keypad6) = pressed(Keypad6);
|
||||
key(Keyboard::Keypad7) = pressed(Keypad7);
|
||||
key(Keyboard::Keypad8) = pressed(Keypad8);
|
||||
key(Keyboard::Keypad9) = pressed(Keypad9);
|
||||
key(Keyboard::Keypad0) = pressed(Keypad0);
|
||||
|
||||
assign(keyboard<0>::add, XK_KP_Add);
|
||||
assign(keyboard<0>::subtract, XK_KP_Subtract);
|
||||
assign(keyboard<0>::multiply, XK_KP_Multiply);
|
||||
assign(keyboard<0>::divide, XK_KP_Divide);
|
||||
assign(keyboard<0>::enter, XK_KP_Enter);
|
||||
key(Keyboard::Point) = pressed(Point);
|
||||
key(Keyboard::Enter) = pressed(Enter);
|
||||
key(Keyboard::Add) = pressed(Add);
|
||||
key(Keyboard::Subtract) = pressed(Subtract);
|
||||
key(Keyboard::Multiply) = pressed(Multiply);
|
||||
key(Keyboard::Divide) = pressed(Divide);
|
||||
|
||||
//assign(keyboard<0>::num_lock, XK_???);
|
||||
//assign(keyboard<0>::caps_lock, XK_???);
|
||||
key(Keyboard::Up) = pressed(Up);
|
||||
key(Keyboard::Down) = pressed(Down);
|
||||
key(Keyboard::Left) = pressed(Left);
|
||||
key(Keyboard::Right) = pressed(Right);
|
||||
|
||||
assign(keyboard<0>::up, XK_Up);
|
||||
assign(keyboard<0>::down, XK_Down);
|
||||
assign(keyboard<0>::left, XK_Left);
|
||||
assign(keyboard<0>::right, XK_Right);
|
||||
key(Keyboard::Tab) = pressed(Tab);
|
||||
key(Keyboard::Return) = pressed(Return);
|
||||
key(Keyboard::Spacebar) = pressed(Spacebar);
|
||||
key(Keyboard::Menu) = pressed(Menu);
|
||||
|
||||
assign(keyboard<0>::tab, XK_Tab);
|
||||
assign(keyboard<0>::return_, XK_Return);
|
||||
assign(keyboard<0>::spacebar, XK_space);
|
||||
key(Keyboard::Shift) = pressed(LeftShift) || pressed(RightShift);
|
||||
key(Keyboard::Control) = pressed(LeftControl) || pressed(RightControl);
|
||||
key(Keyboard::Alt) = pressed(LeftAlt) || pressed(RightAlt);
|
||||
key(Keyboard::Super) = pressed(LeftSuper) || pressed(RightSuper);
|
||||
|
||||
#undef key
|
||||
#undef pressed
|
||||
}
|
||||
|
||||
void x_init() {
|
||||
Display *display = XOpenDisplay(0);
|
||||
memset(&scancode, 0, sizeof scancode);
|
||||
|
||||
#define assign(x, y) scancode[x] = XKeysymToKeycode(display, y)
|
||||
assign(Escape, XK_Escape);
|
||||
|
||||
assign(F1, XK_F1);
|
||||
assign(F2, XK_F2);
|
||||
assign(F3, XK_F3);
|
||||
assign(F4, XK_F4);
|
||||
assign(F5, XK_F5);
|
||||
assign(F6, XK_F6);
|
||||
assign(F7, XK_F7);
|
||||
assign(F8, XK_F8);
|
||||
assign(F9, XK_F9);
|
||||
assign(F10, XK_F10);
|
||||
assign(F11, XK_F11);
|
||||
assign(F12, XK_F12);
|
||||
|
||||
assign(ScrollLock, XK_Scroll_Lock);
|
||||
assign(Pause, XK_Pause);
|
||||
|
||||
assign(Tilde, XK_asciitilde);
|
||||
|
||||
assign(Num0, XK_0);
|
||||
assign(Num1, XK_1);
|
||||
assign(Num2, XK_2);
|
||||
assign(Num3, XK_3);
|
||||
assign(Num4, XK_4);
|
||||
assign(Num5, XK_5);
|
||||
assign(Num6, XK_6);
|
||||
assign(Num7, XK_7);
|
||||
assign(Num8, XK_8);
|
||||
assign(Num9, XK_9);
|
||||
|
||||
assign(Dash, XK_minus);
|
||||
assign(Equal, XK_equal);
|
||||
assign(Backspace, XK_BackSpace);
|
||||
|
||||
assign(Insert, XK_Insert);
|
||||
assign(Delete, XK_Delete);
|
||||
assign(Home, XK_Home);
|
||||
assign(End, XK_End);
|
||||
assign(PageUp, XK_Prior);
|
||||
assign(PageDown, XK_Next);
|
||||
|
||||
assign(A, XK_A);
|
||||
assign(B, XK_B);
|
||||
assign(C, XK_C);
|
||||
assign(D, XK_D);
|
||||
assign(E, XK_E);
|
||||
assign(F, XK_F);
|
||||
assign(G, XK_G);
|
||||
assign(H, XK_H);
|
||||
assign(I, XK_I);
|
||||
assign(J, XK_J);
|
||||
assign(K, XK_K);
|
||||
assign(L, XK_L);
|
||||
assign(M, XK_M);
|
||||
assign(N, XK_N);
|
||||
assign(O, XK_O);
|
||||
assign(P, XK_P);
|
||||
assign(Q, XK_Q);
|
||||
assign(R, XK_R);
|
||||
assign(S, XK_S);
|
||||
assign(T, XK_T);
|
||||
assign(U, XK_U);
|
||||
assign(V, XK_V);
|
||||
assign(W, XK_W);
|
||||
assign(X, XK_X);
|
||||
assign(Y, XK_Y);
|
||||
assign(Z, XK_Z);
|
||||
|
||||
assign(LeftBracket, XK_bracketleft);
|
||||
assign(RightBracket, XK_bracketright);
|
||||
assign(Backslash, XK_backslash);
|
||||
assign(Semicolon, XK_semicolon);
|
||||
assign(Apostrophe, XK_apostrophe);
|
||||
assign(Comma, XK_comma);
|
||||
assign(Period, XK_period);
|
||||
assign(Slash, XK_slash);
|
||||
|
||||
assign(Keypad0, XK_KP_0);
|
||||
assign(Keypad1, XK_KP_1);
|
||||
assign(Keypad2, XK_KP_2);
|
||||
assign(Keypad3, XK_KP_3);
|
||||
assign(Keypad4, XK_KP_4);
|
||||
assign(Keypad5, XK_KP_5);
|
||||
assign(Keypad6, XK_KP_6);
|
||||
assign(Keypad7, XK_KP_7);
|
||||
assign(Keypad8, XK_KP_8);
|
||||
assign(Keypad9, XK_KP_9);
|
||||
|
||||
assign(Add, XK_KP_Add);
|
||||
assign(Subtract, XK_KP_Subtract);
|
||||
assign(Multiply, XK_KP_Multiply);
|
||||
assign(Divide, XK_KP_Divide);
|
||||
assign(Enter, XK_KP_Enter);
|
||||
|
||||
assign(Up, XK_Up);
|
||||
assign(Down, XK_Down);
|
||||
assign(Left, XK_Left);
|
||||
assign(Right, XK_Right);
|
||||
|
||||
assign(Tab, XK_Tab);
|
||||
assign(Return, XK_Return);
|
||||
assign(Spacebar, XK_space);
|
||||
|
||||
assign(LeftControl, XK_Control_L);
|
||||
assign(RightControl, XK_Control_R);
|
||||
assign(LeftAlt, XK_Alt_L);
|
||||
assign(RightAlt, XK_Alt_R);
|
||||
assign(LeftShift, XK_Shift_L);
|
||||
assign(RightShift, XK_Shift_R);
|
||||
assign(LeftSuper, XK_Super_L);
|
||||
assign(RightSuper, XK_Super_R);
|
||||
assign(Menu, XK_Menu);
|
||||
|
||||
assign(keyboard<0>::lctrl, XK_Control_L);
|
||||
assign(keyboard<0>::rctrl, XK_Control_R);
|
||||
assign(keyboard<0>::lalt, XK_Alt_L);
|
||||
assign(keyboard<0>::ralt, XK_Alt_R);
|
||||
assign(keyboard<0>::lshift, XK_Shift_L);
|
||||
assign(keyboard<0>::rshift, XK_Shift_R);
|
||||
assign(keyboard<0>::lsuper, XK_Super_L);
|
||||
assign(keyboard<0>::rsuper, XK_Super_R);
|
||||
assign(keyboard<0>::menu, XK_Menu);
|
||||
#undef assign
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
|
|
@ -14,6 +14,9 @@ InputInterface input;
|
|||
const char *Video::Handle = "Handle";
|
||||
const char *Video::Synchronize = "Synchronize";
|
||||
const char *Video::Filter = "Filter";
|
||||
const char *Video::GLSL = "GLSL";
|
||||
const char *Video::FragmentShader = "FragmentShader";
|
||||
const char *Video::VertexShader = "VertexShader";
|
||||
|
||||
void VideoInterface::driver(const char *driver) {
|
||||
if(p) term();
|
||||
|
|
|
@ -3,6 +3,9 @@ public:
|
|||
static const char *Handle;
|
||||
static const char *Synchronize;
|
||||
static const char *Filter;
|
||||
static const char *GLSL;
|
||||
static const char *FragmentShader;
|
||||
static const char *VertexShader;
|
||||
|
||||
enum Filter {
|
||||
FilterPoint,
|
||||
|
|
|
@ -60,6 +60,9 @@ public:
|
|||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
if(name == Video::GLSL) return true;
|
||||
if(name == Video::FragmentShader) return true;
|
||||
if(name == Video::VertexShader) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -89,6 +92,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::FragmentShader) {
|
||||
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::VertexShader) {
|
||||
OpenGL::set_vertex_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -175,6 +188,16 @@ public:
|
|||
OpenGL::init();
|
||||
settings.width = 256;
|
||||
settings.height = 256;
|
||||
|
||||
//vertical synchronization
|
||||
int (*glSwapInterval)(int);
|
||||
glSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalEXT");
|
||||
if(glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
glSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalSGI");
|
||||
if(glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
glSwapInterval = (int (*)(int))glGetProcAddress("glXSwapIntervalMESA");
|
||||
if(glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,15 +2,36 @@
|
|||
|
||||
#if defined(PLATFORM_X)
|
||||
#include <GL/glx.h>
|
||||
#define glGetProcAddress(name) (*glXGetProcAddress)((const GLubyte*)(name))
|
||||
#elif defined(PLATFORM_WIN)
|
||||
#include <GL/glext.h>
|
||||
#define glGetProcAddress(name) wglGetProcAddress(name)
|
||||
#else
|
||||
#error "ruby::OpenGL: unsupported platform"
|
||||
#endif
|
||||
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram = 0;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram = 0;
|
||||
PFNGLCREATESHADERPROC glCreateShader = 0;
|
||||
PFNGLDELETESHADERPROC glDeleteShader = 0;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource = 0;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader = 0;
|
||||
PFNGLATTACHSHADERPROC glAttachShader = 0;
|
||||
PFNGLDETACHSHADERPROC glDetachShader = 0;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram = 0;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = 0;
|
||||
PFNGLUNIFORM1IPROC glUniform1i = 0;
|
||||
PFNGLUNIFORM2FVPROC glUniform2fv = 0;
|
||||
PFNGLUNIFORM4FVPROC glUniform4fv = 0;
|
||||
|
||||
class OpenGL {
|
||||
public:
|
||||
GLuint gltexture;
|
||||
GLuint glprogram;
|
||||
GLuint fragmentshader;
|
||||
GLuint vertexshader;
|
||||
bool shader_support;
|
||||
|
||||
uint32_t *buffer;
|
||||
unsigned iwidth, iheight;
|
||||
|
||||
|
@ -45,6 +66,23 @@ public:
|
|||
}
|
||||
|
||||
void refresh(bool smooth, unsigned inwidth, unsigned inheight, unsigned outwidth, unsigned outheight) {
|
||||
if(shader_support) {
|
||||
glUseProgram(glprogram);
|
||||
GLint location;
|
||||
|
||||
float inputSize[2] = { inwidth, inheight };
|
||||
location = glGetUniformLocation(glprogram, "rubyInputSize");
|
||||
glUniform2fv(location, 1, inputSize);
|
||||
|
||||
float outputSize[2] = { outwidth, outheight };
|
||||
location = glGetUniformLocation(glprogram, "rubyOutputSize");
|
||||
glUniform2fv(location, 1, outputSize);
|
||||
|
||||
float textureSize[2] = { iwidth, iheight };
|
||||
location = glGetUniformLocation(glprogram, "rubyTextureSize");
|
||||
glUniform2fv(location, 1, textureSize);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
|
@ -78,6 +116,48 @@ public:
|
|||
glEnd();
|
||||
|
||||
glFlush();
|
||||
|
||||
if(shader_support) {
|
||||
glUseProgram(0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_fragment_shader(const char *source) {
|
||||
if(!shader_support) return;
|
||||
|
||||
if(fragmentshader) {
|
||||
glDetachShader(glprogram, fragmentshader);
|
||||
glDeleteShader(fragmentshader);
|
||||
fragmentshader = 0;
|
||||
}
|
||||
|
||||
if(source) {
|
||||
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentshader, 1, &source, 0);
|
||||
glCompileShader(fragmentshader);
|
||||
glAttachShader(glprogram, fragmentshader);
|
||||
}
|
||||
|
||||
glLinkProgram(glprogram);
|
||||
}
|
||||
|
||||
void set_vertex_shader(const char *source) {
|
||||
if(!shader_support) return;
|
||||
|
||||
if(vertexshader) {
|
||||
glDetachShader(glprogram, vertexshader);
|
||||
glDeleteShader(vertexshader);
|
||||
vertexshader = 0;
|
||||
}
|
||||
|
||||
if(source) {
|
||||
vertexshader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexshader, 1, &source, 0);
|
||||
glCompileShader(vertexshader);
|
||||
glAttachShader(glprogram, vertexshader);
|
||||
}
|
||||
|
||||
glLinkProgram(glprogram);
|
||||
}
|
||||
|
||||
void init() {
|
||||
|
@ -92,6 +172,28 @@ public:
|
|||
glEnable(GL_DITHER);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
//bind shader functions
|
||||
glCreateProgram = (PFNGLCREATEPROGRAMPROC)glGetProcAddress("glCreateProgram");
|
||||
glUseProgram = (PFNGLUSEPROGRAMPROC)glGetProcAddress("glUseProgram");
|
||||
glCreateShader = (PFNGLCREATESHADERPROC)glGetProcAddress("glCreateShader");
|
||||
glDeleteShader = (PFNGLDELETESHADERPROC)glGetProcAddress("glDeleteShader");
|
||||
glShaderSource = (PFNGLSHADERSOURCEPROC)glGetProcAddress("glShaderSource");
|
||||
glCompileShader = (PFNGLCOMPILESHADERPROC)glGetProcAddress("glCompileShader");
|
||||
glAttachShader = (PFNGLATTACHSHADERPROC)glGetProcAddress("glAttachShader");
|
||||
glDetachShader = (PFNGLDETACHSHADERPROC)glGetProcAddress("glDetachShader");
|
||||
glLinkProgram = (PFNGLLINKPROGRAMPROC)glGetProcAddress("glLinkProgram");
|
||||
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)glGetProcAddress("glGetUniformLocation");
|
||||
glUniform1i = (PFNGLUNIFORM1IPROC)glGetProcAddress("glUniform1i");
|
||||
glUniform2fv = (PFNGLUNIFORM2FVPROC)glGetProcAddress("glUniform2fv");
|
||||
glUniform4fv = (PFNGLUNIFORM4FVPROC)glGetProcAddress("glUniform4fv");
|
||||
|
||||
shader_support = glCreateProgram && glUseProgram && glCreateShader
|
||||
&& glDeleteShader && glShaderSource && glCompileShader && glAttachShader
|
||||
&& glDetachShader && glLinkProgram && glGetUniformLocation
|
||||
&& glUniform1i && glUniform2fv && glUniform4fv;
|
||||
|
||||
if(shader_support) glprogram = glCreateProgram();
|
||||
|
||||
//create surface texture
|
||||
resize(256, 256);
|
||||
}
|
||||
|
@ -112,6 +214,10 @@ public:
|
|||
|
||||
OpenGL() {
|
||||
gltexture = 0;
|
||||
glprogram = 0;
|
||||
fragmentshader = 0;
|
||||
vertexshader = 0;
|
||||
|
||||
buffer = 0;
|
||||
iwidth = 0;
|
||||
iheight = 0;
|
||||
|
|
|
@ -27,6 +27,9 @@ public:
|
|||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
if(name == Video::GLSL) return true;
|
||||
if(name == Video::FragmentShader) return true;
|
||||
if(name == Video::VertexShader) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -55,6 +58,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::FragmentShader) {
|
||||
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::VertexShader) {
|
||||
OpenGL::set_vertex_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -105,6 +118,12 @@ public:
|
|||
OpenGL::init();
|
||||
settings.width = 256;
|
||||
settings.height = 256;
|
||||
|
||||
//vertical synchronization
|
||||
BOOL (APIENTRY *glSwapInterval)(int);
|
||||
glSwapInterval = (BOOL (APIENTRY*)(int))glGetProcAddress("wglSwapIntervalEXT");
|
||||
if(glSwapInterval) glSwapInterval(settings.synchronize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ void Audio::coprocessor_enable(bool state) {
|
|||
dsp_wroffset = cop_wroffset = 0;
|
||||
dsp_length = cop_length = 0;
|
||||
|
||||
for(unsigned i = 0; i < 4; i++) r_left[i] = r_right[i] = 0;
|
||||
r_sum_l = r_sum_r = 0;
|
||||
}
|
||||
|
||||
void Audio::coprocessor_frequency(double input_frequency) {
|
||||
|
@ -24,72 +24,45 @@ void Audio::coprocessor_frequency(double input_frequency) {
|
|||
r_frac = 0;
|
||||
}
|
||||
|
||||
void Audio::sample(uint16 left, uint16 right) {
|
||||
void Audio::sample(int16 left, int16 right) {
|
||||
if(coprocessor == false) {
|
||||
system.interface->audio_sample(left, right);
|
||||
} else {
|
||||
dsp_buffer[dsp_wroffset] = (left << 0) + (right << 16);
|
||||
dsp_buffer[dsp_wroffset] = ((uint16)left << 0) + ((uint16)right << 16);
|
||||
dsp_wroffset = (dsp_wroffset + 1) & 32767;
|
||||
dsp_length = (dsp_length + 1) & 32767;
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::coprocessor_sample(uint16 left, uint16 right) {
|
||||
r_left [0] = r_left [1];
|
||||
r_left [1] = r_left [2];
|
||||
r_left [2] = r_left [3];
|
||||
r_left [3] = (int16)left;
|
||||
|
||||
r_right[0] = r_right[1];
|
||||
r_right[1] = r_right[2];
|
||||
r_right[2] = r_right[3];
|
||||
r_right[3] = (int16)right;
|
||||
|
||||
while(r_frac <= 1.0) {
|
||||
left = sclamp<16>(hermite(r_frac, r_left [0], r_left [1], r_left [2], r_left [3]));
|
||||
right = sclamp<16>(hermite(r_frac, r_right[0], r_right[1], r_right[2], r_right[3]));
|
||||
r_frac += r_step;
|
||||
|
||||
cop_buffer[cop_wroffset] = (left << 0) + (right << 16);
|
||||
cop_wroffset = (cop_wroffset + 1) & 32767;
|
||||
cop_length = (cop_length + 1) & 32767;
|
||||
flush();
|
||||
void Audio::coprocessor_sample(int16 left, int16 right) {
|
||||
if(r_frac >= 1.0) {
|
||||
r_frac -= 1.0;
|
||||
r_sum_l += left;
|
||||
r_sum_r += right;
|
||||
return;
|
||||
}
|
||||
|
||||
r_frac -= 1.0;
|
||||
r_sum_l += left * r_frac;
|
||||
r_sum_r += right * r_frac;
|
||||
|
||||
uint16 output_left = sclamp<16>(int(r_sum_l / r_step));
|
||||
uint16 output_right = sclamp<16>(int(r_sum_r / r_step));
|
||||
|
||||
double first = 1.0 - r_frac;
|
||||
r_sum_l = left * first;
|
||||
r_sum_r = right * first;
|
||||
r_frac = r_step - first;
|
||||
|
||||
cop_buffer[cop_wroffset] = (output_left << 0) + (output_right << 16);
|
||||
cop_wroffset = (cop_wroffset + 1) & 32767;
|
||||
cop_length = (cop_length + 1) & 32767;
|
||||
flush();
|
||||
}
|
||||
|
||||
void Audio::init() {
|
||||
}
|
||||
|
||||
//========
|
||||
//private:
|
||||
//========
|
||||
|
||||
//4-tap hermite interpolation
|
||||
double Audio::hermite(double mu1, double a, double b, double c, double d) {
|
||||
const double tension = 0.0; //-1 = low, 0 = normal, 1 = high
|
||||
const double bias = 0.0; //-1 = left, 0 = even, 1 = right
|
||||
|
||||
double mu2, mu3, m0, m1, a0, a1, a2, a3;
|
||||
|
||||
mu2 = mu1 * mu1;
|
||||
mu3 = mu2 * mu1;
|
||||
|
||||
m0 = (b - a) * (1 + bias) * (1 - tension) / 2;
|
||||
m0 += (c - b) * (1 - bias) * (1 - tension) / 2;
|
||||
m1 = (c - b) * (1 + bias) * (1 - tension) / 2;
|
||||
m1 += (d - c) * (1 - bias) * (1 - tension) / 2;
|
||||
|
||||
a0 = +2 * mu3 - 3 * mu2 + 1;
|
||||
a1 = mu3 - 2 * mu2 + mu1;
|
||||
a2 = mu3 - mu2;
|
||||
a3 = -2 * mu3 + 3 * mu2;
|
||||
|
||||
return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
|
||||
}
|
||||
|
||||
void Audio::flush() {
|
||||
while(dsp_length > 0 && cop_length > 0) {
|
||||
uint32 dsp_sample = dsp_buffer[dsp_rdoffset];
|
||||
|
|
|
@ -2,8 +2,8 @@ class Audio {
|
|||
public:
|
||||
void coprocessor_enable(bool state);
|
||||
void coprocessor_frequency(double frequency);
|
||||
void sample(uint16 left, uint16 right);
|
||||
void coprocessor_sample(uint16 left, uint16 right);
|
||||
void sample(int16 left, int16 right);
|
||||
void coprocessor_sample(int16 left, int16 right);
|
||||
void init();
|
||||
|
||||
private:
|
||||
|
@ -13,9 +13,8 @@ private:
|
|||
unsigned dsp_wroffset, cop_wroffset;
|
||||
unsigned dsp_length, cop_length;
|
||||
|
||||
double hermite(double mu, double a, double b, double c, double d);
|
||||
double r_step, r_frac;
|
||||
int r_left[4], r_right[4];
|
||||
int r_sum_l, r_sum_r;
|
||||
|
||||
void flush();
|
||||
};
|
||||
|
|
|
@ -8,58 +8,40 @@ uint8 Input::port_read(bool portnumber) {
|
|||
switch(p.device) {
|
||||
case DeviceJoypad: {
|
||||
if(p.counter0 >= 16) return 1;
|
||||
unsigned deviceid = (portnumber == 0 ? DeviceIDJoypad1 : DeviceIDJoypad2);
|
||||
return system.interface->input_poll(deviceid, p.counter0++);
|
||||
return system.interface->input_poll(portnumber, p.device, 0, p.counter0++);
|
||||
} //case DeviceJoypad
|
||||
|
||||
case DeviceMultitap: {
|
||||
if(cpu.joylatch()) return 2; //when latch is high -- data2 = 1, data1 = 0
|
||||
|
||||
unsigned deviceidx, deviceid0, deviceid1;
|
||||
if(portnumber == 0) {
|
||||
if(cpu.pio() & 0x40) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
unsigned deviceidx, deviceindex0, deviceindex1;
|
||||
uint8 mask = (portnumber == 0 ? 0x40 : 0x80);
|
||||
|
||||
deviceid0 = DeviceIDMultitap1A;
|
||||
deviceid1 = DeviceIDMultitap1B;
|
||||
} else {
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
if(cpu.pio() & mask) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
|
||||
deviceid0 = DeviceIDMultitap1C;
|
||||
deviceid1 = DeviceIDMultitap1D;
|
||||
}
|
||||
deviceindex0 = 0; //controller 1
|
||||
deviceindex1 = 1; //controller 2
|
||||
} else {
|
||||
if(cpu.pio() & 0x80) {
|
||||
deviceidx = p.counter0;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter0++;
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
|
||||
deviceid0 = DeviceIDMultitap2A;
|
||||
deviceid1 = DeviceIDMultitap2B;
|
||||
} else {
|
||||
deviceidx = p.counter1;
|
||||
if(deviceidx >= 16) return 3;
|
||||
p.counter1++;
|
||||
|
||||
deviceid0 = DeviceIDMultitap2C;
|
||||
deviceid1 = DeviceIDMultitap2D;
|
||||
}
|
||||
deviceindex0 = 2; //controller 3
|
||||
deviceindex1 = 3; //controller 4
|
||||
}
|
||||
|
||||
return (system.interface->input_poll(deviceid0, deviceidx) << 0)
|
||||
| (system.interface->input_poll(deviceid1, deviceidx) << 1);
|
||||
return (system.interface->input_poll(portnumber, p.device, deviceindex0, deviceidx) << 0)
|
||||
| (system.interface->input_poll(portnumber, p.device, deviceindex1, deviceidx) << 1);
|
||||
} //case DeviceMultitap
|
||||
|
||||
case DeviceMouse: {
|
||||
if(p.counter0 >= 32) return 1;
|
||||
unsigned deviceid = (portnumber == 0 ? DeviceIDMouse1 : DeviceIDMouse2);
|
||||
|
||||
int position_x = system.interface->input_poll(deviceid, MouseX); //-n = left, 0 = center, +n = right
|
||||
int position_y = system.interface->input_poll(deviceid, MouseY); //-n = up, 0 = center, +n = right
|
||||
int position_x = system.interface->input_poll(portnumber, p.device, 0, MouseX); //-n = left, 0 = center, +n = right
|
||||
int position_y = system.interface->input_poll(portnumber, p.device, 0, MouseY); //-n = up, 0 = center, +n = right
|
||||
|
||||
bool direction_x = position_x < 0; //0 = right, 1 = left
|
||||
bool direction_y = position_y < 0; //0 = down, 1 = up
|
||||
|
@ -80,8 +62,8 @@ uint8 Input::port_read(bool portnumber) {
|
|||
case 6: return 0;
|
||||
case 7: return 0;
|
||||
|
||||
case 8: return system.interface->input_poll(deviceid, MouseRight);
|
||||
case 9: return system.interface->input_poll(deviceid, MouseLeft);
|
||||
case 8: return system.interface->input_poll(portnumber, p.device, 0, MouseRight);
|
||||
case 9: return system.interface->input_poll(portnumber, p.device, 0, MouseLeft);
|
||||
case 10: return 0; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused)
|
||||
case 11: return 0; // ||
|
||||
|
||||
|
@ -116,7 +98,7 @@ uint8 Input::port_read(bool portnumber) {
|
|||
|
||||
if(p.counter0 == 0) {
|
||||
//turbo is a switch; toggle is edge sensitive
|
||||
bool turbo = system.interface->input_poll(DeviceIDSuperScope, SuperScopeTurbo);
|
||||
bool turbo = system.interface->input_poll(portnumber, p.device, 0, SuperScopeTurbo);
|
||||
if(turbo && !p.superscope.turbolock) {
|
||||
p.superscope.turbo = !p.superscope.turbo; //toggle state
|
||||
p.superscope.turbolock = true;
|
||||
|
@ -127,7 +109,7 @@ uint8 Input::port_read(bool portnumber) {
|
|||
//trigger is a button
|
||||
//if turbo is active, trigger is level sensitive; otherwise it is edge sensitive
|
||||
p.superscope.trigger = false;
|
||||
bool trigger = system.interface->input_poll(DeviceIDSuperScope, SuperScopeTrigger);
|
||||
bool trigger = system.interface->input_poll(portnumber, p.device, 0, SuperScopeTrigger);
|
||||
if(trigger && (p.superscope.turbo || !p.superscope.triggerlock)) {
|
||||
p.superscope.trigger = true;
|
||||
p.superscope.triggerlock = true;
|
||||
|
@ -136,11 +118,11 @@ uint8 Input::port_read(bool portnumber) {
|
|||
}
|
||||
|
||||
//cursor is a button; it is always level sensitive
|
||||
p.superscope.cursor = system.interface->input_poll(DeviceIDSuperScope, SuperScopeCursor);
|
||||
p.superscope.cursor = system.interface->input_poll(portnumber, p.device, 0, SuperScopeCursor);
|
||||
|
||||
//pause is a button; it is always edge sensitive
|
||||
p.superscope.pause = false;
|
||||
bool pause = system.interface->input_poll(DeviceIDSuperScope, SuperScopePause);
|
||||
bool pause = system.interface->input_poll(portnumber, p.device, 0, SuperScopePause);
|
||||
if(pause && !p.superscope.pauselock) {
|
||||
p.superscope.pause = true;
|
||||
p.superscope.pauselock = true;
|
||||
|
@ -171,12 +153,12 @@ uint8 Input::port_read(bool portnumber) {
|
|||
if(p.counter0 >= 32) return 1;
|
||||
|
||||
if(p.counter0 == 0) {
|
||||
p.justifier.trigger1 = system.interface->input_poll(DeviceIDJustifier1, JustifierTrigger);
|
||||
p.justifier.start1 = system.interface->input_poll(DeviceIDJustifier1, JustifierStart);
|
||||
p.justifier.trigger1 = system.interface->input_poll(portnumber, p.device, 0, JustifierTrigger);
|
||||
p.justifier.start1 = system.interface->input_poll(portnumber, p.device, 0, JustifierStart);
|
||||
|
||||
if(p.device == DeviceJustifiers) {
|
||||
p.justifier.trigger2 = system.interface->input_poll(DeviceIDJustifier2, JustifierTrigger);
|
||||
p.justifier.start2 = system.interface->input_poll(DeviceIDJustifier2, JustifierStart);
|
||||
p.justifier.trigger2 = system.interface->input_poll(portnumber, p.device, 1, JustifierTrigger);
|
||||
p.justifier.start2 = system.interface->input_poll(portnumber, p.device, 1, JustifierStart);
|
||||
} else {
|
||||
p.justifier.x2 = -1;
|
||||
p.justifier.y2 = -1;
|
||||
|
@ -238,8 +220,8 @@ void Input::update() {
|
|||
|
||||
switch(p.device) {
|
||||
case DeviceSuperScope: {
|
||||
int x = system.interface->input_poll(DeviceIDSuperScope, SuperScopeX);
|
||||
int y = system.interface->input_poll(DeviceIDSuperScope, SuperScopeY);
|
||||
int x = system.interface->input_poll(1, p.device, 0, SuperScopeX);
|
||||
int y = system.interface->input_poll(1, p.device, 0, SuperScopeY);
|
||||
x += p.superscope.x;
|
||||
y += p.superscope.y;
|
||||
p.superscope.x = max(-16, min(256 + 16, x));
|
||||
|
@ -251,15 +233,15 @@ void Input::update() {
|
|||
|
||||
case DeviceJustifier:
|
||||
case DeviceJustifiers: {
|
||||
int x1 = system.interface->input_poll(DeviceIDJustifier1, JustifierX);
|
||||
int y1 = system.interface->input_poll(DeviceIDJustifier1, JustifierY);
|
||||
int x1 = system.interface->input_poll(1, p.device, 0, JustifierX);
|
||||
int y1 = system.interface->input_poll(1, p.device, 0, JustifierY);
|
||||
x1 += p.justifier.x1;
|
||||
y1 += p.justifier.y1;
|
||||
p.justifier.x1 = max(-16, min(256 + 16, x1));
|
||||
p.justifier.y1 = max(-16, min(240 + 16, y1));
|
||||
|
||||
int x2 = system.interface->input_poll(DeviceIDJustifier2, JustifierX);
|
||||
int y2 = system.interface->input_poll(DeviceIDJustifier2, JustifierY);
|
||||
int x2 = system.interface->input_poll(1, p.device, 1, JustifierX);
|
||||
int y2 = system.interface->input_poll(1, p.device, 1, JustifierY);
|
||||
x2 += p.justifier.x2;
|
||||
y2 += p.justifier.y2;
|
||||
p.justifier.x2 = max(-16, min(256 + 16, x2));
|
||||
|
|
|
@ -10,32 +10,13 @@ public:
|
|||
DeviceJustifiers,
|
||||
};
|
||||
|
||||
enum DeviceID {
|
||||
DeviceIDNone,
|
||||
DeviceIDJoypad1,
|
||||
DeviceIDJoypad2,
|
||||
DeviceIDMultitap1A,
|
||||
DeviceIDMultitap1B,
|
||||
DeviceIDMultitap1C,
|
||||
DeviceIDMultitap1D,
|
||||
DeviceIDMultitap2A,
|
||||
DeviceIDMultitap2B,
|
||||
DeviceIDMultitap2C,
|
||||
DeviceIDMultitap2D,
|
||||
DeviceIDMouse1,
|
||||
DeviceIDMouse2,
|
||||
DeviceIDSuperScope,
|
||||
DeviceIDJustifier1,
|
||||
DeviceIDJustifier2,
|
||||
};
|
||||
|
||||
enum JoypadID {
|
||||
JoypadB = 0, JoypadY = 1,
|
||||
JoypadSelect = 2, JoypadStart = 3,
|
||||
JoypadUp = 4, JoypadDown = 5,
|
||||
JoypadLeft = 6, JoypadRight = 7,
|
||||
JoypadA = 8, JoypadX = 9,
|
||||
JoypadL = 10, JoypadR = 11,
|
||||
JoypadB = 0, JoypadY = 1,
|
||||
JoypadSelect = 2, JoypadStart = 3,
|
||||
JoypadUp = 4, JoypadDown = 5,
|
||||
JoypadLeft = 6, JoypadRight = 7,
|
||||
JoypadA = 8, JoypadX = 9,
|
||||
JoypadL = 10, JoypadR = 11,
|
||||
};
|
||||
|
||||
enum MouseID {
|
||||
|
|
|
@ -3,5 +3,5 @@ public:
|
|||
virtual void video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height) {}
|
||||
virtual void audio_sample(uint16_t l_sample, uint16_t r_sample) {}
|
||||
virtual void input_poll() {}
|
||||
virtual int16_t input_poll(unsigned deviceid, unsigned id) { return 0; }
|
||||
virtual int16_t input_poll(bool port, unsigned device, unsigned index, unsigned id) { return 0; }
|
||||
};
|
||||
|
|
|
@ -51,6 +51,8 @@ void System::serialize_all(serializer &s) {
|
|||
ppu.serialize(s);
|
||||
dsp.serialize(s);
|
||||
|
||||
if(cartridge.mode() == Cartridge::ModeSuperGameBoy) supergameboy.serialize(s);
|
||||
|
||||
if(cartridge.has_srtc()) srtc.serialize(s);
|
||||
if(cartridge.has_sdd1()) sdd1.serialize(s);
|
||||
if(cartridge.has_spc7110()) spc7110.serialize(s);
|
||||
|
|
|
@ -15,30 +15,30 @@ void Application::initPaths(const char *basename) {
|
|||
}
|
||||
|
||||
if(strend(temp, "/") == false) strcat(temp, "/");
|
||||
config.path.base = temp;
|
||||
config().path.base = temp;
|
||||
} else {
|
||||
config.path.base = "";
|
||||
config().path.base = "";
|
||||
}
|
||||
|
||||
if(userpath(temp)) {
|
||||
strtr(temp, "\\", "/");
|
||||
if(strend(temp, "/") == false) strcat(temp, "/");
|
||||
config.path.user = temp;
|
||||
config().path.user = temp;
|
||||
} else {
|
||||
config.path.user = "";
|
||||
config().path.user = "";
|
||||
}
|
||||
|
||||
char cwd[PATH_MAX];
|
||||
config.path.current = getcwd(cwd);
|
||||
config().path.startup = getcwd(cwd);
|
||||
}
|
||||
|
||||
void Application::locateFile(string &filename, bool createDataDirectory) {
|
||||
//first, check if file exists in executable directory (single-user mode)
|
||||
string temp = string() << config.path.base << filename;
|
||||
string temp = string() << config().path.base << filename;
|
||||
|
||||
if(file::exists(temp) == false) {
|
||||
//if not, use user data path (multi-user mode)
|
||||
temp = config.path.user;
|
||||
temp = config().path.user;
|
||||
temp << ".bsnes";
|
||||
if(createDataDirectory) mkdir(temp); //ensure directory exists
|
||||
temp << "/" << filename;
|
||||
|
@ -66,7 +66,8 @@ int Application::main(int &argc, char **argv) {
|
|||
app->setStyleSheet(defaultStylesheet);
|
||||
}
|
||||
|
||||
config.load(configFilename);
|
||||
config().load(configFilename);
|
||||
mapper().bind();
|
||||
init();
|
||||
SNES::system.init(&interface);
|
||||
mainWindow->system_loadSpecial_superGameBoy->setVisible(SNES::supergameboy.opened());
|
||||
|
@ -87,7 +88,7 @@ int Application::main(int &argc, char **argv) {
|
|||
}
|
||||
|
||||
utility.unloadCartridge();
|
||||
config.save(configFilename);
|
||||
config().save(configFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -100,9 +101,9 @@ void Application::run() {
|
|||
|
||||
QApplication::processEvents();
|
||||
utility.updateSystemState();
|
||||
inputManager.refresh();
|
||||
mapper().poll();
|
||||
|
||||
if(config.input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation) {
|
||||
if(config().input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation) {
|
||||
bool active = mainWindow->isActive();
|
||||
if(!autopause && !active) {
|
||||
autopause = true;
|
||||
|
@ -135,7 +136,7 @@ void Application::run() {
|
|||
if(autosaveTime >= CLOCKS_PER_SEC * 60) {
|
||||
//auto-save RAM once per minute in case of emulator crash
|
||||
autosaveTime = 0;
|
||||
if(config.system.autoSaveMemory == true) utility.saveMemory();
|
||||
if(config().system.autoSaveMemory == true) utility.saveMemory();
|
||||
}
|
||||
|
||||
if(screensaverTime >= CLOCKS_PER_SEC * 30) {
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include "../tools/tools.cpp"
|
||||
|
||||
void Application::init() {
|
||||
if(config.system.crashedOnLastRun == true) {
|
||||
if(config().system.crashedOnLastRun == true) {
|
||||
//emulator crashed on last run, disable all drivers
|
||||
QMessageBox::warning(0, "bsnes Crash Notification", utf8() <<
|
||||
QMessageBox::warning(0, "bsnes Crash Notification", string() <<
|
||||
"<p><b>Warning:</b><br>bsnes crashed while attempting to initialize device "
|
||||
"drivers the last time it was run.</p>"
|
||||
"<p>To prevent this from occurring again, all drivers have been disabled. Please "
|
||||
|
@ -27,19 +27,19 @@ void Application::init() {
|
|||
"restart the emulator for the changes to take effect. <i>Video, audio and input "
|
||||
"will not work until you do this!</i></p>"
|
||||
"<p><b>Settings that caused failure on last run:</b><br>"
|
||||
<< "Video driver: " << config.system.video << "<br>"
|
||||
<< "Audio driver: " << config.system.audio << "<br>"
|
||||
<< "Input driver: " << config.system.input << "<br></p>"
|
||||
<< "Video driver: " << config().system.video << "<br>"
|
||||
<< "Audio driver: " << config().system.audio << "<br>"
|
||||
<< "Input driver: " << config().system.input << "<br></p>"
|
||||
);
|
||||
|
||||
config.system.video = "None";
|
||||
config.system.audio = "None";
|
||||
config.system.input = "None";
|
||||
config().system.video = "None";
|
||||
config().system.audio = "None";
|
||||
config().system.input = "None";
|
||||
}
|
||||
|
||||
if(config.system.video == "") config.system.video = video.default_driver();
|
||||
if(config.system.audio == "") config.system.audio = audio.default_driver();
|
||||
if(config.system.input == "") config.system.input = input.default_driver();
|
||||
if(config().system.video == "") config().system.video = video.default_driver();
|
||||
if(config().system.audio == "") config().system.audio = audio.default_driver();
|
||||
if(config().system.input == "") config().system.input = input.default_driver();
|
||||
|
||||
mainWindow = new MainWindow;
|
||||
loaderWindow = new LoaderWindow;
|
||||
|
@ -59,15 +59,15 @@ void Application::init() {
|
|||
|
||||
//if emulator crashes while initializing drivers, next run will disable them all.
|
||||
//this will allow user to choose different driver settings.
|
||||
config.system.crashedOnLastRun = true;
|
||||
config.save(configFilename);
|
||||
config().system.crashedOnLastRun = true;
|
||||
config().save(configFilename);
|
||||
|
||||
video.driver(config.system.video);
|
||||
video.driver(config().system.video);
|
||||
video.set(Video::Handle, (uintptr_t)mainWindow->canvas->winId());
|
||||
video.set("QWidget", (QWidget*)mainWindow->canvas);
|
||||
if(video.init() == false) {
|
||||
QMessageBox::warning(0, "bsnes", utf8() <<
|
||||
"<p><b>Warning:</b> " << config.system.video << " video driver failed to initialize. "
|
||||
QMessageBox::warning(0, "bsnes", string() <<
|
||||
"<p><b>Warning:</b> " << config().system.video << " video driver failed to initialize. "
|
||||
"Video driver has been disabled.</p>"
|
||||
"<p>Please go to Settings->Configuration->Advanced and choose a different driver, and "
|
||||
"then restart the emulator for the changes to take effect.</p>"
|
||||
|
@ -76,14 +76,14 @@ void Application::init() {
|
|||
video.init();
|
||||
}
|
||||
|
||||
audio.driver(config.system.audio);
|
||||
audio.driver(config().system.audio);
|
||||
audio.set(Audio::Handle, (uintptr_t)mainWindow->canvas->winId());
|
||||
audio.set(Audio::Frequency, config.audio.outputFrequency);
|
||||
audio.set(Audio::Latency, config.audio.latency);
|
||||
audio.set(Audio::Volume, config.audio.volume);
|
||||
audio.set(Audio::Frequency, config().audio.outputFrequency);
|
||||
audio.set(Audio::Latency, config().audio.latency);
|
||||
audio.set(Audio::Volume, config().audio.volume);
|
||||
if(audio.init() == false) {
|
||||
QMessageBox::warning(0, "bsnes", utf8() <<
|
||||
"<p><b>Warning:</b> " << config.system.audio << " audio driver failed to initialize. "
|
||||
QMessageBox::warning(0, "bsnes", string() <<
|
||||
"<p><b>Warning:</b> " << config().system.audio << " audio driver failed to initialize. "
|
||||
"Audio driver has been disabled.</p>"
|
||||
"<p>Please go to Settings->Configuration->Advanced and choose a different driver, and "
|
||||
"then restart the emulator for the changes to take effect.</p>"
|
||||
|
@ -92,11 +92,11 @@ void Application::init() {
|
|||
audio.init();
|
||||
}
|
||||
|
||||
input.driver(config.system.input);
|
||||
input.driver(config().system.input);
|
||||
input.set("Handle", (uintptr_t)mainWindow->canvas->winId());
|
||||
if(input.init() == false) {
|
||||
QMessageBox::warning(0, "bsnes", utf8() <<
|
||||
"<p><b>Warning:</b> " << config.system.input << " input driver failed to initialize. "
|
||||
QMessageBox::warning(0, "bsnes", string() <<
|
||||
"<p><b>Warning:</b> " << config().system.input << " input driver failed to initialize. "
|
||||
"Input driver has been disabled.</p>"
|
||||
"<p>Please go to Settings->Configuration->Advanced and choose a different driver, and "
|
||||
"then restart the emulator for the changes to take effect.</p>"
|
||||
|
@ -106,18 +106,17 @@ void Application::init() {
|
|||
}
|
||||
|
||||
//didn't crash, note this in the config file now in case a different kind of crash occurs later
|
||||
config.system.crashedOnLastRun = false;
|
||||
config.save(configFilename);
|
||||
config().system.crashedOnLastRun = false;
|
||||
config().save(configFilename);
|
||||
|
||||
inputManager.bind();
|
||||
inputManager.refresh();
|
||||
inputManager.refresh();
|
||||
inputManager.onInput = bind(&Utility::inputEvent, &utility);
|
||||
//no sense showing unusable options ...
|
||||
pixelShaderWindow->setVisible(video.cap(Video::FragmentShader) || video.cap(Video::VertexShader));
|
||||
|
||||
utility.resizeMainWindow();
|
||||
utility.updateAvSync();
|
||||
utility.updateVideoMode();
|
||||
utility.updateColorFilter();
|
||||
utility.updatePixelShader();
|
||||
utility.updateHardwareFilter();
|
||||
utility.updateSoftwareFilter();
|
||||
utility.updateEmulationSpeed();
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
void QbWindow::shrink() {
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
resize(0, 0);
|
||||
usleep(2000);
|
||||
QApplication::processEvents();
|
||||
if(config().video.isFullscreen == false) {
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
resize(0, 0);
|
||||
usleep(2000);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
AboutWindow::AboutWindow() : QbWindow(config.geometry.aboutWindow) {
|
||||
AboutWindow::AboutWindow() : QbWindow(config().geometry.aboutWindow) {
|
||||
setObjectName("about-window");
|
||||
setWindowTitle("About bsnes ...");
|
||||
|
||||
|
@ -12,7 +12,7 @@ AboutWindow::AboutWindow() : QbWindow(config.geometry.aboutWindow) {
|
|||
logo->setFixedSize(600, 106);
|
||||
layout->addWidget(logo);
|
||||
|
||||
info = new QLabel(utf8() <<
|
||||
info = new QLabel(string() <<
|
||||
"<table>"
|
||||
"<tr><td align='right'><b>Version: </b></td><td>" << bsnesVersion << "</td></tr>"
|
||||
"<tr><td align='right'><b>Author: </b></td><td>byuu</td></tr>"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//FolderCreator
|
||||
//=============
|
||||
|
||||
FolderCreator::FolderCreator() : QbWindow(config.geometry.folderCreator) {
|
||||
FolderCreator::FolderCreator() : QbWindow(config().geometry.folderCreator) {
|
||||
setObjectName("folder-creator");
|
||||
setWindowTitle("Create New Folder");
|
||||
|
||||
|
@ -89,7 +89,7 @@ void DiskBrowserView::currentChanged(const QModelIndex ¤t, const QModelInd
|
|||
void DiskBrowserImage::paintEvent(QPaintEvent*) {
|
||||
QPainter painter(this);
|
||||
if(name != "") {
|
||||
QImage image(name);
|
||||
QImage image(QString::fromUtf8(name));
|
||||
painter.drawImage(0, 0, image);
|
||||
}
|
||||
}
|
||||
|
@ -98,81 +98,160 @@ void DiskBrowserImage::paintEvent(QPaintEvent*) {
|
|||
//DiskBrowser
|
||||
//===========
|
||||
|
||||
void DiskBrowser::chooseFolder(PathSettingWidget *widget, const char *title) {
|
||||
void DiskBrowser::inputEvent(uint16_t scancode) {
|
||||
if(!isActiveWindow() || isMinimized()) return;
|
||||
|
||||
//provide very simple support for controlling the window via gamepads
|
||||
if(Joypad::isAnyHat(scancode)) {
|
||||
int16_t state = mapper().state(scancode);
|
||||
|
||||
if(state == Joypad::HatUp) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Up, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
|
||||
if(state == Joypad::HatDown) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Down, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
|
||||
if(state == Joypad::HatLeft) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Backspace, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
|
||||
if(state == Joypad::HatRight) {
|
||||
QKeyEvent event((QEvent::Type)6, Qt::Key_Return, Qt::NoModifier);
|
||||
view->keyPressEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiskBrowser::chooseFolder(const function<void (string)> &callback_, string ¤tPath_, const char *title) {
|
||||
callback = callback_;
|
||||
currentPath = ¤tPath_;
|
||||
browseMode = Folder;
|
||||
activePath = widget;
|
||||
|
||||
hide();
|
||||
group->hide();
|
||||
ok->setText("Choose");
|
||||
setWindowTitle(utf8() << title);
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setWindowTitle(string() << title);
|
||||
setPath(*currentPath);
|
||||
setNameFilters("Folders ()");
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadCartridge() {
|
||||
browseMode = Cartridge;
|
||||
void DiskBrowser::chooseFile(const function<void (string)> &callback_, string ¤tPath_, const char *title) {
|
||||
callback = callback_;
|
||||
currentPath = ¤tPath_;
|
||||
browseMode = File;
|
||||
|
||||
hide();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
group->hide();
|
||||
ok->setText("Choose");
|
||||
setWindowTitle(string() << title);
|
||||
setPath(*currentPath);
|
||||
setNameFilters("All Files (*)");
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadCartridge() {
|
||||
currentPath = &config().path.current.cartridge;
|
||||
browseMode = Cartridge;
|
||||
|
||||
hide();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
setWindowTitle("Load Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "SNES cartridges (*.sfc" << reader.filterList << ");;All files (*)");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "SNES cartridges (*.sfc" << reader.extensionList << reader.compressionList << ");;"
|
||||
<< "BS-X cartridges (*.bs" << reader.compressionList << ");;"
|
||||
<< "Sufami Turbo cartridges (*.st" << reader.compressionList << ");;"
|
||||
<< "Game Boy cartridges (*.gb *.sgb *.gbc" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
filter->setCurrentIndex(config().path.current.filter);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadBaseCartridge() {
|
||||
currentPath = &config().path.current.cartridge;
|
||||
browseMode = BaseCartridge;
|
||||
|
||||
hide();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
setWindowTitle("Load Base Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "SNES cartridges (*.sfc" << reader.filterList << ");;All files (*)");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "SNES cartridges (*.sfc" << reader.extensionList << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadBsxCartridge() {
|
||||
currentPath = &config().path.current.bsx;
|
||||
browseMode = BsxCartridge;
|
||||
|
||||
hide();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
setWindowTitle("Load BS-X Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "BS-X cartridges (*.bs" << reader.filterList << ");;All files (*)");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "BS-X cartridges (*.bs" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadSufamiTurboCartridge1() {
|
||||
currentPath = &config().path.current.st;
|
||||
browseMode = SufamiTurboCartridge1;
|
||||
|
||||
hide();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
setWindowTitle("Load Slot-A Sufami Turbo Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "Sufami Turbo cartridges (*.st" << reader.filterList << ");;All files (*)");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "Sufami Turbo cartridges (*.st" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadSufamiTurboCartridge2() {
|
||||
currentPath = &config().path.current.st;
|
||||
browseMode = SufamiTurboCartridge2;
|
||||
|
||||
hide();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
setWindowTitle("Load Slot-B Sufami Turbo Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "Sufami Turbo Cartridges (*.st" << reader.filterList << ");;All files (*)");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "Sufami Turbo Cartridges (*.st" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
void DiskBrowser::loadSuperGameBoyCartridge() {
|
||||
currentPath = &config().path.current.sgb;
|
||||
browseMode = SuperGameBoyCartridge;
|
||||
|
||||
hide();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
ok->setText("Load");
|
||||
setWindowTitle("Load Super Game Boy Cartridge");
|
||||
setPath(utf8() << (config.path.rom != "" ? config.path.rom : config.path.current));
|
||||
setNameFilters(utf8() << "Game Boy cartridges (*.gb *.gbc" << reader.filterList << ");;All files (*)");
|
||||
setPath(config().path.rom == "" ? *currentPath : config().path.rom);
|
||||
setNameFilters(string()
|
||||
<< "Game Boy cartridges (*.gb *.sgb *.gbc" << reader.compressionList << ");;"
|
||||
<< "All files (*)"
|
||||
);
|
||||
show();
|
||||
}
|
||||
|
||||
|
@ -219,7 +298,7 @@ void DiskBrowser::changeItem(const QModelIndex &item) {
|
|||
ok->setEnabled(true);
|
||||
image->name = nall::basename(filename) << ".png";
|
||||
if(file::exists(image->name) == false) image->name = "";
|
||||
info->setText(utf8() << queryImageInformation());
|
||||
info->setText(string() << queryImageInformation());
|
||||
string patch = nall::basename(filename) << ".ups";
|
||||
applyPatch->setVisible(file::exists(patch));
|
||||
}
|
||||
|
@ -234,17 +313,48 @@ void DiskBrowser::loadSelected() {
|
|||
|
||||
if(browseMode == Folder || loadable == true) {
|
||||
QModelIndex item = view->currentIndex();
|
||||
config.path.current = dir(model->filePath(item).toUtf8().constData());
|
||||
if(currentPath) *currentPath = dir(model->filePath(item).toUtf8().constData());
|
||||
hide();
|
||||
|
||||
switch(browseMode) { default:
|
||||
case Folder: activePath->selectPath(filename); break;
|
||||
case Cartridge: utility.loadCartridgeNormal(filename); break;
|
||||
case BaseCartridge: loaderWindow->selectBaseCartridge(filename); break;
|
||||
case BsxCartridge: loaderWindow->selectSlot1Cartridge(filename); break;
|
||||
case SufamiTurboCartridge1: loaderWindow->selectSlot1Cartridge(filename); break;
|
||||
case SufamiTurboCartridge2: loaderWindow->selectSlot2Cartridge(filename); break;
|
||||
case SuperGameBoyCartridge: loaderWindow->selectSlot1Cartridge(filename); break;
|
||||
if(browseMode == Folder || browseMode == File) {
|
||||
callback(filename);
|
||||
} else if(browseMode == Cartridge) {
|
||||
//quick-loading mode: determine load type via active filter
|
||||
config().path.current.filter = filter->currentIndex();
|
||||
|
||||
if(config().path.current.filter == 1) { //"BS-X cartridges"
|
||||
if(config().path.bsx == "") {
|
||||
loaderWindow->loadBsxCartridge("", filename);
|
||||
} else {
|
||||
utility.loadCartridgeBsx(config().path.bsx, filename);
|
||||
}
|
||||
} else if(config().path.current.filter == 2) { //"Sufami Turbo cartridges"
|
||||
if(config().path.st == "") {
|
||||
loaderWindow->loadSufamiTurboCartridge("", filename, "");
|
||||
} else {
|
||||
utility.loadCartridgeSufamiTurbo(config().path.st, filename, "");
|
||||
}
|
||||
} else if(config().path.current.filter == 3) { //"Game Boy cartridges"
|
||||
if(SNES::supergameboy.opened() == false) {
|
||||
QMessageBox::warning(0, "Warning", "Super Game Boy support missing - cartridge cannot be loaded.");
|
||||
} else if(config().path.sgb == "") {
|
||||
loaderWindow->loadSuperGameBoyCartridge("", filename);
|
||||
} else {
|
||||
utility.loadCartridgeSuperGameBoy(config().path.sgb, filename);
|
||||
}
|
||||
} else { //"SNES cartridges" (0) or "All files" (4)
|
||||
utility.loadCartridgeNormal(filename);
|
||||
}
|
||||
} else if(browseMode == BaseCartridge) {
|
||||
loaderWindow->selectBaseCartridge(filename);
|
||||
} else if(browseMode == BsxCartridge) {
|
||||
loaderWindow->selectSlot1Cartridge(filename);
|
||||
} else if(browseMode == SufamiTurboCartridge1) {
|
||||
loaderWindow->selectSlot1Cartridge(filename);
|
||||
} else if(browseMode == SufamiTurboCartridge2) {
|
||||
loaderWindow->selectSlot2Cartridge(filename);
|
||||
} else if(browseMode == SuperGameBoyCartridge) {
|
||||
loaderWindow->selectSlot1Cartridge(filename);
|
||||
}
|
||||
} else {
|
||||
//this is a standard folder in ROM loading mode; enter into the folder
|
||||
|
@ -259,6 +369,9 @@ void DiskBrowser::setPath(const QString &reqPath) {
|
|||
disconnect(path, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePath()));
|
||||
|
||||
QString effectivePath = reqPath;
|
||||
if(effectivePath == "") {
|
||||
effectivePath = QString::fromUtf8(config().path.startup);
|
||||
}
|
||||
if(effectivePath == "<root>" || QDir(reqPath).exists() == false) {
|
||||
effectivePath = "";
|
||||
newFolder->setEnabled(false);
|
||||
|
@ -294,7 +407,7 @@ void DiskBrowser::setNameFilters(const QString &filters) {
|
|||
filterPart.split(";;", filterData);
|
||||
|
||||
for(unsigned i = 0; i < filterPart.size(); i++) {
|
||||
filter->addItem(utf8() << filterPart[i]);
|
||||
filter->addItem(filterPart[i]);
|
||||
}
|
||||
|
||||
connect(filter, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter()));
|
||||
|
@ -337,7 +450,7 @@ bool DiskBrowser::currentFilename(string &filename) {
|
|||
|
||||
if(browseMode != Folder) {
|
||||
if(model->isDir(item) == true) {
|
||||
QDir directory(utf8() << filename);
|
||||
QDir directory(filename);
|
||||
directory.setNameFilters(QStringList() << "*.sfc");
|
||||
QStringList list = directory.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
if(list.count() == 1) {
|
||||
|
@ -354,11 +467,11 @@ bool DiskBrowser::currentFilename(string &filename) {
|
|||
|
||||
void DiskBrowser::toggleShowPanel() {
|
||||
showPanel->setChecked(!showPanel->isChecked());
|
||||
config.diskBrowser.showPanel = showPanel->isChecked();
|
||||
group->setVisible(config.diskBrowser.showPanel);
|
||||
config().diskBrowser.showPanel = showPanel->isChecked();
|
||||
group->setVisible(config().diskBrowser.showPanel);
|
||||
}
|
||||
|
||||
DiskBrowser::DiskBrowser() : QbWindow(config.geometry.diskBrowser) {
|
||||
DiskBrowser::DiskBrowser() : QbWindow(config().geometry.diskBrowser) {
|
||||
setObjectName("disk-browser");
|
||||
resize(720, 480);
|
||||
|
||||
|
@ -434,7 +547,7 @@ DiskBrowser::DiskBrowser() : QbWindow(config.geometry.diskBrowser) {
|
|||
options->setMenu(menu);
|
||||
|
||||
menu->addAction(showPanel = new QbCheckAction("Show Side Panel", 0));
|
||||
showPanel->setChecked(config.diskBrowser.showPanel);
|
||||
showPanel->setChecked(config().diskBrowser.showPanel);
|
||||
|
||||
ok = new QPushButton("Ok");
|
||||
ok->setEnabled(false);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
class PathSettingWidget;
|
||||
|
||||
class FolderCreator : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -62,18 +60,22 @@ public:
|
|||
QPushButton *ok;
|
||||
QPushButton *cancel;
|
||||
QFileSystemModel *model;
|
||||
PathSettingWidget *activePath;
|
||||
|
||||
QMenu *menu;
|
||||
QbCheckAction *showPanel;
|
||||
|
||||
void chooseFolder(PathSettingWidget*, const char*);
|
||||
void inputEvent(uint16_t scancode);
|
||||
|
||||
void chooseFolder(const function<void (string)>&, string&, const char*);
|
||||
void chooseFile(const function<void (string)>&, string&, const char*);
|
||||
|
||||
void loadCartridge();
|
||||
void loadBaseCartridge();
|
||||
void loadBsxCartridge();
|
||||
void loadSufamiTurboCartridge1();
|
||||
void loadSufamiTurboCartridge2();
|
||||
void loadSuperGameBoyCartridge();
|
||||
|
||||
string queryImageInformation();
|
||||
|
||||
void setPath(const QString&);
|
||||
|
@ -92,8 +94,12 @@ public slots:
|
|||
void toggleShowPanel();
|
||||
|
||||
private:
|
||||
function<void (string)> callback;
|
||||
string *currentPath;
|
||||
|
||||
enum BrowseMode {
|
||||
Folder,
|
||||
File,
|
||||
Cartridge,
|
||||
BaseCartridge,
|
||||
BsxCartridge,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
HtmlViewerWindow::HtmlViewerWindow() : QbWindow(config.geometry.htmlViewerWindow) {
|
||||
HtmlViewerWindow::HtmlViewerWindow() : QbWindow(config().geometry.htmlViewerWindow) {
|
||||
setObjectName("html-window");
|
||||
resize(560, 480);
|
||||
|
||||
|
@ -12,7 +12,7 @@ HtmlViewerWindow::HtmlViewerWindow() : QbWindow(config.geometry.htmlViewerWindow
|
|||
}
|
||||
|
||||
void HtmlViewerWindow::show(const char *title, const char *htmlData) {
|
||||
document->setHtml(utf8() << htmlData);
|
||||
document->setHtml(string() << htmlData);
|
||||
setWindowTitle(title);
|
||||
QbWindow::show();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
LoaderWindow::LoaderWindow() : QbWindow(config.geometry.loaderWindow) {
|
||||
LoaderWindow::LoaderWindow() : QbWindow(config().geometry.loaderWindow) {
|
||||
setObjectName("loader-window");
|
||||
setMinimumWidth(520);
|
||||
|
||||
|
@ -145,17 +145,17 @@ void LoaderWindow::showWindow(const char *title) {
|
|||
}
|
||||
|
||||
void LoaderWindow::selectBaseCartridge(const char *filename) {
|
||||
baseFile->setText(utf8() << filename);
|
||||
baseFile->setText(string() << filename);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void LoaderWindow::selectSlot1Cartridge(const char *filename) {
|
||||
slot1File->setText(utf8() << filename);
|
||||
slot1File->setText(string() << filename);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void LoaderWindow::selectSlot2Cartridge(const char *filename) {
|
||||
slot2File->setText(utf8() << filename);
|
||||
slot2File->setText(string() << filename);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
|
@ -209,17 +209,17 @@ void LoaderWindow::onLoad() {
|
|||
} break;
|
||||
|
||||
case SNES::Cartridge::ModeBsx: {
|
||||
config.path.bsx = base;
|
||||
config().path.bsx = base;
|
||||
utility.loadCartridgeBsx(base, slot1);
|
||||
} break;
|
||||
|
||||
case SNES::Cartridge::ModeSufamiTurbo: {
|
||||
config.path.st = base;
|
||||
config().path.st = base;
|
||||
utility.loadCartridgeSufamiTurbo(base, slot1, slot2);
|
||||
} break;
|
||||
|
||||
case SNES::Cartridge::ModeSuperGameBoy: {
|
||||
config.path.sgb = base;
|
||||
config().path.sgb = base;
|
||||
utility.loadCartridgeSuperGameBoy(base, slot1);
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
MainWindow::MainWindow() : QbWindow(config.geometry.mainWindow) {
|
||||
MainWindow::MainWindow() : QbWindow(config().geometry.mainWindow) {
|
||||
setObjectName("main-window");
|
||||
setWindowTitle(utf8() << bsnesTitle << " v" << bsnesVersion);
|
||||
setWindowTitle(string() << bsnesTitle << " v" << bsnesVersion);
|
||||
|
||||
//menu bar
|
||||
#if defined(PLATFORM_OSX)
|
||||
|
@ -9,126 +9,176 @@ MainWindow::MainWindow() : QbWindow(config.geometry.mainWindow) {
|
|||
menuBar = new QMenuBar;
|
||||
#endif
|
||||
|
||||
system = menuBar->addMenu("System");
|
||||
system_load = system->addAction("Load Cartridge ...");
|
||||
system_load->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial = system->addMenu("Load Special");
|
||||
system_loadSpecial->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_bsxSlotted = system_loadSpecial->addAction("Load BS-X Slotted Cartridge ...");
|
||||
system_loadSpecial_bsxSlotted->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_bsx = system_loadSpecial->addAction("Load BS-X Cartridge ...");
|
||||
system_loadSpecial_bsx->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_sufamiTurbo = system_loadSpecial->addAction("Load Sufami Turbo Cartridge ...");
|
||||
system_loadSpecial_sufamiTurbo->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system_loadSpecial_superGameBoy = system_loadSpecial->addAction("Load Super Game Boy Cartridge ...");
|
||||
system_loadSpecial_superGameBoy->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
system->addSeparator();
|
||||
system->addAction(system_power = new QbCheckAction("Power", 0));
|
||||
system_reset = system->addAction("Reset");
|
||||
system_reset->setIcon(QIcon(":/16x16/view-refresh.png"));
|
||||
system->addSeparator();
|
||||
system_port1 = system->addMenu("Controller Port 1");
|
||||
system_port1->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port1->addAction(system_port1_none = new QbRadioAction("None", 0));
|
||||
system_port1->addAction(system_port1_joypad = new QbRadioAction("Joypad", 0));
|
||||
system_port1->addAction(system_port1_multitap = new QbRadioAction("Multitap", 0));
|
||||
system_port1->addAction(system_port1_mouse = new QbRadioAction("Mouse", 0));
|
||||
system_port2 = system->addMenu("Controller Port 2");
|
||||
system_port2->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port2->addAction(system_port2_none = new QbRadioAction("None", 0));
|
||||
system_port2->addAction(system_port2_joypad = new QbRadioAction("Joypad", 0));
|
||||
system_port2->addAction(system_port2_multitap = new QbRadioAction("Multitap", 0));
|
||||
system_port2->addAction(system_port2_mouse = new QbRadioAction("Mouse", 0));
|
||||
system_port2->addAction(system_port2_superscope = new QbRadioAction("Super Scope", 0));
|
||||
system_port2->addAction(system_port2_justifier = new QbRadioAction("Justifier", 0));
|
||||
system_port2->addAction(system_port2_justifiers = new QbRadioAction("Two Justifiers", 0));
|
||||
#if !defined(PLATFORM_OSX)
|
||||
system->addSeparator();
|
||||
#endif
|
||||
system_exit = system->addAction("Exit");
|
||||
system_exit->setIcon(QIcon(":/16x16/process-stop.png"));
|
||||
system_exit->setMenuRole(QAction::QuitRole);
|
||||
system = menuBar->addMenu("&System");
|
||||
|
||||
settings = menuBar->addMenu("Settings");
|
||||
settings_videoMode = settings->addMenu("Video Mode");
|
||||
settings_videoMode->setIcon(QIcon(":/16x16/video-display.png"));
|
||||
settings_videoMode->addAction(settings_videoMode_1x = new QbRadioAction("Scale 1x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_2x = new QbRadioAction("Scale 2x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_3x = new QbRadioAction("Scale 3x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_4x = new QbRadioAction("Scale 4x", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_max = new QbRadioAction("Scale Max", 0));
|
||||
settings_videoMode->addSeparator();
|
||||
settings_videoMode->addAction(settings_videoMode_correctAspectRatio = new QbCheckAction("Correct Aspect Ratio", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_fullscreen = new QbCheckAction("Fullscreen", 0));
|
||||
settings_videoMode->addSeparator();
|
||||
settings_videoMode->addAction(settings_videoMode_ntsc = new QbRadioAction("NTSC", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_pal = new QbRadioAction("PAL", 0));
|
||||
system_load = system->addAction("Load &Cartridge ...");
|
||||
system_load->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
if(filter.opened()) {
|
||||
settings_videoFilter = settings->addMenu("Video Filter");
|
||||
settings_videoFilter->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
system_loadSpecial = system->addMenu("Load &Special");
|
||||
system_loadSpecial->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
settings_videoFilter_configure = settings_videoFilter->addAction("Configure Active Filter ...");
|
||||
settings_videoFilter_configure->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_videoFilter->addSeparator();
|
||||
system_loadSpecial_bsxSlotted = system_loadSpecial->addAction("Load BS-X &Slotted Cartridge ...");
|
||||
system_loadSpecial_bsxSlotted->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
settings_videoFilter->addAction(settings_videoFilter_none = new QbRadioAction("None", 0));
|
||||
settings_videoFilter_list.add(settings_videoFilter_none);
|
||||
system_loadSpecial_bsx = system_loadSpecial->addAction("Load &BS-X Cartridge ...");
|
||||
system_loadSpecial_bsx->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
lstring filterlist;
|
||||
filterlist.split(";", filter.dl_supported());
|
||||
for(unsigned i = 0; i < filterlist.size(); i++) {
|
||||
QbRadioAction *action = new QbRadioAction(utf8() << filterlist[i], 0);
|
||||
settings_videoFilter->addAction(action);
|
||||
settings_videoFilter_list.add(action);
|
||||
}
|
||||
system_loadSpecial_sufamiTurbo = system_loadSpecial->addAction("Load Sufami &Turbo Cartridge ...");
|
||||
system_loadSpecial_sufamiTurbo->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
system_loadSpecial_superGameBoy = system_loadSpecial->addAction("Load Super &Game Boy Cartridge ...");
|
||||
system_loadSpecial_superGameBoy->setIcon(QIcon(":/16x16/document-open.png"));
|
||||
|
||||
system->addSeparator();
|
||||
|
||||
system->addAction(system_power = new QbCheckAction("&Power", 0));
|
||||
|
||||
system_reset = system->addAction("&Reset");
|
||||
system_reset->setIcon(QIcon(":/16x16/view-refresh.png"));
|
||||
|
||||
system->addSeparator();
|
||||
|
||||
system_port1 = system->addMenu("Controller Port &1");
|
||||
system_port1->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port1->addAction(system_port1_none = new QbRadioAction("&None", 0));
|
||||
system_port1->addAction(system_port1_gamepad = new QbRadioAction("&Gamepad", 0));
|
||||
system_port1->addAction(system_port1_asciipad = new QbRadioAction("&asciiPad", 0));
|
||||
system_port1->addAction(system_port1_multitap = new QbRadioAction("&Multitap", 0));
|
||||
system_port1->addAction(system_port1_mouse = new QbRadioAction("&Mouse", 0));
|
||||
|
||||
system_port2 = system->addMenu("Controller Port &2");
|
||||
system_port2->setIcon(QIcon(":/16x16/input-gaming.png"));
|
||||
system_port2->addAction(system_port2_none = new QbRadioAction("&None", 0));
|
||||
system_port2->addAction(system_port2_gamepad = new QbRadioAction("&Gamepad", 0));
|
||||
system_port2->addAction(system_port2_asciipad = new QbRadioAction("&asciiPad", 0));
|
||||
system_port2->addAction(system_port2_multitap = new QbRadioAction("&Multitap", 0));
|
||||
system_port2->addAction(system_port2_mouse = new QbRadioAction("&Mouse", 0));
|
||||
system_port2->addAction(system_port2_superscope = new QbRadioAction("&Super Scope", 0));
|
||||
system_port2->addAction(system_port2_justifier = new QbRadioAction("&Justifier", 0));
|
||||
system_port2->addAction(system_port2_justifiers = new QbRadioAction("Two &Justifiers", 0));
|
||||
|
||||
#if !defined(PLATFORM_OSX)
|
||||
system->addSeparator();
|
||||
#endif
|
||||
|
||||
system_exit = system->addAction("E&xit");
|
||||
system_exit->setIcon(QIcon(":/16x16/process-stop.png"));
|
||||
system_exit->setMenuRole(QAction::QuitRole);
|
||||
|
||||
settings = menuBar->addMenu("S&ettings");
|
||||
|
||||
settings_videoMode = settings->addMenu("Video &Mode");
|
||||
settings_videoMode->setIcon(QIcon(":/16x16/video-display.png"));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_1x = new QbRadioAction("Scale &1x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_2x = new QbRadioAction("Scale &2x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_3x = new QbRadioAction("Scale &3x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_4x = new QbRadioAction("Scale &4x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_5x = new QbRadioAction("Scale &5x", 0));
|
||||
|
||||
settings_videoMode->addSeparator();
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_correctAspectRatio = new QbCheckAction("Correct &Aspect Ratio", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_fullscreen = new QbCheckAction("&Fullscreen", 0));
|
||||
|
||||
settings_videoMode->addSeparator();
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_ntsc = new QbRadioAction("&NTSC", 0));
|
||||
settings_videoMode->addAction(settings_videoMode_pal = new QbRadioAction("&PAL", 0));
|
||||
|
||||
if(filter.opened()) {
|
||||
settings_videoFilter = settings->addMenu("Video &Filter");
|
||||
settings_videoFilter->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
|
||||
settings_videoFilter_configure = settings_videoFilter->addAction("&Configure Active Filter ...");
|
||||
settings_videoFilter_configure->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_videoFilter->addSeparator();
|
||||
|
||||
settings_videoFilter->addAction(settings_videoFilter_none = new QbRadioAction("&None", 0));
|
||||
settings_videoFilter_list.add(settings_videoFilter_none);
|
||||
|
||||
lstring filterlist;
|
||||
filterlist.split(";", filter.dl_supported());
|
||||
for(unsigned i = 0; i < filterlist.size(); i++) {
|
||||
QbRadioAction *action = new QbRadioAction(filterlist[i], 0);
|
||||
settings_videoFilter->addAction(action);
|
||||
settings_videoFilter_list.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
settings->addAction(settings_smoothVideo = new QbCheckAction("Smooth Video Output", 0));
|
||||
settings->addSeparator();
|
||||
settings->addAction(settings_muteAudio = new QbCheckAction("Mute Audio Output", 0));
|
||||
settings->addSeparator();
|
||||
settings_emulationSpeed = settings->addMenu("Emulation Speed");
|
||||
settings_emulationSpeed->setIcon(QIcon(":/16x16/appointment-new.png"));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slowest = new QbRadioAction("50%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slow = new QbRadioAction("75%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_normal = new QbRadioAction("100%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fast = new QbRadioAction("150%", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fastest = new QbRadioAction("200%", 0));
|
||||
settings_emulationSpeed->addSeparator();
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncVideo = new QbCheckAction("Sync Video", 0));
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncAudio = new QbCheckAction("Sync Audio", 0));
|
||||
settings_configuration = settings->addAction("Configuration ...");
|
||||
settings_configuration->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_configuration->setMenuRole(QAction::PreferencesRole);
|
||||
settings->addAction(settings_smoothVideo = new QbCheckAction("&Smooth Video Output", 0));
|
||||
|
||||
tools = menuBar->addMenu("Tools");
|
||||
tools_cheatEditor = tools->addAction("Cheat Editor ...");
|
||||
tools_cheatEditor->setIcon(QIcon(":/16x16/accessories-text-editor.png"));
|
||||
tools_cheatFinder = tools->addAction("Cheat Finder ...");
|
||||
tools_cheatFinder->setIcon(QIcon(":/16x16/system-search.png"));
|
||||
tools_stateManager = tools->addAction("State Manager ...");
|
||||
tools_stateManager->setIcon(QIcon(":/16x16/system-file-manager.png"));
|
||||
tools->addSeparator();
|
||||
tools_captureScreenshot = tools->addAction("Capture Screenshot");
|
||||
tools_captureScreenshot->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
tools_debugger = tools->addAction("Debugger ...");
|
||||
tools_debugger->setIcon(QIcon(":/16x16/utilities-terminal.png"));
|
||||
#if !defined(DEBUGGER)
|
||||
tools_debugger->setVisible(false);
|
||||
#endif
|
||||
settings->addSeparator();
|
||||
|
||||
help = menuBar->addMenu("Help");
|
||||
help_documentation = help->addAction("Documentation ...");
|
||||
help_documentation->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
help_license = help->addAction("License ...");
|
||||
help_license->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
#if !defined(PLATFORM_OSX)
|
||||
help->addSeparator();
|
||||
#endif
|
||||
help_about = help->addAction("About ...");
|
||||
help_about->setIcon(QIcon(":/16x16/help-browser.png"));
|
||||
help_about->setMenuRole(QAction::AboutRole);
|
||||
settings->addAction(settings_muteAudio = new QbCheckAction("&Mute Audio Output", 0));
|
||||
|
||||
settings->addSeparator();
|
||||
|
||||
settings_emulationSpeed = settings->addMenu("Emulation &Speed");
|
||||
settings_emulationSpeed->setIcon(QIcon(":/16x16/appointment-new.png"));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slowest = new QbRadioAction("50%", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_slow = new QbRadioAction("75%", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_normal = new QbRadioAction("100%", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fast = new QbRadioAction("150%", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_fastest = new QbRadioAction("200%", 0));
|
||||
|
||||
settings_emulationSpeed->addSeparator();
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncVideo = new QbCheckAction("Sync &Video", 0));
|
||||
|
||||
settings_emulationSpeed->addAction(settings_emulationSpeed_syncAudio = new QbCheckAction("Sync &Audio", 0));
|
||||
|
||||
settings_configuration = settings->addAction("&Configuration ...");
|
||||
settings_configuration->setIcon(QIcon(":/16x16/preferences-desktop.png"));
|
||||
settings_configuration->setMenuRole(QAction::PreferencesRole);
|
||||
|
||||
tools = menuBar->addMenu("&Tools");
|
||||
|
||||
tools_cheatEditor = tools->addAction("Cheat &Editor ...");
|
||||
tools_cheatEditor->setIcon(QIcon(":/16x16/accessories-text-editor.png"));
|
||||
|
||||
tools_cheatFinder = tools->addAction("Cheat &Finder ...");
|
||||
tools_cheatFinder->setIcon(QIcon(":/16x16/system-search.png"));
|
||||
|
||||
tools_stateManager = tools->addAction("&State Manager ...");
|
||||
tools_stateManager->setIcon(QIcon(":/16x16/system-file-manager.png"));
|
||||
|
||||
tools->addSeparator();
|
||||
|
||||
tools_captureScreenshot = tools->addAction("&Capture Screenshot");
|
||||
tools_captureScreenshot->setIcon(QIcon(":/16x16/image-x-generic.png"));
|
||||
|
||||
tools_debugger = tools->addAction("&Debugger ...");
|
||||
tools_debugger->setIcon(QIcon(":/16x16/utilities-terminal.png"));
|
||||
#if !defined(DEBUGGER)
|
||||
tools_debugger->setVisible(false);
|
||||
#endif
|
||||
|
||||
help = menuBar->addMenu("&Help");
|
||||
|
||||
help_documentation = help->addAction("&Documentation ...");
|
||||
help_documentation->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
|
||||
help_license = help->addAction("&License ...");
|
||||
help_license->setIcon(QIcon(":/16x16/text-x-generic.png"));
|
||||
|
||||
#if !defined(PLATFORM_OSX)
|
||||
help->addSeparator();
|
||||
#endif
|
||||
|
||||
help_about = help->addAction("&About ...");
|
||||
help_about->setIcon(QIcon(":/16x16/help-browser.png"));
|
||||
help_about->setMenuRole(QAction::AboutRole);
|
||||
|
||||
//canvas
|
||||
canvasContainer = new CanvasObject;
|
||||
|
@ -180,11 +230,13 @@ MainWindow::MainWindow() : QbWindow(config.geometry.mainWindow) {
|
|||
connect(system_power, SIGNAL(triggered()), this, SLOT(power()));
|
||||
connect(system_reset, SIGNAL(triggered()), this, SLOT(reset()));
|
||||
connect(system_port1_none, SIGNAL(triggered()), this, SLOT(setPort1None()));
|
||||
connect(system_port1_joypad, SIGNAL(triggered()), this, SLOT(setPort1Joypad()));
|
||||
connect(system_port1_gamepad, SIGNAL(triggered()), this, SLOT(setPort1Gamepad()));
|
||||
connect(system_port1_asciipad, SIGNAL(triggered()), this, SLOT(setPort1Asciipad()));
|
||||
connect(system_port1_multitap, SIGNAL(triggered()), this, SLOT(setPort1Multitap()));
|
||||
connect(system_port1_mouse, SIGNAL(triggered()), this, SLOT(setPort1Mouse()));
|
||||
connect(system_port2_none, SIGNAL(triggered()), this, SLOT(setPort2None()));
|
||||
connect(system_port2_joypad, SIGNAL(triggered()), this, SLOT(setPort2Joypad()));
|
||||
connect(system_port2_gamepad, SIGNAL(triggered()), this, SLOT(setPort2Gamepad()));
|
||||
connect(system_port2_asciipad, SIGNAL(triggered()), this, SLOT(setPort2Asciipad()));
|
||||
connect(system_port2_multitap, SIGNAL(triggered()), this, SLOT(setPort2Multitap()));
|
||||
connect(system_port2_mouse, SIGNAL(triggered()), this, SLOT(setPort2Mouse()));
|
||||
connect(system_port2_superscope, SIGNAL(triggered()), this, SLOT(setPort2SuperScope()));
|
||||
|
@ -195,7 +247,7 @@ MainWindow::MainWindow() : QbWindow(config.geometry.mainWindow) {
|
|||
connect(settings_videoMode_2x, SIGNAL(triggered()), this, SLOT(setVideoMode2x()));
|
||||
connect(settings_videoMode_3x, SIGNAL(triggered()), this, SLOT(setVideoMode3x()));
|
||||
connect(settings_videoMode_4x, SIGNAL(triggered()), this, SLOT(setVideoMode4x()));
|
||||
connect(settings_videoMode_max, SIGNAL(triggered()), this, SLOT(setVideoModeMax()));
|
||||
connect(settings_videoMode_5x, SIGNAL(triggered()), this, SLOT(setVideoMode5x()));
|
||||
connect(settings_videoMode_correctAspectRatio, SIGNAL(triggered()), this, SLOT(toggleAspectCorrection()));
|
||||
connect(settings_videoMode_fullscreen, SIGNAL(triggered()), this, SLOT(toggleFullscreen()));
|
||||
connect(settings_videoMode_ntsc, SIGNAL(triggered()), this, SLOT(setVideoNtsc()));
|
||||
|
@ -234,49 +286,52 @@ void MainWindow::syncUi() {
|
|||
system_power->setEnabled(SNES::cartridge.loaded());
|
||||
system_reset->setEnabled(SNES::cartridge.loaded() && application.power);
|
||||
|
||||
system_port1_none->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceNone);
|
||||
system_port1_joypad->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceJoypad);
|
||||
system_port1_multitap->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceMultitap);
|
||||
system_port1_mouse->setChecked (SNES::config.controller_port1 == SNES::Input::DeviceMouse);
|
||||
system_port2_none->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceNone);
|
||||
system_port2_joypad->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceJoypad);
|
||||
system_port2_multitap->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceMultitap);
|
||||
system_port2_mouse->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceMouse);
|
||||
system_port2_superscope->setChecked(SNES::config.controller_port2 == SNES::Input::DeviceSuperScope);
|
||||
system_port2_justifier->setChecked (SNES::config.controller_port2 == SNES::Input::DeviceJustifier);
|
||||
system_port2_justifiers->setChecked(SNES::config.controller_port2 == SNES::Input::DeviceJustifiers);
|
||||
system_port1_none->setChecked (config().input.port1 == ControllerPort1::None);
|
||||
system_port1_gamepad->setChecked (config().input.port1 == ControllerPort1::Gamepad);
|
||||
system_port1_asciipad->setChecked (config().input.port1 == ControllerPort1::Asciipad);
|
||||
system_port1_multitap->setChecked (config().input.port1 == ControllerPort1::Multitap);
|
||||
system_port1_mouse->setChecked (config().input.port1 == ControllerPort1::Mouse);
|
||||
|
||||
settings_videoMode_1x->setChecked (config.video.context->multiplier == 1);
|
||||
settings_videoMode_2x->setChecked (config.video.context->multiplier == 2);
|
||||
settings_videoMode_3x->setChecked (config.video.context->multiplier == 3);
|
||||
settings_videoMode_4x->setChecked (config.video.context->multiplier == 4);
|
||||
settings_videoMode_max->setChecked(config.video.context->multiplier >= 5);
|
||||
system_port2_none->setChecked (config().input.port2 == ControllerPort2::None);
|
||||
system_port2_gamepad->setChecked (config().input.port2 == ControllerPort2::Gamepad);
|
||||
system_port2_asciipad->setChecked (config().input.port2 == ControllerPort2::Asciipad);
|
||||
system_port2_multitap->setChecked (config().input.port2 == ControllerPort2::Multitap);
|
||||
system_port2_mouse->setChecked (config().input.port2 == ControllerPort2::Mouse);
|
||||
system_port2_superscope->setChecked(config().input.port2 == ControllerPort2::SuperScope);
|
||||
system_port2_justifier->setChecked (config().input.port2 == ControllerPort2::Justifier);
|
||||
system_port2_justifiers->setChecked(config().input.port2 == ControllerPort2::Justifiers);
|
||||
|
||||
settings_videoMode_correctAspectRatio->setChecked(config.video.context->correctAspectRatio);
|
||||
settings_videoMode_fullscreen->setChecked(config.video.isFullscreen);
|
||||
settings_videoMode_ntsc->setChecked(config.video.context->region == 0);
|
||||
settings_videoMode_pal->setChecked (config.video.context->region == 1);
|
||||
settings_videoMode_1x->setChecked(config().video.context->multiplier == 1);
|
||||
settings_videoMode_2x->setChecked(config().video.context->multiplier == 2);
|
||||
settings_videoMode_3x->setChecked(config().video.context->multiplier == 3);
|
||||
settings_videoMode_4x->setChecked(config().video.context->multiplier == 4);
|
||||
settings_videoMode_5x->setChecked(config().video.context->multiplier == 5);
|
||||
|
||||
settings_videoMode_correctAspectRatio->setChecked(config().video.context->correctAspectRatio);
|
||||
settings_videoMode_fullscreen->setChecked(config().video.isFullscreen);
|
||||
settings_videoMode_ntsc->setChecked(config().video.context->region == 0);
|
||||
settings_videoMode_pal->setChecked (config().video.context->region == 1);
|
||||
|
||||
if(filter.opened()) {
|
||||
//only enable configuration option if the active filter supports it ...
|
||||
settings_videoFilter_configure->setEnabled(filter.settings());
|
||||
|
||||
for(unsigned i = 0; i < settings_videoFilter_list.size(); i++) {
|
||||
settings_videoFilter_list[i]->setChecked(config.video.context->swFilter == i);
|
||||
settings_videoFilter_list[i]->setChecked(config().video.context->swFilter == i);
|
||||
}
|
||||
}
|
||||
|
||||
settings_smoothVideo->setChecked(config.video.context->hwFilter == 1);
|
||||
settings_muteAudio->setChecked(config.audio.mute);
|
||||
settings_smoothVideo->setChecked(config().video.context->hwFilter == 1);
|
||||
settings_muteAudio->setChecked(config().audio.mute);
|
||||
|
||||
settings_emulationSpeed_slowest->setChecked(config.system.speed == 0);
|
||||
settings_emulationSpeed_slow->setChecked (config.system.speed == 1);
|
||||
settings_emulationSpeed_normal->setChecked (config.system.speed == 2);
|
||||
settings_emulationSpeed_fast->setChecked (config.system.speed == 3);
|
||||
settings_emulationSpeed_fastest->setChecked(config.system.speed == 4);
|
||||
settings_emulationSpeed_slowest->setChecked(config().system.speed == 0);
|
||||
settings_emulationSpeed_slow->setChecked (config().system.speed == 1);
|
||||
settings_emulationSpeed_normal->setChecked (config().system.speed == 2);
|
||||
settings_emulationSpeed_fast->setChecked (config().system.speed == 3);
|
||||
settings_emulationSpeed_fastest->setChecked(config().system.speed == 4);
|
||||
|
||||
settings_emulationSpeed_syncVideo->setChecked(config.video.synchronize);
|
||||
settings_emulationSpeed_syncAudio->setChecked(config.audio.synchronize);
|
||||
settings_emulationSpeed_syncVideo->setChecked(config().video.synchronize);
|
||||
settings_emulationSpeed_syncAudio->setChecked(config().audio.synchronize);
|
||||
}
|
||||
|
||||
bool MainWindow::isActive() {
|
||||
|
@ -292,15 +347,15 @@ void MainWindow::loadBsxSlottedCartridge() {
|
|||
}
|
||||
|
||||
void MainWindow::loadBsxCartridge() {
|
||||
loaderWindow->loadBsxCartridge(config.path.bsx, "");
|
||||
loaderWindow->loadBsxCartridge(config().path.bsx, "");
|
||||
}
|
||||
|
||||
void MainWindow::loadSufamiTurboCartridge() {
|
||||
loaderWindow->loadSufamiTurboCartridge(config.path.st, "", "");
|
||||
loaderWindow->loadSufamiTurboCartridge(config().path.st, "", "");
|
||||
}
|
||||
|
||||
void MainWindow::loadSuperGameBoyCartridge() {
|
||||
loaderWindow->loadSuperGameBoyCartridge(config.path.sgb, "");
|
||||
loaderWindow->loadSuperGameBoyCartridge(config().path.sgb, "");
|
||||
}
|
||||
|
||||
void MainWindow::power() {
|
||||
|
@ -316,52 +371,102 @@ void MainWindow::reset() {
|
|||
utility.modifySystemState(Utility::Reset);
|
||||
}
|
||||
|
||||
void MainWindow::setPort1None() { SNES::config.controller_port1 = SNES::Input::DeviceNone; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1Joypad() { SNES::config.controller_port1 = SNES::Input::DeviceJoypad; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1Multitap() { SNES::config.controller_port1 = SNES::Input::DeviceMultitap; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1Mouse() { SNES::config.controller_port1 = SNES::Input::DeviceMouse; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2None() { SNES::config.controller_port2 = SNES::Input::DeviceNone; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Joypad() { SNES::config.controller_port2 = SNES::Input::DeviceJoypad; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Multitap() { SNES::config.controller_port2 = SNES::Input::DeviceMultitap; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Mouse() { SNES::config.controller_port2 = SNES::Input::DeviceMouse; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2SuperScope() { SNES::config.controller_port2 = SNES::Input::DeviceSuperScope; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Justifier() { SNES::config.controller_port2 = SNES::Input::DeviceJustifier; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort2Justifiers() { SNES::config.controller_port2 = SNES::Input::DeviceJustifiers; utility.updateControllers(); syncUi(); }
|
||||
void MainWindow::setPort1None() {
|
||||
config().input.port1 = ControllerPort1::None;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceNone;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Gamepad() {
|
||||
config().input.port1 = ControllerPort1::Gamepad;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Asciipad() {
|
||||
config().input.port1 = ControllerPort1::Asciipad;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Multitap() {
|
||||
config().input.port1 = ControllerPort1::Multitap;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceMultitap;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort1Mouse() {
|
||||
config().input.port1 = ControllerPort1::Mouse;
|
||||
SNES::config.controller_port1 = SNES::Input::DeviceMouse;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2None() {
|
||||
config().input.port2 = ControllerPort2::None;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceNone;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Gamepad() {
|
||||
config().input.port2 = ControllerPort2::Gamepad;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Asciipad() {
|
||||
config().input.port2 = ControllerPort2::Asciipad;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJoypad;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Multitap() {
|
||||
config().input.port2 = ControllerPort2::Multitap;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceMultitap;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Mouse() {
|
||||
config().input.port2 = ControllerPort2::Mouse;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceMouse;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2SuperScope() {
|
||||
config().input.port2 = ControllerPort2::SuperScope;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceSuperScope;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Justifier() {
|
||||
config().input.port2 = ControllerPort2::Justifier;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJustifier;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::setPort2Justifiers() {
|
||||
config().input.port2 = ControllerPort2::Justifiers;
|
||||
SNES::config.controller_port2 = SNES::Input::DeviceJustifiers;
|
||||
utility.updateControllers();
|
||||
}
|
||||
|
||||
void MainWindow::quit() {
|
||||
hide();
|
||||
application.terminate = true;
|
||||
}
|
||||
|
||||
void MainWindow::setVideoMode1x() { config.video.context->multiplier = 1; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode2x() { config.video.context->multiplier = 2; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode3x() { config.video.context->multiplier = 3; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode4x() { config.video.context->multiplier = 4; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoModeMax() { config.video.context->multiplier = 9; utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoMode1x() { utility.setScale(1); }
|
||||
void MainWindow::setVideoMode2x() { utility.setScale(2); }
|
||||
void MainWindow::setVideoMode3x() { utility.setScale(3); }
|
||||
void MainWindow::setVideoMode4x() { utility.setScale(4); }
|
||||
void MainWindow::setVideoMode5x() { utility.setScale(5); }
|
||||
|
||||
void MainWindow::toggleAspectCorrection() {
|
||||
settings_videoMode_correctAspectRatio->toggleChecked();
|
||||
config.video.context->correctAspectRatio = settings_videoMode_correctAspectRatio->isChecked();
|
||||
utility.resizeMainWindow();
|
||||
}
|
||||
void MainWindow::toggleAspectCorrection() { utility.toggleAspectCorrection(); }
|
||||
void MainWindow::toggleFullscreen() { utility.toggleFullscreen(); }
|
||||
|
||||
void MainWindow::toggleFullscreen() {
|
||||
settings_videoMode_fullscreen->toggleChecked();
|
||||
config.video.isFullscreen = settings_videoMode_fullscreen->isChecked();
|
||||
utility.updateFullscreenState();
|
||||
utility.resizeMainWindow();
|
||||
syncUi();
|
||||
}
|
||||
void MainWindow::setVideoNtsc() { utility.setNtscMode(); }
|
||||
void MainWindow::setVideoPal() { utility.setPalMode(); }
|
||||
|
||||
void MainWindow::setVideoNtsc() { config.video.context->region = 0; utility.updateVideoMode(); utility.resizeMainWindow(); syncUi(); }
|
||||
void MainWindow::setVideoPal() { config.video.context->region = 1; utility.updateVideoMode(); utility.resizeMainWindow(); syncUi(); }
|
||||
|
||||
void MainWindow::toggleSmoothVideo() {
|
||||
settings_smoothVideo->toggleChecked();
|
||||
config.video.context->hwFilter = settings_smoothVideo->isChecked();
|
||||
utility.updateHardwareFilter();
|
||||
syncUi();
|
||||
}
|
||||
void MainWindow::toggleSmoothVideo() { utility.toggleSmoothVideoOutput(); }
|
||||
|
||||
void MainWindow::configureFilter() {
|
||||
QWidget *widget = filter.settings();
|
||||
|
@ -375,7 +480,7 @@ void MainWindow::configureFilter() {
|
|||
void MainWindow::setFilter() {
|
||||
for(unsigned i = 0; i < settings_videoFilter_list.size(); i++) {
|
||||
if(sender() == settings_videoFilter_list[i]) {
|
||||
config.video.context->swFilter = i;
|
||||
config().video.context->swFilter = i;
|
||||
utility.updateSoftwareFilter();
|
||||
syncUi();
|
||||
return;
|
||||
|
@ -385,26 +490,17 @@ void MainWindow::setFilter() {
|
|||
|
||||
void MainWindow::muteAudio() {
|
||||
settings_muteAudio->toggleChecked();
|
||||
config.audio.mute = settings_muteAudio->isChecked();
|
||||
config().audio.mute = settings_muteAudio->isChecked();
|
||||
}
|
||||
|
||||
void MainWindow::setSpeedSlowest() { config.system.speed = 0; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedSlow() { config.system.speed = 1; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedNormal() { config.system.speed = 2; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFast() { config.system.speed = 3; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFastest() { config.system.speed = 4; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedSlowest() { config().system.speed = 0; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedSlow() { config().system.speed = 1; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedNormal() { config().system.speed = 2; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFast() { config().system.speed = 3; utility.updateEmulationSpeed(); syncUi(); }
|
||||
void MainWindow::setSpeedFastest() { config().system.speed = 4; utility.updateEmulationSpeed(); syncUi(); }
|
||||
|
||||
void MainWindow::syncVideo() {
|
||||
settings_emulationSpeed_syncVideo->toggleChecked();
|
||||
config.video.synchronize = settings_emulationSpeed_syncVideo->isChecked();
|
||||
utility.updateAvSync();
|
||||
}
|
||||
|
||||
void MainWindow::syncAudio() {
|
||||
settings_emulationSpeed_syncAudio->toggleChecked();
|
||||
config.audio.synchronize = settings_emulationSpeed_syncAudio->isChecked();
|
||||
utility.updateAvSync();
|
||||
}
|
||||
void MainWindow::syncVideo() { utility.toggleSynchronizeVideo(); }
|
||||
void MainWindow::syncAudio() { utility.toggleSynchronizeAudio(); }
|
||||
|
||||
void MainWindow::showConfigWindow() { settingsWindow->show(); }
|
||||
|
||||
|
|
|
@ -31,12 +31,14 @@ public:
|
|||
QAction *system_reset;
|
||||
QMenu *system_port1;
|
||||
QbRadioAction *system_port1_none;
|
||||
QbRadioAction *system_port1_joypad;
|
||||
QbRadioAction *system_port1_gamepad;
|
||||
QbRadioAction *system_port1_asciipad;
|
||||
QbRadioAction *system_port1_multitap;
|
||||
QbRadioAction *system_port1_mouse;
|
||||
QMenu *system_port2;
|
||||
QbRadioAction *system_port2_none;
|
||||
QbRadioAction *system_port2_joypad;
|
||||
QbRadioAction *system_port2_gamepad;
|
||||
QbRadioAction *system_port2_asciipad;
|
||||
QbRadioAction *system_port2_multitap;
|
||||
QbRadioAction *system_port2_mouse;
|
||||
QbRadioAction *system_port2_superscope;
|
||||
|
@ -49,7 +51,7 @@ public:
|
|||
QbRadioAction *settings_videoMode_2x;
|
||||
QbRadioAction *settings_videoMode_3x;
|
||||
QbRadioAction *settings_videoMode_4x;
|
||||
QbRadioAction *settings_videoMode_max;
|
||||
QbRadioAction *settings_videoMode_5x;
|
||||
QbCheckAction *settings_videoMode_correctAspectRatio;
|
||||
QbCheckAction *settings_videoMode_fullscreen;
|
||||
QbRadioAction *settings_videoMode_ntsc;
|
||||
|
@ -79,10 +81,10 @@ public:
|
|||
QAction *help_documentation;
|
||||
QAction *help_license;
|
||||
QAction *help_about;
|
||||
//
|
||||
|
||||
CanvasObject *canvasContainer;
|
||||
QVBoxLayout *canvasLayout;
|
||||
CanvasWidget *canvas;
|
||||
QVBoxLayout *canvasLayout;
|
||||
CanvasWidget *canvas;
|
||||
QLabel *systemState;
|
||||
|
||||
void syncUi();
|
||||
|
@ -99,11 +101,13 @@ public slots:
|
|||
void power();
|
||||
void reset();
|
||||
void setPort1None();
|
||||
void setPort1Joypad();
|
||||
void setPort1Gamepad();
|
||||
void setPort1Asciipad();
|
||||
void setPort1Multitap();
|
||||
void setPort1Mouse();
|
||||
void setPort2None();
|
||||
void setPort2Joypad();
|
||||
void setPort2Gamepad();
|
||||
void setPort2Asciipad();
|
||||
void setPort2Multitap();
|
||||
void setPort2Mouse();
|
||||
void setPort2SuperScope();
|
||||
|
@ -114,7 +118,7 @@ public slots:
|
|||
void setVideoMode2x();
|
||||
void setVideoMode3x();
|
||||
void setVideoMode4x();
|
||||
void setVideoModeMax();
|
||||
void setVideoMode5x();
|
||||
void toggleAspectCorrection();
|
||||
void toggleFullscreen();
|
||||
void setVideoNtsc();
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
Configuration &config() {
|
||||
static Configuration configuration;
|
||||
return configuration;
|
||||
}
|
||||
|
||||
bool Configuration::load(const char *filename) {
|
||||
if(configuration::load(filename) == false) return false;
|
||||
SNES::config.superfx.speed = max(0, min(2, SNES::config.superfx.speed));
|
||||
|
@ -5,21 +10,6 @@ bool Configuration::load(const char *filename) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Configuration::attachJoypad(Configuration::Input::Joypad &joypad, const char *name) {
|
||||
attach(joypad.up = "none", string() << name << ".up");
|
||||
attach(joypad.down = "none", string() << name << ".down");
|
||||
attach(joypad.left = "none", string() << name << ".left");
|
||||
attach(joypad.right = "none", string() << name << ".right");
|
||||
attach(joypad.a = "none", string() << name << ".a");
|
||||
attach(joypad.b = "none", string() << name << ".b");
|
||||
attach(joypad.x = "none", string() << name << ".x");
|
||||
attach(joypad.y = "none", string() << name << ".y");
|
||||
attach(joypad.l = "none", string() << name << ".l");
|
||||
attach(joypad.r = "none", string() << name << ".r");
|
||||
attach(joypad.select = "none", string() << name << ".select");
|
||||
attach(joypad.start = "none", string() << name << ".start");
|
||||
}
|
||||
|
||||
Configuration::Configuration() {
|
||||
//========
|
||||
//external
|
||||
|
@ -62,16 +52,25 @@ Configuration::Configuration() {
|
|||
attach(file.autodetect_type = false, "file.autodetectType");
|
||||
attach(file.bypass_patch_crc32 = false, "file.bypassPatchCrc32");
|
||||
|
||||
attach(path.current = "", "path.current");
|
||||
attach(path.rom = "", "path.rom");
|
||||
attach(path.save = "", "path.save");
|
||||
attach(path.state = "", "path.state");
|
||||
attach(path.patch = "", "path.patch");
|
||||
attach(path.cheat = "", "path.cheat");
|
||||
attach(path.data = "", "path.data");
|
||||
attach(path.bsx = "", "path.bsx");
|
||||
attach(path.st = "", "path.st");
|
||||
attach(path.sgb = "", "path.sgb");
|
||||
attach(path.rom = "", "path.rom");
|
||||
attach(path.save = "", "path.save");
|
||||
attach(path.state = "", "path.state");
|
||||
attach(path.patch = "", "path.patch");
|
||||
attach(path.cheat = "", "path.cheat");
|
||||
attach(path.data = "", "path.data");
|
||||
attach(path.bsx = "", "path.bsx");
|
||||
attach(path.st = "", "path.st");
|
||||
attach(path.sgb = "", "path.sgb");
|
||||
attach(path.fragmentShader = "", "path.fragmentShader");
|
||||
attach(path.vertexShader = "", "path.vertexShader");
|
||||
|
||||
attach(path.current.folder = "", "path.current.folder");
|
||||
attach(path.current.shader = "", "path.current.shader");
|
||||
attach(path.current.cartridge = "", "path.current.cartridge");
|
||||
attach(path.current.bsx = "", "path.current.bsx");
|
||||
attach(path.current.st = "", "path.current.st");
|
||||
attach(path.current.sgb = "", "path.current.sgb");
|
||||
attach(path.current.filter = 0, "path.current.filter");
|
||||
|
||||
video.context = &video.windowed;
|
||||
attach(video.isFullscreen = false, "video.isFullscreen");
|
||||
|
@ -80,6 +79,7 @@ Configuration::Configuration() {
|
|||
attach(video.contrastAdjust = 0, "video.contrastAdjust");
|
||||
attach(video.brightnessAdjust = 0, "video.brightnessAdjust");
|
||||
attach(video.gammaAdjust = 0, "video.gammaAdjust");
|
||||
attach(video.scanlineAdjust = 100, "video.scanlineAdjust");
|
||||
attach(video.enableGammaRamp = true, "video.enableGammaRamp");
|
||||
|
||||
attach(video.ntscAspectRatio = 54.0 / 47.0, "video.ntscAspectRatio", "NTSC aspect ratio (x / y)");
|
||||
|
@ -107,98 +107,21 @@ Configuration::Configuration() {
|
|||
attach(audio.outputFrequency = 48000, "audio.outputFrequency");
|
||||
attach(audio.inputFrequency = 32000, "audio.inputFrequency");
|
||||
|
||||
attach(input.port1 = ControllerPort1::Gamepad, "input.port1");
|
||||
attach(input.port2 = ControllerPort2::Gamepad, "input.port2");
|
||||
attach(input.focusPolicy = Input::FocusPolicyIgnoreInput, "input.focusPolicy");
|
||||
attach(input.allowInvalidInput = false, "input.allowInvalidInput", "Allow up+down / left+right combinations; may trigger bugs in some games");
|
||||
|
||||
attach(input.joypad1.up = "keyboard00.up", "input.joypad1.up");
|
||||
attach(input.joypad1.down = "keyboard00.down", "input.joypad1.down");
|
||||
attach(input.joypad1.left = "keyboard00.left", "input.joypad1.left");
|
||||
attach(input.joypad1.right = "keyboard00.right", "input.joypad1.right");
|
||||
attach(input.joypad1.a = "keyboard00.x", "input.joypad1.a");
|
||||
attach(input.joypad1.b = "keyboard00.z", "input.joypad1.b");
|
||||
attach(input.joypad1.x = "keyboard00.s", "input.joypad1.x");
|
||||
attach(input.joypad1.y = "keyboard00.a", "input.joypad1.y");
|
||||
attach(input.joypad1.l = "keyboard00.d", "input.joypad1.l");
|
||||
attach(input.joypad1.r = "keyboard00.c", "input.joypad1.r");
|
||||
attach(input.joypad1.select = "keyboard00.rshift", "input.joypad1.select");
|
||||
attach(input.joypad1.start = "keyboard00.return", "input.joypad1.start");
|
||||
|
||||
//these are all mapped to "none" by default
|
||||
attachJoypad(input.joypad2, "input.joypad2");
|
||||
attachJoypad(input.multitap1a, "input.multitap1a");
|
||||
attachJoypad(input.multitap1b, "input.multitap1b");
|
||||
attachJoypad(input.multitap1c, "input.multitap1c");
|
||||
attachJoypad(input.multitap1d, "input.multitap1d");
|
||||
attachJoypad(input.multitap2a, "input.multitap2a");
|
||||
attachJoypad(input.multitap2b, "input.multitap2b");
|
||||
attachJoypad(input.multitap2c, "input.multitap2c");
|
||||
attachJoypad(input.multitap2d, "input.multitap2d");
|
||||
|
||||
attach(input.mouse1.x = "mouse00.x", "input.mouse1.x");
|
||||
attach(input.mouse1.y = "mouse00.y", "input.mouse1.y");
|
||||
attach(input.mouse1.left = "mouse00.button00", "input.mouse1.left");
|
||||
attach(input.mouse1.right = "mouse00.button02", "input.mouse1.right");
|
||||
|
||||
//more likely a user will only use one mouse at a time, than for a system to have two mice
|
||||
attach(input.mouse2.x = "mouse00.x", "input.mouse2.x");
|
||||
attach(input.mouse2.y = "mouse00.y", "input.mouse2.y");
|
||||
attach(input.mouse2.left = "mouse00.button00", "input.mouse2.left");
|
||||
attach(input.mouse2.right = "mouse00.button02", "input.mouse2.right");
|
||||
|
||||
//unlikely a user will have a five-button mouse for turbo / pause mapping
|
||||
attach(input.superscope.x = "mouse00.x", "input.superscope.x");
|
||||
attach(input.superscope.y = "mouse00.y", "input.superscope.y");
|
||||
attach(input.superscope.trigger = "mouse00.button00", "input.superscope.trigger");
|
||||
attach(input.superscope.cursor = "mouse00.button02", "input.superscope.cursor");
|
||||
attach(input.superscope.turbo = "keyboard00.t", "input.superscope.turbo");
|
||||
attach(input.superscope.pause = "keyboard00.p", "input.superscope.pause");
|
||||
|
||||
attach(input.justifier1.x = "mouse00.x", "input.justifier1.x");
|
||||
attach(input.justifier1.y = "mouse00.y", "input.justifier1.y");
|
||||
attach(input.justifier1.trigger = "mouse00.button00", "input.justifier1.trigger");
|
||||
attach(input.justifier1.start = "mouse00.button02", "input.jusitifer1.start");
|
||||
|
||||
attach(input.justifier2.x = "mouse01.x", "input.justifier2.x");
|
||||
attach(input.justifier2.y = "mouse01.y", "input.justifier2.y");
|
||||
attach(input.justifier2.trigger = "mouse01.button00", "input.justifier2.trigger");
|
||||
attach(input.justifier2.start = "mouse01.button02", "input.justifier2.start");
|
||||
|
||||
attach(input.uiGeneral.loadCartridge = "none", "input.uiGeneral.loadCartridge");
|
||||
attach(input.uiGeneral.pauseEmulation = "keyboard00.pause", "input.uiGeneral.pauseEmulation");
|
||||
attach(input.uiGeneral.resetSystem = "none", "input.uiGeneral.resetSystem");
|
||||
attach(input.uiGeneral.powerCycleSystem = "none", "input.uiGeneral.powerCycleSystem");
|
||||
|
||||
attach(input.uiGeneral.captureScreenshot = "none", "input.uiGeneral.captureScreenshot");
|
||||
attach(input.uiGeneral.showStateManager = "keyboard00.f3", "input.uiGeneral.showStateManager");
|
||||
|
||||
attach(input.uiGeneral.quickLoad1 = "keyboard00.f4", "input.uiGeneral.quickLoad1");
|
||||
attach(input.uiGeneral.quickLoad2 = "none", "input.uiGeneral.quickLoad2");
|
||||
attach(input.uiGeneral.quickLoad3 = "none", "input.uiGeneral.quickLoad3");
|
||||
attach(input.uiGeneral.quickSave1 = "keyboard00.f2", "input.uiGeneral.quickSave1");
|
||||
attach(input.uiGeneral.quickSave2 = "none", "input.uiGeneral.quickSave2");
|
||||
attach(input.uiGeneral.quickSave3 = "none", "input.uiGeneral.quickSave3");
|
||||
|
||||
attach(input.uiGeneral.lowerSpeed = "keyboard00.divide", "input.uiGeneral.lowerSpeed");
|
||||
attach(input.uiGeneral.raiseSpeed = "keyboard00.multiply", "input.uiGeneral.raiseSpeed");
|
||||
attach(input.uiGeneral.toggleCheatSystem = "none", "input.uiGeneral.toggleCheatSystem");
|
||||
attach(input.uiGeneral.toggleFullscreen = "keyboard00.f11", "input.uiGeneral.toggleFullscreen");
|
||||
attach(input.uiGeneral.toggleMenu = "keyboard00.escape", "input.uiGeneral.toggleMenu");
|
||||
attach(input.uiGeneral.toggleStatus = "keyboard00.escape", "input.uiGeneral.toggleStatus");
|
||||
attach(input.uiGeneral.exitEmulator = "none", "input.uiGeneral.exitEmulator");
|
||||
|
||||
attach(geometry.mainWindow = "", "geometry.mainWindow");
|
||||
attach(geometry.loaderWindow = "", "geometry.loaderWindow");
|
||||
attach(geometry.htmlViewerWindow = "", "geometry.htmlViewerWindow");
|
||||
attach(geometry.aboutWindow = "", "geometry.aboutWindow");
|
||||
attach(geometry.diskBrowser = "", "geometry.diskBrowser");
|
||||
attach(geometry.folderCreator = "", "geometry.folderCreator");
|
||||
attach(geometry.settingsWindow = "", "geometry.settingsWindow");
|
||||
attach(geometry.inputCaptureWindow = "", "geometry.inputCaptureWindow");
|
||||
attach(geometry.inputMouseCaptureWindow = "", "geometry.inputMouseCaptureWindow");
|
||||
attach(geometry.inputCalibrationWindow = "", "geometry.inputCalibrationWindow");
|
||||
attach(geometry.toolsWindow = "", "geometry.toolsWindow");
|
||||
attach(geometry.debugger = "", "geometry.debugger");
|
||||
attach(geometry.breakpointEditor = "", "geometry.breakpointEditor");
|
||||
attach(geometry.memoryEditor = "", "geometry.memoryEditor");
|
||||
attach(geometry.vramViewer = "", "geometry.vramViewer");
|
||||
attach(geometry.mainWindow = "", "geometry.mainWindow");
|
||||
attach(geometry.loaderWindow = "", "geometry.loaderWindow");
|
||||
attach(geometry.htmlViewerWindow = "", "geometry.htmlViewerWindow");
|
||||
attach(geometry.aboutWindow = "", "geometry.aboutWindow");
|
||||
attach(geometry.diskBrowser = "", "geometry.diskBrowser");
|
||||
attach(geometry.folderCreator = "", "geometry.folderCreator");
|
||||
attach(geometry.settingsWindow = "", "geometry.settingsWindow");
|
||||
attach(geometry.toolsWindow = "", "geometry.toolsWindow");
|
||||
attach(geometry.debugger = "", "geometry.debugger");
|
||||
attach(geometry.breakpointEditor = "", "geometry.breakpointEditor");
|
||||
attach(geometry.memoryEditor = "", "geometry.memoryEditor");
|
||||
attach(geometry.vramViewer = "", "geometry.vramViewer");
|
||||
}
|
||||
|
|
|
@ -20,15 +20,21 @@ public:
|
|||
struct Path {
|
||||
string base; //binary path
|
||||
string user; //user profile path (bsnes.cfg, ...)
|
||||
string current; //current working directory (path to currently loaded cartridge)
|
||||
string startup; //startup path
|
||||
string rom, save, state, patch, cheat, data;
|
||||
string bsx, st, sgb;
|
||||
string fragmentShader, vertexShader;
|
||||
|
||||
struct Current {
|
||||
string folder, shader, cartridge, bsx, st, sgb;
|
||||
unsigned filter; //current active filter for "Load Cartridge"
|
||||
} current;
|
||||
} path;
|
||||
|
||||
struct Video {
|
||||
bool isFullscreen;
|
||||
bool synchronize;
|
||||
signed contrastAdjust, brightnessAdjust, gammaAdjust;
|
||||
signed contrastAdjust, brightnessAdjust, gammaAdjust, scanlineAdjust;
|
||||
bool enableGammaRamp;
|
||||
double ntscAspectRatio, palAspectRatio;
|
||||
|
||||
|
@ -46,49 +52,11 @@ public:
|
|||
} audio;
|
||||
|
||||
struct Input {
|
||||
unsigned port1;
|
||||
unsigned port2;
|
||||
enum policy_t { FocusPolicyPauseEmulation, FocusPolicyIgnoreInput, FocusPolicyAllowInput };
|
||||
unsigned focusPolicy;
|
||||
bool allowInvalidInput;
|
||||
|
||||
struct Joypad {
|
||||
string up, down, left, right, a, b, x, y, l, r, select, start;
|
||||
} joypad1, joypad2,
|
||||
multitap1a, multitap1b, multitap1c, multitap1d,
|
||||
multitap2a, multitap2b, multitap2c, multitap2d;
|
||||
|
||||
struct Mouse {
|
||||
string x, y, left, right;
|
||||
} mouse1, mouse2;
|
||||
|
||||
struct SuperScope {
|
||||
string x, y, trigger, turbo, cursor, pause;
|
||||
} superscope;
|
||||
|
||||
struct Justifier {
|
||||
string x, y, trigger, start;
|
||||
} justifier1, justifier2;
|
||||
|
||||
struct UiGeneral {
|
||||
string loadCartridge;
|
||||
string pauseEmulation;
|
||||
string resetSystem;
|
||||
string powerCycleSystem;
|
||||
string captureScreenshot;
|
||||
string showStateManager;
|
||||
string quickLoad1;
|
||||
string quickLoad2;
|
||||
string quickLoad3;
|
||||
string quickSave1;
|
||||
string quickSave2;
|
||||
string quickSave3;
|
||||
string lowerSpeed;
|
||||
string raiseSpeed;
|
||||
string toggleCheatSystem;
|
||||
string toggleFullscreen;
|
||||
string toggleMenu;
|
||||
string toggleStatus;
|
||||
string exitEmulator;
|
||||
} uiGeneral;
|
||||
} input;
|
||||
|
||||
struct Geometry {
|
||||
|
@ -98,14 +66,8 @@ public:
|
|||
string aboutWindow;
|
||||
string diskBrowser;
|
||||
string folderCreator;
|
||||
|
||||
string settingsWindow;
|
||||
string inputCaptureWindow;
|
||||
string inputMouseCaptureWindow;
|
||||
string inputCalibrationWindow;
|
||||
|
||||
string toolsWindow;
|
||||
|
||||
string debugger;
|
||||
string breakpointEditor;
|
||||
string memoryEditor;
|
||||
|
@ -113,6 +75,7 @@ public:
|
|||
} geometry;
|
||||
|
||||
bool load(const char *filename);
|
||||
void attachJoypad(Configuration::Input::Joypad &joypad, const char *name);
|
||||
Configuration();
|
||||
} config;
|
||||
};
|
||||
|
||||
Configuration &config();
|
||||
|
|
|
@ -58,7 +58,7 @@ void BreakpointItem::toggle() {
|
|||
}
|
||||
}
|
||||
|
||||
BreakpointEditor::BreakpointEditor() : QbWindow(config.geometry.breakpointEditor) {
|
||||
BreakpointEditor::BreakpointEditor() : QbWindow(config().geometry.breakpointEditor) {
|
||||
setObjectName("breakpoint-editor");
|
||||
setWindowTitle("Breakpoint Editor");
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "memory.cpp"
|
||||
#include "vramviewer.cpp"
|
||||
|
||||
Debugger::Debugger() : QbWindow(config.geometry.debugger) {
|
||||
Debugger::Debugger() : QbWindow(config().geometry.debugger) {
|
||||
setObjectName("debugger");
|
||||
setWindowTitle("Debugger");
|
||||
|
||||
|
@ -133,7 +133,7 @@ void Debugger::stepAction() {
|
|||
void Debugger::tracerUpdate() {
|
||||
if(SNES::debugger.trace_cpu || SNES::debugger.trace_smp) {
|
||||
if(SNES::debugger.tracefile.open() == false) {
|
||||
SNES::debugger.tracefile.open(utf8() << config.path.data << "trace.log", file::mode_write);
|
||||
SNES::debugger.tracefile.open(string() << config().path.data << "trace.log", file::mode_write);
|
||||
}
|
||||
} else if(!SNES::debugger.trace_cpu && !SNES::debugger.trace_smp) {
|
||||
if(SNES::debugger.tracefile.open() == true) {
|
||||
|
@ -158,19 +158,19 @@ void Debugger::event() {
|
|||
switch(SNES::debugger.break_event) {
|
||||
case SNES::Debugger::BreakpointHit: {
|
||||
unsigned n = SNES::debugger.breakpoint_hit;
|
||||
echo(utf8() << "Breakpoint " << n << " hit (" << SNES::debugger.breakpoint[n].counter << ").<br>");
|
||||
echo(string() << "Breakpoint " << n << " hit (" << SNES::debugger.breakpoint[n].counter << ").<br>");
|
||||
|
||||
if(SNES::debugger.breakpoint[n].mode == SNES::Debugger::Breakpoint::Exec) {
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::CPUBus) {
|
||||
SNES::debugger.step_cpu = true;
|
||||
SNES::cpu.disassemble_opcode(t);
|
||||
echo(utf8() << t << "<br>");
|
||||
echo(string() << t << "<br>");
|
||||
}
|
||||
|
||||
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::APURAM) {
|
||||
SNES::debugger.step_smp = true;
|
||||
SNES::smp.disassemble_opcode(t);
|
||||
echo(utf8() << t << "<br>");
|
||||
echo(string() << t << "<br>");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -179,14 +179,14 @@ void Debugger::event() {
|
|||
SNES::cpu.disassemble_opcode(t);
|
||||
string s = t;
|
||||
s.replace(" ", " ");
|
||||
echo(utf8() << "<font color='#0000a0'>" << s << "</font><br>");
|
||||
echo(string() << "<font color='#0000a0'>" << s << "</font><br>");
|
||||
} break;
|
||||
|
||||
case SNES::Debugger::SMPStep: {
|
||||
SNES::smp.disassemble_opcode(t);
|
||||
string s = t;
|
||||
s.replace(" ", " ");
|
||||
echo(utf8() << "<font color='#a00000'>" << s << "</font><br>");
|
||||
echo(string() << "<font color='#a00000'>" << s << "</font><br>");
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ void HexEditor::update() {
|
|||
if(y != 15) output << "<br>";
|
||||
}
|
||||
|
||||
setHtml(utf8() << output);
|
||||
setHtml(output);
|
||||
}
|
||||
|
||||
void HexEditor::sliderMoved() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
MemoryEditor::MemoryEditor() : QbWindow(config.geometry.memoryEditor) {
|
||||
MemoryEditor::MemoryEditor() : QbWindow(config().geometry.memoryEditor) {
|
||||
setObjectName("memory-editor");
|
||||
setWindowTitle("Memory Editor");
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
VramViewer::VramViewer() : QbWindow(config.geometry.vramViewer) {
|
||||
VramViewer::VramViewer() : QbWindow(config().geometry.vramViewer) {
|
||||
setObjectName("vram-viewer");
|
||||
setWindowTitle("Video RAM Viewer");
|
||||
|
||||
|
|
|
@ -0,0 +1,372 @@
|
|||
namespace Controllers {
|
||||
|
||||
void TurboInput::cache() {
|
||||
if(state) {
|
||||
cachedState = (counter < holdHi ? state : 0);
|
||||
if(++counter >= holdHi + holdLo) counter = 0;
|
||||
} else {
|
||||
cachedState = 0;
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TurboInput::TurboInput(const char *label, const char *configName) :
|
||||
DigitalInput(label, configName) {
|
||||
holdHi = 2;
|
||||
holdLo = 2;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
int16_t Gamepad::status(unsigned index, unsigned id) const {
|
||||
switch(id) {
|
||||
case SNES::Input::JoypadUp: return up.cachedState;
|
||||
case SNES::Input::JoypadDown: return down.cachedState;
|
||||
case SNES::Input::JoypadLeft: return left.cachedState;
|
||||
case SNES::Input::JoypadRight: return right.cachedState;
|
||||
case SNES::Input::JoypadA: return a.cachedState | turboA.cachedState;
|
||||
case SNES::Input::JoypadB: return b.cachedState | turboB.cachedState;
|
||||
case SNES::Input::JoypadX: return x.cachedState | turboX.cachedState;
|
||||
case SNES::Input::JoypadY: return y.cachedState | turboY.cachedState;
|
||||
case SNES::Input::JoypadL: return l.cachedState | turboL.cachedState;
|
||||
case SNES::Input::JoypadR: return r.cachedState | turboR.cachedState;
|
||||
case SNES::Input::JoypadSelect: return select.cachedState;
|
||||
case SNES::Input::JoypadStart: return start.cachedState;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gamepad::Gamepad(unsigned category, const char *label, const char *configName) :
|
||||
InputGroup(category, label),
|
||||
up("Up", string() << "input." << configName << ".up"),
|
||||
down("Down", string() << "input." << configName << ".down"),
|
||||
left("Left", string() << "input." << configName << ".left"),
|
||||
right("Right", string() << "input." << configName << ".right"),
|
||||
b("B", string() << "input." << configName << ".b"),
|
||||
a("A", string() << "input." << configName << ".a"),
|
||||
y("Y", string() << "input." << configName << ".y"),
|
||||
x("X", string() << "input." << configName << ".x"),
|
||||
l("L", string() << "input." << configName << ".l"),
|
||||
r("R", string() << "input." << configName << ".r"),
|
||||
select("Select", string() << "input." << configName << ".select"),
|
||||
start("Start", string() << "input." << configName << ".start"),
|
||||
turboB("Turbo B", string() << "input." << configName << ".turboB"),
|
||||
turboA("Turbo A", string() << "input." << configName << ".turboA"),
|
||||
turboY("Turbo Y", string() << "input." << configName << ".turboY"),
|
||||
turboX("Turbo X", string() << "input." << configName << ".turboX"),
|
||||
turboL("Turbo L", string() << "input." << configName << ".turboL"),
|
||||
turboR("Turbo R", string() << "input." << configName << ".turboR") {
|
||||
attach(&up); attach(&down); attach(&left); attach(&right);
|
||||
attach(&b); attach(&a); attach(&y); attach(&x);
|
||||
attach(&l); attach(&r); attach(&select); attach(&start);
|
||||
attach(&turboB); attach(&turboA); attach(&turboY); attach(&turboX);
|
||||
attach(&turboL); attach(&turboR);
|
||||
|
||||
if(this == &gamepad1) {
|
||||
up.name = "KB0::Up";
|
||||
down.name = "KB0::Down";
|
||||
left.name = "KB0::Left";
|
||||
right.name = "KB0::Right";
|
||||
b.name = "KB0::Z";
|
||||
a.name = "KB0::X";
|
||||
y.name = "KB0::A";
|
||||
x.name = "KB0::S";
|
||||
l.name = "KB0::D";
|
||||
r.name = "KB0::C";
|
||||
select.name = "KB0::Apostrophe";
|
||||
start.name = "KB0::Return";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int16_t Multitap::status(unsigned index, unsigned id) const {
|
||||
switch(index & 3) { default:
|
||||
case 0: return port1.status(index, id);
|
||||
case 1: return port2.status(index, id);
|
||||
case 2: return port3.status(index, id);
|
||||
case 3: return port4.status(index, id);
|
||||
}
|
||||
}
|
||||
|
||||
Multitap::Multitap(Gamepad &port1_, Gamepad &port2_, Gamepad &port3_, Gamepad &port4_) :
|
||||
InputGroup(InputCategory::Hidden, "Multitap"),
|
||||
port1(port1_), port2(port2_), port3(port3_), port4(port4_) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void AsciiSwitch::poll() {
|
||||
DigitalInput::poll();
|
||||
|
||||
//only change state when controller is active
|
||||
if(!parent) return;
|
||||
if(parent->category == InputCategory::Port1 && mapper().port1 != parent) return;
|
||||
if(parent->category == InputCategory::Port2 && mapper().port2 != parent) return;
|
||||
|
||||
if(previousState != state && state) {
|
||||
switch(mode) {
|
||||
case Off: mode = Turbo; utility.showMessage(string() << label << " set to turbo."); break;
|
||||
case Turbo: mode = Auto; utility.showMessage(string() << label << " set to auto."); break;
|
||||
case Auto: mode = Off; utility.showMessage(string() << label << " set to off."); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsciiSwitch::AsciiSwitch(const char *label, const char *configName) :
|
||||
DigitalInput(label, configName) {
|
||||
mode = Off;
|
||||
}
|
||||
|
||||
void AsciiInput::cache() {
|
||||
if(asciiSwitch->mode == AsciiSwitch::Off) {
|
||||
cachedState = state;
|
||||
} else if(asciiSwitch->mode == AsciiSwitch::Turbo) {
|
||||
if(state) {
|
||||
cachedState = (counter < holdHi ? state : 0);
|
||||
if(++counter >= holdHi + holdLo) counter = 0;
|
||||
} else {
|
||||
cachedState = 0;
|
||||
counter = 0;
|
||||
}
|
||||
} else if(asciiSwitch->mode == AsciiSwitch::Auto) {
|
||||
cachedState = (counter < holdHi);
|
||||
if(++counter >= holdHi + holdLo) counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AsciiInput::AsciiInput(const char *label, const char *configName) :
|
||||
DigitalInput(label, configName) {
|
||||
holdHi = 2;
|
||||
holdLo = 2;
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
void AsciiSlowMotion::poll() {
|
||||
DigitalInput::poll();
|
||||
|
||||
//only change state when controller is active
|
||||
if(!parent) return;
|
||||
if(parent->category == InputCategory::Port1 && mapper().port1 != parent) return;
|
||||
if(parent->category == InputCategory::Port2 && mapper().port2 != parent) return;
|
||||
|
||||
if(previousState != state && state) {
|
||||
if(enabled == false) {
|
||||
enabled = true;
|
||||
utility.showMessage(string() << label << " enabled.");
|
||||
} else {
|
||||
enabled = false;
|
||||
utility.showMessage(string() << label << " disabled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsciiSlowMotion::cache() {
|
||||
if(enabled == false) {
|
||||
cachedState = 0;
|
||||
} else {
|
||||
cachedState = counter < holdHi;
|
||||
if(++counter >= holdHi + holdLo) counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AsciiSlowMotion::AsciiSlowMotion(const char *label, const char *configName) :
|
||||
DigitalInput(label, configName) {
|
||||
enabled = false;
|
||||
holdHi = 2;
|
||||
holdLo = 2;
|
||||
}
|
||||
|
||||
int16_t Asciipad::status(unsigned index, unsigned id) const {
|
||||
switch(id) {
|
||||
case SNES::Input::JoypadUp: return up.cachedState;
|
||||
case SNES::Input::JoypadDown: return down.cachedState;
|
||||
case SNES::Input::JoypadLeft: return left.cachedState;
|
||||
case SNES::Input::JoypadRight: return right.cachedState;
|
||||
case SNES::Input::JoypadA: return a.cachedState;
|
||||
case SNES::Input::JoypadB: return b.cachedState;
|
||||
case SNES::Input::JoypadX: return x.cachedState;
|
||||
case SNES::Input::JoypadY: return y.cachedState;
|
||||
case SNES::Input::JoypadL: return l.cachedState;
|
||||
case SNES::Input::JoypadR: return r.cachedState;
|
||||
case SNES::Input::JoypadSelect: return select.cachedState;
|
||||
case SNES::Input::JoypadStart: return start.cachedState | slowMotion.cachedState;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Asciipad::Asciipad(unsigned category, const char *label, const char *configName) :
|
||||
InputGroup(category, label),
|
||||
up("Up", string() << "input." << configName << ".up"),
|
||||
down("Down", string() << "input." << configName << ".down"),
|
||||
left("Left", string() << "input." << configName << ".left"),
|
||||
right("Right", string() << "input." << configName << ".right"),
|
||||
b("B", string() << "input." << configName << ".b"),
|
||||
a("A", string() << "input." << configName << ".a"),
|
||||
y("Y", string() << "input." << configName << ".y"),
|
||||
x("X", string() << "input." << configName << ".x"),
|
||||
l("L", string() << "input." << configName << ".l"),
|
||||
r("R", string() << "input." << configName << ".r"),
|
||||
select("Select", string() << "input." << configName << ".select"),
|
||||
start("Start", string() << "input." << configName << ".start"),
|
||||
switchB("B Switch", string() << "input." << configName << ".bSwitch"),
|
||||
switchA("A Switch", string() << "input." << configName << ".aSwitch"),
|
||||
switchY("Y Switch", string() << "input." << configName << ".ySwitch"),
|
||||
switchX("X Switch", string() << "input." << configName << ".xSwitch"),
|
||||
switchL("L Switch", string() << "input." << configName << ".lSwitch"),
|
||||
switchR("R Switch", string() << "input." << configName << ".rSwitch"),
|
||||
slowMotion("Slow Motion", string() << "input." << configName << ".slowMotion") {
|
||||
b.asciiSwitch = &switchB;
|
||||
a.asciiSwitch = &switchA;
|
||||
y.asciiSwitch = &switchY;
|
||||
x.asciiSwitch = &switchX;
|
||||
l.asciiSwitch = &switchL;
|
||||
r.asciiSwitch = &switchR;
|
||||
|
||||
attach(&up); attach(&down); attach(&left); attach(&right);
|
||||
attach(&b); attach(&a); attach(&y); attach(&x);
|
||||
attach(&l); attach(&r); attach(&select); attach(&start);
|
||||
attach(&switchB); attach(&switchA); attach(&switchY); attach(&switchX);
|
||||
attach(&switchL); attach(&switchR); attach(&slowMotion);
|
||||
|
||||
if(this == &asciipad1) {
|
||||
up.name = "KB0::Up";
|
||||
down.name = "KB0::Down";
|
||||
left.name = "KB0::Left";
|
||||
right.name = "KB0::Right";
|
||||
b.name = "KB0::Z";
|
||||
a.name = "KB0::X";
|
||||
y.name = "KB0::A";
|
||||
x.name = "KB0::S";
|
||||
l.name = "KB0::D";
|
||||
r.name = "KB0::C";
|
||||
select.name = "KB0::Apostrophe";
|
||||
start.name = "KB0::Return";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int16_t Mouse::status(unsigned index, unsigned id) const {
|
||||
switch(id) {
|
||||
case SNES::Input::MouseX: return x.cachedState;
|
||||
case SNES::Input::MouseY: return y.cachedState;
|
||||
case SNES::Input::MouseLeft: return left.cachedState;
|
||||
case SNES::Input::MouseRight: return right.cachedState;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Mouse::Mouse(unsigned category, const char *label, const char *configName) :
|
||||
InputGroup(category, label),
|
||||
x("X-axis", string() << "input." << configName << ".x"),
|
||||
y("Y-axis", string() << "input." << configName << ".y"),
|
||||
left("Left Button", string() << "input." << configName << ".left"),
|
||||
right("Right Button", string() << "input." << configName << ".right") {
|
||||
attach(&x); attach(&y); attach(&left); attach(&right);
|
||||
|
||||
x.name = "MS0::Xaxis";
|
||||
y.name = "MS0::Yaxis";
|
||||
left.name = "MS0::Button0";
|
||||
right.name = "MS0::Button2";
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int16_t SuperScope::status(unsigned index, unsigned id) const {
|
||||
switch(id) {
|
||||
case SNES::Input::SuperScopeX: return x.cachedState;
|
||||
case SNES::Input::SuperScopeY: return y.cachedState;
|
||||
case SNES::Input::SuperScopeTrigger: return trigger.cachedState;
|
||||
case SNES::Input::SuperScopeCursor: return cursor.cachedState;
|
||||
case SNES::Input::SuperScopeTurbo: return turbo.cachedState;
|
||||
case SNES::Input::SuperScopePause: return pause.cachedState;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SuperScope::SuperScope(unsigned category, const char *label, const char *configName) :
|
||||
InputGroup(category, label),
|
||||
x("X-axis", string() << "input." << configName << ".x"),
|
||||
y("Y-axis", string() << "input." << configName << ".y"),
|
||||
trigger("Trigger", string() << "input." << configName << ".trigger"),
|
||||
cursor("Cursor", string() << "input." << configName << ".cursor"),
|
||||
turbo("Turbo", string() << "input." << configName << ".turbo"),
|
||||
pause("Pause", string() << "input." << configName << ".pause") {
|
||||
attach(&x); attach(&y); attach(&trigger); attach(&cursor);
|
||||
attach(&turbo); attach(&pause);
|
||||
|
||||
x.name = "MS0::Xaxis";
|
||||
y.name = "MS0::Yaxis";
|
||||
trigger.name = "MS0::Button0";
|
||||
cursor.name = "MS0::Button2";
|
||||
turbo.name = "KB0::T";
|
||||
pause.name = "KB0::P";
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int16_t Justifier::status(unsigned index, unsigned id) const {
|
||||
switch(id) {
|
||||
case SNES::Input::JustifierX: return x.cachedState;
|
||||
case SNES::Input::JustifierY: return y.cachedState;
|
||||
case SNES::Input::JustifierTrigger: return trigger.cachedState;
|
||||
case SNES::Input::JustifierStart: return start.cachedState;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Justifier::Justifier(unsigned category, const char *label, const char *configName) :
|
||||
InputGroup(category, label),
|
||||
x("X-axis", string() << "input." << configName << ".x"),
|
||||
y("Y-axis", string() << "input." << configName << ".y"),
|
||||
trigger("Trigger", string() << "input." << configName << ".trigger"),
|
||||
start("Start", string() << "input." << configName << ".start") {
|
||||
attach(&x); attach(&y); attach(&trigger); attach(&start);
|
||||
|
||||
if(this == &justifier1) {
|
||||
x.name = "MS0::Xaxis";
|
||||
y.name = "MS0::Yaxis";
|
||||
trigger.name = "MS0::Button0";
|
||||
start.name = "MS0::Button2";
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int16_t Justifiers::status(unsigned index, unsigned id) const {
|
||||
switch(index & 1) { default:
|
||||
case 0: return port1.status(index, id);
|
||||
case 1: return port2.status(index, id);
|
||||
}
|
||||
}
|
||||
|
||||
Justifiers::Justifiers(Justifier &port1_, Justifier &port2_) :
|
||||
InputGroup(InputCategory::Hidden, "Justifiers"),
|
||||
port1(port1_), port2(port2_) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Gamepad gamepad1(InputCategory::Port1, "Gamepad", "gamepad1");
|
||||
Asciipad asciipad1(InputCategory::Port1, "asciiPad", "asciipad1");
|
||||
Gamepad multitap1a(InputCategory::Port1, "Multitap - Port 1", "multitap1a");
|
||||
Gamepad multitap1b(InputCategory::Port1, "Multitap - Port 2", "multitap1b");
|
||||
Gamepad multitap1c(InputCategory::Port1, "Multitap - Port 3", "multitap1c");
|
||||
Gamepad multitap1d(InputCategory::Port1, "Multitap - Port 4", "multitap1d");
|
||||
Multitap multitap1(multitap1a, multitap1b, multitap1c, multitap1d);
|
||||
Mouse mouse1(InputCategory::Port1, "Mouse", "mouse1");
|
||||
|
||||
Gamepad gamepad2(InputCategory::Port2, "Gamepad", "gamepad2");
|
||||
Asciipad asciipad2(InputCategory::Port2, "asciiPad", "asciipad2");
|
||||
Gamepad multitap2a(InputCategory::Port2, "Multitap - Port 1", "multitap2a");
|
||||
Gamepad multitap2b(InputCategory::Port2, "Multitap - Port 2", "multitap2b");
|
||||
Gamepad multitap2c(InputCategory::Port2, "Multitap - Port 3", "multitap2c");
|
||||
Gamepad multitap2d(InputCategory::Port2, "Multitap - Port 4", "multitap2d");
|
||||
Multitap multitap2(multitap2a, multitap2b, multitap2c, multitap2d);
|
||||
Mouse mouse2(InputCategory::Port2, "Mouse", "mouse2");
|
||||
SuperScope superscope(InputCategory::Port2, "Super Scope", "superscope");
|
||||
Justifier justifier1(InputCategory::Port2, "Justifier 1", "justifier1");
|
||||
Justifier justifier2(InputCategory::Port2, "Justifier 2", "justifier2");
|
||||
Justifiers justifiers(justifier1, justifier2);
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
struct ControllerPort1 { enum { None, Gamepad, Asciipad, Multitap, Mouse }; };
|
||||
struct ControllerPort2 { enum { None, Gamepad, Asciipad, Multitap, Mouse, SuperScope, Justifier, Justifiers }; };
|
||||
|
||||
namespace Controllers {
|
||||
|
||||
struct TurboInput : DigitalInput {
|
||||
unsigned holdHi;
|
||||
unsigned holdLo;
|
||||
unsigned counter;
|
||||
void cache();
|
||||
TurboInput(const char*, const char*);
|
||||
};
|
||||
|
||||
struct Gamepad : InputGroup {
|
||||
DigitalInput up, down, left, right, b, a, y, x, l, r, select, start;
|
||||
TurboInput turboB, turboA, turboY, turboX, turboL, turboR;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
Gamepad(unsigned, const char*, const char*);
|
||||
};
|
||||
|
||||
struct Multitap : InputGroup {
|
||||
Gamepad &port1, &port2, &port3, &port4;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
Multitap(Gamepad&, Gamepad&, Gamepad&, Gamepad&);
|
||||
};
|
||||
|
||||
struct AsciiSwitch : DigitalInput {
|
||||
enum Mode { Off, Turbo, Auto } mode;
|
||||
void poll();
|
||||
AsciiSwitch(const char*, const char*);
|
||||
};
|
||||
|
||||
struct AsciiSlowMotion : DigitalInput {
|
||||
bool enabled;
|
||||
unsigned holdHi;
|
||||
unsigned holdLo;
|
||||
unsigned counter;
|
||||
void poll();
|
||||
void cache();
|
||||
AsciiSlowMotion(const char*, const char*);
|
||||
};
|
||||
|
||||
struct AsciiInput : DigitalInput {
|
||||
AsciiSwitch *asciiSwitch;
|
||||
unsigned holdHi;
|
||||
unsigned holdLo;
|
||||
unsigned counter;
|
||||
void cache();
|
||||
AsciiInput(const char*, const char*);
|
||||
};
|
||||
|
||||
struct Asciipad : InputGroup {
|
||||
DigitalInput up, down, left, right;
|
||||
AsciiInput b, a, y, x, l, r;
|
||||
DigitalInput select, start;
|
||||
AsciiSwitch switchB, switchA, switchY, switchX, switchL, switchR;
|
||||
AsciiSlowMotion slowMotion;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
Asciipad(unsigned, const char*, const char*);
|
||||
};
|
||||
|
||||
struct Mouse : InputGroup {
|
||||
AnalogInput x, y;
|
||||
DigitalInput left, right;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
Mouse(unsigned, const char*, const char*);
|
||||
};
|
||||
|
||||
struct SuperScope : InputGroup {
|
||||
AnalogInput x, y;
|
||||
DigitalInput trigger, cursor, turbo, pause;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
SuperScope(unsigned, const char*, const char*);
|
||||
};
|
||||
|
||||
struct Justifier : InputGroup {
|
||||
AnalogInput x, y;
|
||||
DigitalInput trigger, start;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
Justifier(unsigned, const char*, const char*);
|
||||
};
|
||||
|
||||
struct Justifiers : InputGroup {
|
||||
Justifier &port1;
|
||||
Justifier &port2;
|
||||
int16_t status(unsigned, unsigned) const;
|
||||
Justifiers(Justifier&, Justifier&);
|
||||
};
|
||||
|
||||
extern Gamepad gamepad1;
|
||||
extern Asciipad asciipad1;
|
||||
extern Gamepad multitap1a;
|
||||
extern Gamepad multitap1b;
|
||||
extern Gamepad multitap1c;
|
||||
extern Gamepad multitap1d;
|
||||
extern Multitap multitap1;
|
||||
extern Mouse mouse1;
|
||||
|
||||
extern Gamepad gamepad2;
|
||||
extern Asciipad asciipad2;
|
||||
extern Gamepad multitap2a;
|
||||
extern Gamepad multitap2b;
|
||||
extern Gamepad multitap2c;
|
||||
extern Gamepad multitap2d;
|
||||
extern Multitap multitap2;
|
||||
extern Mouse mouse2;
|
||||
extern SuperScope superscope;
|
||||
extern Justifier justifier1;
|
||||
extern Justifier justifier2;
|
||||
extern Justifiers justifiers;
|
||||
|
||||
}
|
|
@ -1,261 +0,0 @@
|
|||
//===========
|
||||
//InputDevice
|
||||
//===========
|
||||
|
||||
InputDevice::InputDevice(SNES::Input::DeviceID i, bool p, const char *n) : InputGroup(n), id(i), port(p) {
|
||||
}
|
||||
|
||||
//======
|
||||
//Joypad
|
||||
//======
|
||||
|
||||
int16_t Joypad::state(unsigned index) const {
|
||||
if(config.input.allowInvalidInput == false) {
|
||||
//SNES D-pads have central pivot point, making up+down or left+right combinations impossible.
|
||||
//some software programs rely on this, and will crash if these combinations are allowed.
|
||||
if(index == SNES::Input::JoypadDown && up.state ) return 0;
|
||||
if(index == SNES::Input::JoypadRight && left.state) return 0;
|
||||
}
|
||||
|
||||
switch(index) {
|
||||
case SNES::Input::JoypadUp: return up.state;
|
||||
case SNES::Input::JoypadDown: return down.state;
|
||||
case SNES::Input::JoypadLeft: return left.state;
|
||||
case SNES::Input::JoypadRight: return right.state;
|
||||
case SNES::Input::JoypadA: return a.state;
|
||||
case SNES::Input::JoypadB: return b.state;
|
||||
case SNES::Input::JoypadX: return x.state;
|
||||
case SNES::Input::JoypadY: return y.state;
|
||||
case SNES::Input::JoypadL: return l.state;
|
||||
case SNES::Input::JoypadR: return r.state;
|
||||
case SNES::Input::JoypadSelect: return select.state;
|
||||
case SNES::Input::JoypadStart: return start.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Joypad::Joypad(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &up_t, string &down_t, string &left_t, string &right_t, string &a_t, string &b_t,
|
||||
string &x_t, string &y_t, string &l_t, string &r_t, string &select_t, string &start_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
up (InputObject::Button, "Up", up_t),
|
||||
down (InputObject::Button, "Down", down_t),
|
||||
left (InputObject::Button, "Left", left_t),
|
||||
right (InputObject::Button, "Right", right_t),
|
||||
a (InputObject::Button, "A", a_t),
|
||||
b (InputObject::Button, "B", b_t),
|
||||
x (InputObject::Button, "X", x_t),
|
||||
y (InputObject::Button, "Y", y_t),
|
||||
l (InputObject::Button, "L", l_t),
|
||||
r (InputObject::Button, "R", r_t),
|
||||
select(InputObject::Button, "Select", select_t),
|
||||
start (InputObject::Button, "Start", start_t) {
|
||||
attach(up); attach(down); attach(left); attach(right); attach(a); attach(b);
|
||||
attach(x); attach(y); attach(l); attach(r); attach(select); attach(start);
|
||||
}
|
||||
|
||||
//=====
|
||||
//Mouse
|
||||
//=====
|
||||
|
||||
int16_t Mouse::state(unsigned index) const {
|
||||
switch(index) {
|
||||
case SNES::Input::MouseX: return x.state;
|
||||
case SNES::Input::MouseY: return y.state;
|
||||
case SNES::Input::MouseLeft: return left.state;
|
||||
case SNES::Input::MouseRight: return right.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Mouse::Mouse(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &x_t, string &y_t, string &left_t, string &right_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
x (InputObject::Axis, "X-axis", x_t),
|
||||
y (InputObject::Axis, "Y-axis", y_t),
|
||||
left (InputObject::Button, "Left button", left_t),
|
||||
right(InputObject::Button, "Right button", right_t) {
|
||||
attach(x); attach(y); attach(left); attach(right);
|
||||
}
|
||||
|
||||
//==========
|
||||
//SuperScope
|
||||
//==========
|
||||
|
||||
int16_t SuperScope::state(unsigned index) const {
|
||||
switch(index) {
|
||||
case SNES::Input::SuperScopeX: return x.state;
|
||||
case SNES::Input::SuperScopeY: return y.state;
|
||||
case SNES::Input::SuperScopeTrigger: return trigger.state;
|
||||
case SNES::Input::SuperScopeCursor: return cursor.state;
|
||||
case SNES::Input::SuperScopeTurbo: return turbo.state;
|
||||
case SNES::Input::SuperScopePause: return pause.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SuperScope::SuperScope(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &x_t, string &y_t, string &trigger_t, string &cursor_t, string &turbo_t, string &pause_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
x (InputObject::Axis, "X-axis", x_t),
|
||||
y (InputObject::Axis, "Y-axis", y_t),
|
||||
trigger(InputObject::Button, "Trigger", trigger_t),
|
||||
cursor (InputObject::Button, "Cursor", cursor_t),
|
||||
turbo (InputObject::Button, "Turbo", turbo_t),
|
||||
pause (InputObject::Button, "Pause", pause_t) {
|
||||
attach(x); attach(y); attach(trigger); attach(cursor); attach(turbo); attach(pause);
|
||||
}
|
||||
|
||||
//=========
|
||||
//Justifier
|
||||
//=========
|
||||
|
||||
int16_t Justifier::state(unsigned index) const {
|
||||
switch(index) {
|
||||
case SNES::Input::JustifierX: return x.state;
|
||||
case SNES::Input::JustifierY: return y.state;
|
||||
case SNES::Input::JustifierTrigger: return trigger.state;
|
||||
case SNES::Input::JustifierStart: return start.state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Justifier::Justifier(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string &x_t, string &y_t, string &trigger_t, string &start_t
|
||||
) :
|
||||
InputDevice(id, port, name),
|
||||
x (InputObject::Axis, "X-axis", x_t),
|
||||
y (InputObject::Axis, "Y-axis", y_t),
|
||||
trigger(InputObject::Button, "Trigger", trigger_t),
|
||||
start (InputObject::Button, "Start", start_t) {
|
||||
attach(x); attach(y); attach(trigger); attach(start);
|
||||
}
|
||||
|
||||
//===============
|
||||
//InputDevicePool
|
||||
//===============
|
||||
|
||||
void InputDevicePool::attach(InputDevice &device) {
|
||||
list.add(&device);
|
||||
}
|
||||
|
||||
void InputDevicePool::bind() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->bind();
|
||||
}
|
||||
|
||||
void InputDevicePool::clear() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->clear();
|
||||
}
|
||||
|
||||
void InputDevicePool::poll(const int16_t *table) {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table);
|
||||
}
|
||||
|
||||
InputDevice* InputDevicePool::find(SNES::Input::DeviceID id) {
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
if(list[i]->id == id) return list[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
InputDevicePool::InputDevicePool() : list(*this) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Joypad joypad1(SNES::Input::DeviceIDJoypad1, InputDevice::Port1, "Joypad",
|
||||
config.input.joypad1.up, config.input.joypad1.down, config.input.joypad1.left, config.input.joypad1.right,
|
||||
config.input.joypad1.a, config.input.joypad1.b, config.input.joypad1.x, config.input.joypad1.y,
|
||||
config.input.joypad1.l, config.input.joypad1.r, config.input.joypad1.select, config.input.joypad1.start);
|
||||
|
||||
Joypad joypad2(SNES::Input::DeviceIDJoypad2, InputDevice::Port2, "Joypad",
|
||||
config.input.joypad2.up, config.input.joypad2.down, config.input.joypad2.left, config.input.joypad2.right,
|
||||
config.input.joypad2.a, config.input.joypad2.b, config.input.joypad2.x, config.input.joypad2.y,
|
||||
config.input.joypad2.l, config.input.joypad2.r, config.input.joypad2.select, config.input.joypad2.start);
|
||||
|
||||
Joypad multitap1a(SNES::Input::DeviceIDMultitap1A, InputDevice::Port1, "Multitap - Port 1",
|
||||
config.input.multitap1a.up, config.input.multitap1a.down, config.input.multitap1a.left, config.input.multitap1a.right,
|
||||
config.input.multitap1a.a, config.input.multitap1a.b, config.input.multitap1a.x, config.input.multitap1a.y,
|
||||
config.input.multitap1a.l, config.input.multitap1a.r, config.input.multitap1a.select, config.input.multitap1a.start);
|
||||
|
||||
Joypad multitap1b(SNES::Input::DeviceIDMultitap1B, InputDevice::Port1, "Multitap - Port 2",
|
||||
config.input.multitap1b.up, config.input.multitap1b.down, config.input.multitap1b.left, config.input.multitap1b.right,
|
||||
config.input.multitap1b.a, config.input.multitap1b.b, config.input.multitap1b.x, config.input.multitap1b.y,
|
||||
config.input.multitap1b.l, config.input.multitap1b.r, config.input.multitap1b.select, config.input.multitap1b.start);
|
||||
|
||||
Joypad multitap1c(SNES::Input::DeviceIDMultitap1C, InputDevice::Port1, "Multitap - Port 3",
|
||||
config.input.multitap1c.up, config.input.multitap1c.down, config.input.multitap1c.left, config.input.multitap1c.right,
|
||||
config.input.multitap1c.a, config.input.multitap1c.b, config.input.multitap1c.x, config.input.multitap1c.y,
|
||||
config.input.multitap1c.l, config.input.multitap1c.r, config.input.multitap1c.select, config.input.multitap1c.start);
|
||||
|
||||
Joypad multitap1d(SNES::Input::DeviceIDMultitap1D, InputDevice::Port1, "Multitap - Port 4",
|
||||
config.input.multitap1d.up, config.input.multitap1d.down, config.input.multitap1d.left, config.input.multitap1d.right,
|
||||
config.input.multitap1d.a, config.input.multitap1d.b, config.input.multitap1d.x, config.input.multitap1d.y,
|
||||
config.input.multitap1d.l, config.input.multitap1d.r, config.input.multitap1d.select, config.input.multitap1d.start);
|
||||
|
||||
Joypad multitap2a(SNES::Input::DeviceIDMultitap2A, InputDevice::Port2, "Multitap - Port 1",
|
||||
config.input.multitap2a.up, config.input.multitap2a.down, config.input.multitap2a.left, config.input.multitap2a.right,
|
||||
config.input.multitap2a.a, config.input.multitap2a.b, config.input.multitap2a.x, config.input.multitap2a.y,
|
||||
config.input.multitap2a.l, config.input.multitap2a.r, config.input.multitap2a.select, config.input.multitap2a.start);
|
||||
|
||||
Joypad multitap2b(SNES::Input::DeviceIDMultitap2B, InputDevice::Port2, "Multitap - Port 2",
|
||||
config.input.multitap2b.up, config.input.multitap2b.down, config.input.multitap2b.left, config.input.multitap2b.right,
|
||||
config.input.multitap2b.a, config.input.multitap2b.b, config.input.multitap2b.x, config.input.multitap2b.y,
|
||||
config.input.multitap2b.l, config.input.multitap2b.r, config.input.multitap2b.select, config.input.multitap2b.start);
|
||||
|
||||
Joypad multitap2c(SNES::Input::DeviceIDMultitap2C, InputDevice::Port2, "Multitap - Port 3",
|
||||
config.input.multitap2c.up, config.input.multitap2c.down, config.input.multitap2c.left, config.input.multitap2c.right,
|
||||
config.input.multitap2c.a, config.input.multitap2c.b, config.input.multitap2c.x, config.input.multitap2c.y,
|
||||
config.input.multitap2c.l, config.input.multitap2c.r, config.input.multitap2c.select, config.input.multitap2c.start);
|
||||
|
||||
Joypad multitap2d(SNES::Input::DeviceIDMultitap2D, InputDevice::Port2, "Multitap - Port 4",
|
||||
config.input.multitap2d.up, config.input.multitap2d.down, config.input.multitap2d.left, config.input.multitap2d.right,
|
||||
config.input.multitap2d.a, config.input.multitap2d.b, config.input.multitap2d.x, config.input.multitap2d.y,
|
||||
config.input.multitap2d.l, config.input.multitap2d.r, config.input.multitap2d.select, config.input.multitap2d.start);
|
||||
|
||||
Mouse mouse1(SNES::Input::DeviceIDMouse1, InputDevice::Port1, "Mouse",
|
||||
config.input.mouse1.x, config.input.mouse1.y, config.input.mouse1.left, config.input.mouse1.right);
|
||||
|
||||
Mouse mouse2(SNES::Input::DeviceIDMouse2, InputDevice::Port2, "Mouse",
|
||||
config.input.mouse2.x, config.input.mouse2.y, config.input.mouse2.left, config.input.mouse2.right);
|
||||
|
||||
SuperScope superscope(SNES::Input::DeviceIDSuperScope, InputDevice::Port2, "Super Scope",
|
||||
config.input.superscope.x, config.input.superscope.y,
|
||||
config.input.superscope.trigger, config.input.superscope.cursor,
|
||||
config.input.superscope.turbo, config.input.superscope.pause);
|
||||
|
||||
Justifier justifier1(SNES::Input::DeviceIDJustifier1, InputDevice::Port2, "Justifier 1",
|
||||
config.input.justifier1.x, config.input.justifier1.y,
|
||||
config.input.justifier1.trigger, config.input.justifier1.start);
|
||||
|
||||
Justifier justifier2(SNES::Input::DeviceIDJustifier2, InputDevice::Port2, "Justifier 2",
|
||||
config.input.justifier2.x, config.input.justifier2.y,
|
||||
config.input.justifier2.trigger, config.input.justifier2.start);
|
||||
|
||||
InputSnesDevicePool inputPool;
|
||||
|
||||
InputSnesDevicePool::InputSnesDevicePool() {
|
||||
attach(joypad1);
|
||||
attach(joypad2);
|
||||
attach(multitap1a);
|
||||
attach(multitap1b);
|
||||
attach(multitap1c);
|
||||
attach(multitap1d);
|
||||
attach(multitap2a);
|
||||
attach(multitap2b);
|
||||
attach(multitap2c);
|
||||
attach(multitap2d);
|
||||
attach(mouse1);
|
||||
attach(mouse2);
|
||||
attach(superscope);
|
||||
attach(justifier1);
|
||||
attach(justifier2);
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
struct InputDevice : InputGroup {
|
||||
SNES::Input::DeviceID id;
|
||||
enum Port { Port1, Port2 };
|
||||
const bool port;
|
||||
|
||||
InputDevice(SNES::Input::DeviceID i, bool p, const char *n);
|
||||
};
|
||||
|
||||
struct Joypad : InputDevice {
|
||||
InputObject up, down, left, right, a, b, x, y, l, r, select, start;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
Joypad(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&, string&, string&,
|
||||
string&, string&, string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct Mouse : InputDevice {
|
||||
InputObject x, y, left, right;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
Mouse(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct SuperScope : InputDevice {
|
||||
InputObject x, y, trigger, cursor, turbo, pause;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
SuperScope(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct Justifier : InputDevice {
|
||||
InputObject x, y, trigger, start;
|
||||
|
||||
int16_t state(unsigned index) const;
|
||||
Justifier(SNES::Input::DeviceID id, bool port, const char *name,
|
||||
string&, string&, string&, string&);
|
||||
};
|
||||
|
||||
struct InputDevicePool : public array<InputDevice*> {
|
||||
void attach(InputDevice &device);
|
||||
void bind();
|
||||
void clear();
|
||||
void poll(const int16_t *table);
|
||||
InputDevice* find(SNES::Input::DeviceID id);
|
||||
InputDevicePool();
|
||||
|
||||
private:
|
||||
array<InputDevice*> &list;
|
||||
};
|
||||
|
||||
struct InputSnesDevicePool : public InputDevicePool {
|
||||
InputSnesDevicePool();
|
||||
};
|
||||
|
||||
extern Joypad joypad1;
|
||||
extern Joypad joypad2;
|
||||
extern Joypad multitap1a;
|
||||
extern Joypad multitap1b;
|
||||
extern Joypad multitap1c;
|
||||
extern Joypad multitap1d;
|
||||
extern Joypad multitap2a;
|
||||
extern Joypad multitap2b;
|
||||
extern Joypad multitap2c;
|
||||
extern Joypad multitap2d;
|
||||
extern Mouse mouse1;
|
||||
extern Mouse mouse2;
|
||||
extern SuperScope superscope;
|
||||
extern Justifier justifier1;
|
||||
extern Justifier justifier2;
|
||||
extern InputSnesDevicePool inputPool;
|
|
@ -1,269 +1,260 @@
|
|||
#include "device.cpp"
|
||||
#include "userinterface.cpp"
|
||||
#include "controller.cpp"
|
||||
#include "userinterface-general.cpp"
|
||||
#include "userinterface-system.cpp"
|
||||
#include "userinterface-emulationspeed.cpp"
|
||||
#include "userinterface-states.cpp"
|
||||
#include "userinterface-videosettings.cpp"
|
||||
|
||||
//=========
|
||||
//InputCode
|
||||
//=========
|
||||
|
||||
InputCode::type_t InputCode::type(uint16_t code) {
|
||||
for(unsigned i = 0; i < keyboard<>::count; i++) {
|
||||
unsigned index = keyboard<>::index(i, keyboard<>::none);
|
||||
if(code >= index && code < index + keyboard<>::length) return KeyboardButton;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < mouse<>::count; i++) {
|
||||
unsigned index = mouse<>::index(i, mouse<>::none);
|
||||
if(code == index + mouse<>::x) return MouseAxis;
|
||||
if(code == index + mouse<>::y) return MouseAxis;
|
||||
if(code == index + mouse<>::z) return MouseAxis;
|
||||
|
||||
index = mouse<>::index(i, mouse<>::button);
|
||||
if(code >= index && code < index + mouse<>::buttons) return MouseButton;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
unsigned index;
|
||||
|
||||
index = joypad<>::index(i, joypad<>::hat);
|
||||
if(code >= index && code < index + joypad<>::hats) return JoypadHat;
|
||||
|
||||
index = joypad<>::index(i, joypad<>::axis);
|
||||
if(code >= index && code < index + joypad<>::axes) return JoypadAxis;
|
||||
|
||||
index = joypad<>::index(i, joypad<>::button);
|
||||
if(code >= index && code < index + joypad<>::buttons) return JoypadButton;
|
||||
}
|
||||
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
InputCode::axistype_t InputCode::axisType(uint16_t code) {
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
unsigned index = joypad<>::index(i, joypad<>::axis);
|
||||
if(code >= index && code < index + joypad<>::axes) {
|
||||
return (InputCode::axistype_t)inputManager.axisType(i, code - index);
|
||||
}
|
||||
}
|
||||
return InvalidAxis;
|
||||
}
|
||||
|
||||
//finds what mouse# is associated with code, returns -1 if not a mouse code
|
||||
int InputCode::mouseNumber(uint16_t code) {
|
||||
for(unsigned i = 0; i < mouse<>::count; i++) {
|
||||
unsigned index = mouse<>::index(i, mouse<>::none);
|
||||
if(code >= index && code < index + mouse<>::length) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//finds what joypad# is associated with code, returns -1 if not a joypad code
|
||||
int InputCode::joypadNumber(uint16_t code) {
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
unsigned index = joypad<>::index(i, joypad<>::none);
|
||||
if(code >= index && code < index + joypad<>::length) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//============
|
||||
//InputManager
|
||||
//============
|
||||
|
||||
void InputManager::bind() {
|
||||
inputPool.bind();
|
||||
inputUiPool.bind();
|
||||
}
|
||||
|
||||
void InputManager::poll() {
|
||||
if(config.input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput
|
||||
&& mainWindow->isActive() == false) {
|
||||
inputPool.clear();
|
||||
} else {
|
||||
inputPool.poll(stateTable[activeState]);
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::clear() {
|
||||
inputPool.clear();
|
||||
}
|
||||
|
||||
void InputManager::flush() {
|
||||
for(unsigned i = 0; i < nall::input_limit; i++) {
|
||||
stateTable[0][i] = 0;
|
||||
stateTable[1][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t InputManager::state(uint16_t code) const {
|
||||
return stateTable[ activeState][code];
|
||||
}
|
||||
|
||||
int16_t InputManager::lastState(uint16_t code) const {
|
||||
return stateTable[!activeState][code];
|
||||
}
|
||||
|
||||
int16_t InputManager::getStatus(unsigned deviceid, unsigned id) const {
|
||||
InputDevice *device = inputPool.find((SNES::Input::DeviceID)deviceid);
|
||||
if(device) return device->state(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InputManager::refresh() {
|
||||
bool last = activeState;
|
||||
activeState = !activeState;
|
||||
bool next = activeState;
|
||||
|
||||
input.poll(stateTable[next]);
|
||||
for(unsigned i = 0; i < nall::input_limit; i++) {
|
||||
//alert via callback whenever input state changes for any ID ...
|
||||
if(onInput && stateTable[last][i] != stateTable[next][i]) onInput(i);
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::calibrate(unsigned joy) {
|
||||
unsigned index = joypad<>::index(joy, joypad<>::none);
|
||||
|
||||
for(unsigned axis = 0; axis < joypad<>::axes; axis++) {
|
||||
int16_t value = state(index + joypad<>::axis + axis);
|
||||
pad[joy].axis[axis] = (value >= -16384 && value <= +16384) ? InputCode::Stick : InputCode::Trigger;
|
||||
}
|
||||
|
||||
pad[joy].calibrated = true;
|
||||
}
|
||||
|
||||
bool InputManager::calibrated(unsigned joy) const {
|
||||
return pad[joy].calibrated;
|
||||
}
|
||||
|
||||
InputCode::axistype_t InputManager::axisType(unsigned joy, unsigned axis) const {
|
||||
return pad[joy].axis[axis];
|
||||
}
|
||||
|
||||
InputManager::InputManager() {
|
||||
activeState = 0;
|
||||
flush();
|
||||
|
||||
for(unsigned i = 0; i < joypad<>::count; i++) {
|
||||
pad[i].calibrated = false;
|
||||
for(unsigned n = 0; n < joypad<>::axes; n++) pad[i].axis[n] = InputCode::InvalidAxis;
|
||||
}
|
||||
}
|
||||
|
||||
//===========
|
||||
//InputObject
|
||||
//===========
|
||||
|
||||
void InputObject::bind() {
|
||||
void MappedInput::bind() {
|
||||
lstring part;
|
||||
part.split("::", id);
|
||||
part.split("+", name);
|
||||
|
||||
code = nall::input_find((const char*)part[0]);
|
||||
codetype = InputCode::type(code);
|
||||
|
||||
modifier = None;
|
||||
if(part.size() > 1) {
|
||||
if(part[1] == "up" ) modifier = Up;
|
||||
if(part[1] == "down" ) modifier = Down;
|
||||
if(part[1] == "left" ) modifier = Left;
|
||||
if(part[1] == "right" ) modifier = Right;
|
||||
if(part[1] == "lo" ) modifier = Lo;
|
||||
if(part[1] == "hi" ) modifier = Hi;
|
||||
if(part[1] == "trigger") modifier = Trigger;
|
||||
modifier = InputModifier::None;
|
||||
for(unsigned i = 0; i < part.size(); i++) {
|
||||
if(part[i] == "Shift") modifier |= InputModifier::Shift;
|
||||
if(part[i] == "Control") modifier |= InputModifier::Control;
|
||||
if(part[i] == "Alt") modifier |= InputModifier::Alt;
|
||||
if(part[i] == "Super") modifier |= InputModifier::Super;
|
||||
}
|
||||
|
||||
if(code == nall::input_none) id = "none";
|
||||
string temp = part[part.size() - 1];
|
||||
part.split(".", temp);
|
||||
scancode = Scancode::decode(part[0]);
|
||||
specifier = InputSpecifier::None;
|
||||
if(part[1] == "Up") specifier = InputSpecifier::Up;
|
||||
if(part[1] == "Down") specifier = InputSpecifier::Down;
|
||||
if(part[1] == "Left") specifier = InputSpecifier::Left;
|
||||
if(part[1] == "Right") specifier = InputSpecifier::Right;
|
||||
if(part[1] == "Lo") specifier = InputSpecifier::Lo;
|
||||
if(part[1] == "Hi") specifier = InputSpecifier::Hi;
|
||||
if(part[1] == "Trigger") specifier = InputSpecifier::Trigger;
|
||||
|
||||
//re-encode name, in case previous name was invalid
|
||||
name = "";
|
||||
if(modifier & InputModifier::Shift) name << "Shift+";
|
||||
if(modifier & InputModifier::Control) name << "Control+";
|
||||
if(modifier & InputModifier::Alt) name << "Alt+";
|
||||
if(modifier & InputModifier::Super) name << "Super+";
|
||||
name << Scancode::encode(scancode);
|
||||
if(specifier == InputSpecifier::Up) name << ".Up";
|
||||
if(specifier == InputSpecifier::Down) name << ".Down";
|
||||
if(specifier == InputSpecifier::Left) name << ".Left";
|
||||
if(specifier == InputSpecifier::Right) name << ".Right";
|
||||
if(specifier == InputSpecifier::Lo) name << ".Lo";
|
||||
if(specifier == InputSpecifier::Hi) name << ".Hi";
|
||||
if(specifier == InputSpecifier::Trigger) name << ".Trigger";
|
||||
}
|
||||
|
||||
void InputObject::bind(uint16_t newCode) {
|
||||
code = newCode;
|
||||
codetype = InputCode::type(code);
|
||||
|
||||
id = nall::input_find(newCode);
|
||||
modifier = None;
|
||||
|
||||
if(type == Button && codetype == InputCode::JoypadHat) {
|
||||
switch(inputManager.state(code)) {
|
||||
case joypad<>::hat_up: id << "::up"; modifier = Up; break;
|
||||
case joypad<>::hat_down: id << "::down"; modifier = Down; break;
|
||||
case joypad<>::hat_left: id << "::left"; modifier = Left; break;
|
||||
case joypad<>::hat_right: id << "::right"; modifier = Right; break;
|
||||
}
|
||||
} else if(type == Button && codetype == InputCode::JoypadAxis) {
|
||||
InputCode::axistype_t type = InputCode::axisType(code);
|
||||
int16_t state = inputManager.state(code);
|
||||
|
||||
if(type == InputCode::Stick) {
|
||||
if(state < 0) {
|
||||
id << "::lo";
|
||||
modifier = Lo;
|
||||
} else {
|
||||
id << "::hi";
|
||||
modifier = Hi;
|
||||
}
|
||||
} else if(type == InputCode::Trigger) {
|
||||
id << "::trigger";
|
||||
modifier = Trigger;
|
||||
}
|
||||
}
|
||||
void MappedInput::cache() {
|
||||
cachedState = state;
|
||||
}
|
||||
|
||||
void InputObject::poll(int16_t newState) {
|
||||
if(type == Button && codetype == InputCode::JoypadHat) {
|
||||
//map 4-way hat input to button state
|
||||
state = (modifier == Up && (newState & joypad<>::hat_up ))
|
||||
|| (modifier == Down && (newState & joypad<>::hat_down ))
|
||||
|| (modifier == Left && (newState & joypad<>::hat_left ))
|
||||
|| (modifier == Right && (newState & joypad<>::hat_right));
|
||||
} else if(type == Button && codetype == InputCode::JoypadAxis) {
|
||||
//convert analog input to button state
|
||||
state = (modifier == Lo && newState < -16384)
|
||||
|| (modifier == Hi && newState > +16384)
|
||||
|| (modifier == Trigger && newState < 0);
|
||||
} else if(codetype == InputCode::MouseAxis && !input.acquired()) {
|
||||
//mouse must be acquired (locked to window) to move axes
|
||||
state = 0;
|
||||
} else if(0 && codetype == InputCode::MouseButton && !input.acquired()) {
|
||||
//same for buttons
|
||||
//note: disabled for now ... requiring exclusive access makes it much more difficult
|
||||
//to utilize mouse buttons for eg SNES joypad input.
|
||||
state = 0;
|
||||
} else if(codetype == InputCode::JoypadAxis) {
|
||||
//joypad axis range = -32768 to +32767, scale to -8 to +7 to roughly match mouse delta
|
||||
//todo: scale mouse up instead of joypad down? (would require mouse DPI / resolution)
|
||||
state = newState / 4096;
|
||||
MappedInput::MappedInput(const char *label_, const char *configName) : parent(0), label(label_) {
|
||||
specifier = InputSpecifier::None;
|
||||
state = 0;
|
||||
previousState = 0;
|
||||
cachedState = 0;
|
||||
config().attach(name = "None", configName);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void DigitalInput::poll() {
|
||||
previousState = state;
|
||||
if(modifier == mapper().modifier) {
|
||||
if(specifier == InputSpecifier::None) {
|
||||
state = mapper().state(scancode);
|
||||
} else if(specifier == InputSpecifier::Up) {
|
||||
state = (bool)(mapper().state(scancode) & Joypad::HatUp);
|
||||
} else if(specifier == InputSpecifier::Down) {
|
||||
state = (bool)(mapper().state(scancode) & Joypad::HatDown);
|
||||
} else if(specifier == InputSpecifier::Left) {
|
||||
state = (bool)(mapper().state(scancode) & Joypad::HatLeft);
|
||||
} else if(specifier == InputSpecifier::Right) {
|
||||
state = (bool)(mapper().state(scancode) & Joypad::HatRight);
|
||||
} else if(specifier == InputSpecifier::Lo) {
|
||||
state = mapper().state(scancode) < -16384;
|
||||
} else if(specifier == InputSpecifier::Hi) {
|
||||
state = mapper().state(scancode) > +16384;
|
||||
} else if(specifier == InputSpecifier::Trigger) {
|
||||
state = mapper().state(scancode) < 0;
|
||||
}
|
||||
} else {
|
||||
state = newState;
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
InputObject::InputObject(InputObject::type_t t, const char *n, string &s) : parent(0), type(t), name(n), id(s) {
|
||||
bool DigitalInput::isPressed() const { return state; }
|
||||
bool DigitalInput::wasPressed() const { return previousState; }
|
||||
|
||||
DigitalInput::DigitalInput(const char *label, const char *configName) : MappedInput(label, configName) {
|
||||
}
|
||||
|
||||
//==========
|
||||
//InputGroup
|
||||
//==========
|
||||
//
|
||||
|
||||
void InputGroup::attach(InputObject &object) {
|
||||
list.add(&object);
|
||||
object.parent = this;
|
||||
void AnalogInput::poll() {
|
||||
previousState = state;
|
||||
if(Mouse::isAnyAxis(scancode)) {
|
||||
if(input.acquired()) {
|
||||
state = mapper().state(scancode);
|
||||
} else {
|
||||
state = 0;
|
||||
}
|
||||
} else if(Joypad::isAnyAxis(scancode)) {
|
||||
state = mapper().state(scancode) / 8192;
|
||||
}
|
||||
}
|
||||
|
||||
AnalogInput::AnalogInput(const char *label, const char *configName) : MappedInput(label, configName) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void HotkeyInput::poll() {
|
||||
DigitalInput::poll();
|
||||
if(state && state != previousState && mainWindow->isActive()) pressed();
|
||||
}
|
||||
|
||||
HotkeyInput::HotkeyInput(const char *label, const char *configName) : DigitalInput(label, configName) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void InputGroup::attach(MappedInput *input) {
|
||||
input->parent = this;
|
||||
add(input);
|
||||
}
|
||||
|
||||
void InputGroup::bind() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->bind();
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
(*this)[i]->bind();
|
||||
}
|
||||
}
|
||||
|
||||
void InputGroup::clear() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->state = 0;
|
||||
void InputGroup::poll() {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
(*this)[i]->poll();
|
||||
}
|
||||
}
|
||||
|
||||
void InputGroup::poll(const int16_t *table) {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table[list[i]->code]);
|
||||
void InputGroup::cache() {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
(*this)[i]->cache();
|
||||
}
|
||||
}
|
||||
|
||||
int16_t InputGroup::state(unsigned index) const {
|
||||
if(index < list.size()) return list[index]->state;
|
||||
void InputGroup::flushCache() {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
MappedInput &input = *((*this)[i]);
|
||||
input.cachedState = 0;
|
||||
}
|
||||
}
|
||||
|
||||
InputGroup::InputGroup(unsigned category_, const char *label_) : category(category_), label(label_) {
|
||||
mapper().add(this);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
InputMapper& mapper() {
|
||||
static InputMapper mapper;
|
||||
return mapper;
|
||||
}
|
||||
|
||||
void InputMapper::calibrate() {
|
||||
calibrated = true;
|
||||
audio.clear();
|
||||
QMessageBox::information(settingsWindow, "Joypad Calibration",
|
||||
"Joypads must be calibrated prior to mapping. Please ensure that "
|
||||
"all axes and analog buttons are not pressed or moved in any specific "
|
||||
"direction, and then press ok."
|
||||
);
|
||||
|
||||
poll();
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
for(unsigned axis = 0; axis < Joypad::Axes; axis++) {
|
||||
int16_t n = state(joypad(i).axis(axis));
|
||||
isTrigger[i][axis] = n < -16384 || n > +16384;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::bind() {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
(*this)[i]->bind();
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::poll() {
|
||||
activeState = !activeState;
|
||||
input.poll(stateTable[activeState]);
|
||||
|
||||
modifier = 0;
|
||||
for(unsigned i = 0; i < Keyboard::Count; i++) {
|
||||
if(state(keyboard(i)[Keyboard::Shift])) modifier |= InputModifier::Shift;
|
||||
if(state(keyboard(i)[Keyboard::Control])) modifier |= InputModifier::Control;
|
||||
if(state(keyboard(i)[Keyboard::Alt])) modifier |= InputModifier::Alt;
|
||||
if(state(keyboard(i)[Keyboard::Super])) modifier |= InputModifier::Super;
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
(*this)[i]->poll();
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < Scancode::Limit; i++) {
|
||||
if(state(i) != previousState(i)) {
|
||||
utility.inputEvent(i);
|
||||
diskBrowser->inputEvent(i);
|
||||
inputSettingsWindow->inputEvent(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputMapper::cache() {
|
||||
if(config().input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput && !mainWindow->isActive()) {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
InputGroup &group = *((*this)[i]);
|
||||
group.flushCache();
|
||||
}
|
||||
} else {
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
InputGroup &group = *((*this)[i]);
|
||||
if(group.category == InputCategory::Port1 || group.category == InputCategory::Port2) {
|
||||
group.cache();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t InputMapper::status(bool port, unsigned device, unsigned index, unsigned id) {
|
||||
if(port == InputCategory::Port1 && port1) return port1->status(index, id);
|
||||
if(port == InputCategory::Port2 && port2) return port2->status(index, id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
InputGroup::InputGroup(const char *n) : list(*this), name(n) {
|
||||
string InputMapper::modifierString() const {
|
||||
string name;
|
||||
if(modifier & InputModifier::Shift) name << "Shift+";
|
||||
if(modifier & InputModifier::Control) name << "Control+";
|
||||
if(modifier & InputModifier::Alt) name << "Alt+";
|
||||
if(modifier & InputModifier::Super) name << "Super+";
|
||||
return name;
|
||||
}
|
||||
|
||||
int16_t InputMapper::state(uint16_t scancode) const { return stateTable[activeState][scancode]; }
|
||||
int16_t InputMapper::previousState(uint16_t scancode) const { return stateTable[!activeState][scancode]; }
|
||||
unsigned InputMapper::distance(uint16_t scancode) const { return abs(state(scancode) - previousState(scancode)); }
|
||||
|
||||
InputMapper::InputMapper() : port1(0), port2(0) {
|
||||
calibrated = false;
|
||||
for(unsigned i = 0; i < Joypad::Count; i++) {
|
||||
for(unsigned axis = 0; axis < Joypad::Axes; axis++) {
|
||||
isTrigger[i][axis] = false;
|
||||
}
|
||||
}
|
||||
|
||||
activeState = 0;
|
||||
for(unsigned i = 0; i < Scancode::Limit; i++) {
|
||||
stateTable[0][i] = stateTable[1][i] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,88 +1,89 @@
|
|||
struct InputCode {
|
||||
enum type_t {
|
||||
KeyboardButton,
|
||||
MouseAxis,
|
||||
MouseButton,
|
||||
JoypadHat,
|
||||
JoypadAxis,
|
||||
JoypadButton,
|
||||
Unknown,
|
||||
};
|
||||
enum axistype_t {
|
||||
Stick, //bi-directional, centered analog stick (min = -32768, inactive = 0, max = +32767)
|
||||
Trigger, //uni-directional, pressure-sensitive analog trigger button (min = -32768, inactive = max = +32767)
|
||||
InvalidAxis, //not a joypad axis code, or said joypad is not calibrated
|
||||
};
|
||||
static type_t type(uint16_t code);
|
||||
static axistype_t axisType(uint16_t code);
|
||||
static int mouseNumber(uint16_t code);
|
||||
static int joypadNumber(uint16_t code);
|
||||
};
|
||||
|
||||
class InputManager {
|
||||
public:
|
||||
void bind();
|
||||
void poll();
|
||||
void clear();
|
||||
void flush();
|
||||
|
||||
int16_t state(uint16_t code) const;
|
||||
int16_t lastState(uint16_t code) const;
|
||||
int16_t getStatus(unsigned deviceid, unsigned id) const;
|
||||
|
||||
void refresh();
|
||||
void calibrate(unsigned joypad);
|
||||
bool calibrated(unsigned joypad) const;
|
||||
InputCode::axistype_t axisType(unsigned joypad, unsigned axis) const;
|
||||
function<void (uint16_t)> onInput;
|
||||
|
||||
InputManager();
|
||||
|
||||
private:
|
||||
bool activeState;
|
||||
int16_t stateTable[2][nall::input_limit];
|
||||
|
||||
//joypad axis calibration data
|
||||
struct Pad {
|
||||
bool calibrated;
|
||||
InputCode::axistype_t axis[joypad<>::axes];
|
||||
} pad[joypad<>::count];
|
||||
} inputManager;
|
||||
struct InputSpecifier { enum { None, Up, Down, Left, Right, Lo, Hi, Trigger }; };
|
||||
struct InputModifier { enum { None = 0, Shift = 1, Control = 2, Alt = 4, Super = 8 }; };
|
||||
struct InputCategory { enum { Port1 = 0, Port2 = 1, UserInterface = 2, Hidden = 3 }; };
|
||||
|
||||
struct InputGroup;
|
||||
|
||||
struct InputObject {
|
||||
struct MappedInput {
|
||||
InputGroup *parent;
|
||||
enum type_t { Button, Axis };
|
||||
enum modifier_t { None, Up, Down, Left, Right, Lo, Hi, Trigger };
|
||||
|
||||
type_t type; //type of input this object is mapped to
|
||||
const char *name; //plain-text name ("Up", "Down", ... "Start")
|
||||
string &id; //config-item reference ("joypad1.start") name ("joypad00.button00")
|
||||
uint16_t code; //nall::input code ID
|
||||
InputCode::type_t codetype; //hardware button / axis type
|
||||
modifier_t modifier; //hardware specialization (joypad-axis "::lo", "::hi", etc)
|
||||
int16_t state; //code state as of last inputManager.poll()
|
||||
string name;
|
||||
string label;
|
||||
unsigned specifier;
|
||||
unsigned modifier;
|
||||
unsigned scancode;
|
||||
int16_t state;
|
||||
int16_t previousState;
|
||||
int16_t cachedState;
|
||||
|
||||
void bind();
|
||||
void bind(uint16_t code);
|
||||
void poll(int16_t state);
|
||||
InputObject(type_t t, const char *n, string &s);
|
||||
virtual void poll() = 0;
|
||||
virtual void cache();
|
||||
|
||||
MappedInput(const char*, const char*);
|
||||
};
|
||||
|
||||
struct InputGroup : public array<InputObject*> {
|
||||
const char *name;
|
||||
struct DigitalInput : MappedInput {
|
||||
void poll();
|
||||
|
||||
void attach(InputObject &object);
|
||||
bool isPressed() const;
|
||||
bool wasPressed() const;
|
||||
|
||||
DigitalInput(const char*, const char*);
|
||||
};
|
||||
|
||||
struct AnalogInput : MappedInput {
|
||||
void poll();
|
||||
|
||||
AnalogInput(const char*, const char*);
|
||||
};
|
||||
|
||||
struct HotkeyInput : DigitalInput {
|
||||
void poll();
|
||||
virtual void pressed() {}
|
||||
|
||||
HotkeyInput(const char*, const char*);
|
||||
};
|
||||
|
||||
struct InputGroup : public array<MappedInput*> {
|
||||
unsigned category;
|
||||
string label;
|
||||
|
||||
void attach(MappedInput*);
|
||||
void bind();
|
||||
void clear();
|
||||
void poll(const int16_t *table);
|
||||
virtual int16_t state(unsigned index) const;
|
||||
InputGroup(const char *n);
|
||||
void poll();
|
||||
void cache();
|
||||
void flushCache();
|
||||
virtual int16_t status(unsigned, unsigned) const { return 0; }
|
||||
|
||||
private:
|
||||
array<InputObject*> &list;
|
||||
InputGroup(unsigned, const char*);
|
||||
};
|
||||
|
||||
#include "device.hpp"
|
||||
struct InputMapper : public array<InputGroup*> {
|
||||
InputGroup *port1;
|
||||
InputGroup *port2;
|
||||
|
||||
bool calibrated;
|
||||
bool isTrigger[Joypad::Count][Joypad::Axes];
|
||||
|
||||
bool activeState;
|
||||
int16_t stateTable[2][Scancode::Limit];
|
||||
unsigned modifier;
|
||||
|
||||
void calibrate();
|
||||
void bind();
|
||||
void poll();
|
||||
void cache();
|
||||
int16_t status(bool, unsigned, unsigned, unsigned);
|
||||
|
||||
string modifierString() const;
|
||||
int16_t state(uint16_t) const;
|
||||
int16_t previousState(uint16_t) const;
|
||||
unsigned distance(uint16_t) const;
|
||||
|
||||
InputMapper();
|
||||
};
|
||||
|
||||
InputMapper& mapper();
|
||||
|
||||
#include "controller.hpp"
|
||||
#include "userinterface.hpp"
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
InputGroup userInterfaceEmulationSpeed(InputCategory::UserInterface, "Emulation Speed");
|
||||
|
||||
namespace UserInterfaceEmulationSpeed {
|
||||
|
||||
struct Decrease : HotkeyInput {
|
||||
void pressed() {
|
||||
if(config().system.speed > 0) config().system.speed--;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
Decrease() : HotkeyInput("Decrease", "config.userInterface.emulationSpeed.decrease") {
|
||||
name = "Control+KB0::Divide";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} decrease;
|
||||
|
||||
struct Increase : HotkeyInput {
|
||||
void pressed() {
|
||||
if(config().system.speed < 4) config().system.speed++;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
Increase() : HotkeyInput("Increase", "config.userInterface.emulationSpeed.increase") {
|
||||
name = "Control+KB0::Multiply";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} increase;
|
||||
|
||||
struct SetSlowestSpeed : HotkeyInput {
|
||||
void pressed() {
|
||||
config().system.speed = 0;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
SetSlowestSpeed() : HotkeyInput("Set Slowest Speed", "config.userInterface.emulationSpeed.setSlowest") {
|
||||
name = "Control+KB0::Num1";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} setSlowestSpeed;
|
||||
|
||||
struct SetSlowSpeed : HotkeyInput {
|
||||
void pressed() {
|
||||
config().system.speed = 1;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
SetSlowSpeed() : HotkeyInput("Set Slow Speed", "config.userInterface.emulationSpeed.setSlow") {
|
||||
name = "Control+KB0::Num2";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} setSlowSpeed;
|
||||
|
||||
struct SetNormalSpeed : HotkeyInput {
|
||||
void pressed() {
|
||||
config().system.speed = 2;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
SetNormalSpeed() : HotkeyInput("Set Normal Speed", "config.userInterface.emulationSpeed.setNormal") {
|
||||
name = "Control+KB0::Num3";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} setNormalSpeed;
|
||||
|
||||
struct SetFastSpeed : HotkeyInput {
|
||||
void pressed() {
|
||||
config().system.speed = 3;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
SetFastSpeed() : HotkeyInput("Set Fast Speed", "config.userInterface.emulationSpeed.setFast") {
|
||||
name = "Control+KB0::Num4";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} setFastSpeed;
|
||||
|
||||
struct SetFastestSpeed : HotkeyInput {
|
||||
void pressed() {
|
||||
config().system.speed = 4;
|
||||
utility.updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
SetFastestSpeed() : HotkeyInput("Set Fastest Speed", "config.userInterface.emulationSpeed.setFastest") {
|
||||
name = "Control+KB0::Num5";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} setFastestSpeed;
|
||||
|
||||
struct SynchronizeVideo : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleSynchronizeVideo();
|
||||
}
|
||||
|
||||
SynchronizeVideo() : HotkeyInput("Synchronize Video", "config.userInterface.emulationSpeed.synchronizeVideo") {
|
||||
name = "Control+KB0::V";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} synchronizeVideo;
|
||||
|
||||
struct SynchronizeAudio : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleSynchronizeAudio();
|
||||
}
|
||||
|
||||
SynchronizeAudio() : HotkeyInput("Synchronize Audio", "config.userInterface.emulationSpeed.synchronizeAudio") {
|
||||
name = "Control+KB0::A";
|
||||
userInterfaceEmulationSpeed.attach(this);
|
||||
}
|
||||
} synchronizeAudio;
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
InputGroup userInterfaceGeneral(InputCategory::UserInterface, "General");
|
||||
|
||||
namespace UserInterfaceGeneral {
|
||||
|
||||
struct ToggleMenubar : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleMenubar();
|
||||
}
|
||||
|
||||
ToggleMenubar() : HotkeyInput("Toggle Menubar", "input.userInterface.general.toggleMenubar") {
|
||||
name = "KB0::F12";
|
||||
userInterfaceGeneral.attach(this);
|
||||
}
|
||||
} toggleMenubar;
|
||||
|
||||
struct ToggleStatusbar : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleStatusbar();
|
||||
}
|
||||
|
||||
ToggleStatusbar() : HotkeyInput("Toggle Statusbar", "input.userInterface.general.toggleStatusbar") {
|
||||
name = "KB0::F12";
|
||||
userInterfaceGeneral.attach(this);
|
||||
}
|
||||
} toggleStatusbar;
|
||||
|
||||
struct ToggleCheatSystem : HotkeyInput {
|
||||
void pressed() {
|
||||
if(SNES::cheat.enabled() == false) {
|
||||
SNES::cheat.enable();
|
||||
utility.showMessage("Cheat system enabled.");
|
||||
} else {
|
||||
SNES::cheat.disable();
|
||||
utility.showMessage("Cheat system disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
ToggleCheatSystem() : HotkeyInput("Toggle Cheat System", "input.userInterface.general.toggleCheatSystem") {
|
||||
userInterfaceGeneral.attach(this);
|
||||
}
|
||||
} toggleCheatSystem;
|
||||
|
||||
struct CaptureScreenshot : HotkeyInput {
|
||||
void pressed() {
|
||||
//tell SNES::Interface to save a screenshot at the next video_refresh() event
|
||||
interface.saveScreenshot = true;
|
||||
}
|
||||
|
||||
CaptureScreenshot() : HotkeyInput("Capture Screenshot", "input.userInterface.general.captureScreenshot") {
|
||||
userInterfaceGeneral.attach(this);
|
||||
}
|
||||
} captureScreenshot;
|
||||
|
||||
//put here instead of in a separate "Audio Settings" group,
|
||||
//because there is only one audio option at present
|
||||
struct MuteAudioOutput : HotkeyInput {
|
||||
void pressed() {
|
||||
mainWindow->settings_muteAudio->toggleChecked();
|
||||
config().audio.mute = mainWindow->settings_muteAudio->isChecked();
|
||||
}
|
||||
|
||||
MuteAudioOutput() : HotkeyInput("Mute Audio Output", "input.userInterface.general.muteAudioOutput") {
|
||||
name = "Shift+KB0::M";
|
||||
userInterfaceGeneral.attach(this);
|
||||
}
|
||||
} muteAudioOutput;
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
InputGroup userInterfaceStates(InputCategory::UserInterface, "States");
|
||||
|
||||
namespace UserInterfaceStates {
|
||||
|
||||
//note: interally, there are ten quick save slots: 0-9
|
||||
//for the sake of users, this is displayed as 1-10 in the GUI
|
||||
unsigned activeState = 0;
|
||||
|
||||
struct LoadActiveState : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickLoad(activeState);
|
||||
}
|
||||
|
||||
LoadActiveState() : HotkeyInput("Load Active Quick State", "input.userInterface.states.loadActiveQuickState") {
|
||||
name = "KB0::F2";
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} loadActiveState;
|
||||
|
||||
struct SaveActiveState : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickSave(activeState);
|
||||
}
|
||||
|
||||
SaveActiveState() : HotkeyInput("Save Active Quick State", "input.userInterface.states.saveActiveQuickState") {
|
||||
name = "Shift+KB0::F2";
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} saveActiveState;
|
||||
|
||||
struct DecrementActiveState : HotkeyInput {
|
||||
void pressed() {
|
||||
activeState = (activeState + 10 - 1) % 10;
|
||||
utility.showMessage(string() << "Quick state " << (activeState + 1) << " selected.");
|
||||
}
|
||||
|
||||
DecrementActiveState() : HotkeyInput("Decrement Active Quick State Slot", "input.userInterface.states.decrementActiveQuickState") {
|
||||
name = "KB0::F3";
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} decrementActiveState;
|
||||
|
||||
struct IncrementActiveState : HotkeyInput {
|
||||
void pressed() {
|
||||
activeState = (activeState + 10 + 1) % 10;
|
||||
utility.showMessage(string() << "Quick state " << (activeState + 1) << " selected.");
|
||||
}
|
||||
|
||||
IncrementActiveState() : HotkeyInput("Increment Active Quick State Slot", "input.userInterface.states.incrementActiveQuickState") {
|
||||
name = "KB0::F4";
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} incrementActiveState;
|
||||
|
||||
struct LoadState1 : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickLoad(0);
|
||||
}
|
||||
|
||||
LoadState1() : HotkeyInput("Load Quick State 1", "input.userInterface.states.loadQuickState1") {
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} loadState1;
|
||||
|
||||
struct LoadState2 : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickLoad(1);
|
||||
}
|
||||
|
||||
LoadState2() : HotkeyInput("Load Quick State 2", "input.userInterface.states.loadQuickState2") {
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} loadState2;
|
||||
|
||||
struct LoadState3 : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickLoad(2);
|
||||
}
|
||||
|
||||
LoadState3() : HotkeyInput("Load Quick State 3", "input.userInterface.states.loadQuickState3") {
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} loadState3;
|
||||
|
||||
struct SaveState1 : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickSave(0);
|
||||
}
|
||||
|
||||
SaveState1() : HotkeyInput("Save Quick State 1", "input.userInterface.states.saveQuickState1") {
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} saveState1;
|
||||
|
||||
struct SaveState2 : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickSave(1);
|
||||
}
|
||||
|
||||
SaveState2() : HotkeyInput("Save Quick State 2", "input.userInterface.states.saveQuickState2") {
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} saveState2;
|
||||
|
||||
struct SaveState3 : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.quickSave(2);
|
||||
}
|
||||
|
||||
SaveState3() : HotkeyInput("Save Quick State 3", "input.userInterface.states.saveQuickState3") {
|
||||
userInterfaceStates.attach(this);
|
||||
}
|
||||
} saveState3;
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
InputGroup userInterfaceSystem(InputCategory::UserInterface, "System");
|
||||
|
||||
namespace UserInterfaceSystem {
|
||||
|
||||
struct LoadCartridge : HotkeyInput {
|
||||
void pressed() {
|
||||
diskBrowser->loadCartridge();
|
||||
}
|
||||
|
||||
LoadCartridge() : HotkeyInput("Load Cartridge", "input.userInterface.system.loadCartridge") {
|
||||
name = "Shift+KB0::L";
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} loadCartridge;
|
||||
|
||||
struct LoadBsxSlottedCartridge : HotkeyInput {
|
||||
void pressed() {
|
||||
loaderWindow->loadBsxSlottedCartridge("", "");
|
||||
}
|
||||
|
||||
LoadBsxSlottedCartridge() : HotkeyInput("Load BS-X Slotted Cartridge", "input.userInterface.system.loadBsxSlottedcartridge") {
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} loadBsxSlottedCartridge;
|
||||
|
||||
struct LoadBsxCartridge : HotkeyInput {
|
||||
void pressed() {
|
||||
loaderWindow->loadBsxCartridge(config().path.bsx, "");
|
||||
}
|
||||
|
||||
LoadBsxCartridge() : HotkeyInput("Load BS-X Cartridge", "input.userInterface.system.loadBsxCartridge") {
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} loadBsxCartridge;
|
||||
|
||||
struct LoadSufamiTurboCartridge : HotkeyInput {
|
||||
void pressed() {
|
||||
loaderWindow->loadSufamiTurboCartridge(config().path.st, "", "");
|
||||
}
|
||||
|
||||
LoadSufamiTurboCartridge() : HotkeyInput("Load Sufami Turbo Cartridge", "input.userInterface.system.loadSufamiTurboCartridge") {
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} loadSufamiTurboCartridge;
|
||||
|
||||
struct LoadSuperGameBoyCartridge : HotkeyInput {
|
||||
void pressed() {
|
||||
loaderWindow->loadSuperGameBoyCartridge(config().path.sgb, "");
|
||||
}
|
||||
|
||||
LoadSuperGameBoyCartridge() : HotkeyInput("Load Super Game Boy Cartridge", "input.userInterface.system.loadSuperGameBoyCartridge") {
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} loadSuperGameBoyCartridge;
|
||||
|
||||
struct PowerCycle : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.modifySystemState(Utility::PowerCycle);
|
||||
}
|
||||
|
||||
PowerCycle() : HotkeyInput("Power Cycle", "input.userInterface.system.powerCycle") {
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} powerCycle;
|
||||
|
||||
struct Reset : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.modifySystemState(Utility::Reset);
|
||||
}
|
||||
|
||||
Reset() : HotkeyInput("Reset", "input.userInterface.system.reset") {
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} reset;
|
||||
|
||||
struct Pause : HotkeyInput {
|
||||
void pressed() {
|
||||
application.pause = !application.pause;
|
||||
if(application.pause) audio.clear();
|
||||
}
|
||||
|
||||
Pause() : HotkeyInput("Pause", "input.userInterface.system.pause") {
|
||||
name = "KB0::Pause";
|
||||
userInterfaceSystem.attach(this);
|
||||
}
|
||||
} pause;
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
InputGroup userInterfaceVideoSettings(InputCategory::UserInterface, "Video Settings");
|
||||
|
||||
namespace UserInterfaceVideoSettings {
|
||||
|
||||
struct ToggleFullscreen : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleFullscreen();
|
||||
}
|
||||
|
||||
ToggleFullscreen() : HotkeyInput("Toggle Fullscreen Mode", "input.userInterface.videoSettings.toggleFullscreen") {
|
||||
name = "KB0::F11";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} toggleFullscreen;
|
||||
|
||||
struct SmoothVideoOutput : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleSmoothVideoOutput();
|
||||
}
|
||||
|
||||
SmoothVideoOutput() : HotkeyInput("Smooth Video Output", "input.userInterface.videoSettings.smoothVideoOutput") {
|
||||
name = "Shift+KB0::S";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} smoothVideoOutput;
|
||||
|
||||
struct SetNtscMode : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setNtscMode();
|
||||
}
|
||||
|
||||
SetNtscMode() : HotkeyInput("Set NTSC Mode", "input.userInterface.videoSettings.ntscMode") {
|
||||
name = "Shift+KB0::N";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} setNtscMode;
|
||||
|
||||
struct SetPalMode : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setPalMode();
|
||||
}
|
||||
|
||||
SetPalMode() : HotkeyInput("Set PAL Mode", "input.userInterface.videoSettings.palMode") {
|
||||
name = "Shift+KB0::P";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} setPalMode;
|
||||
|
||||
struct AspectCorrection : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.toggleAspectCorrection();
|
||||
}
|
||||
|
||||
AspectCorrection() : HotkeyInput("Aspect Correction", "input.userInterface.videoSettings.aspectCorrection") {
|
||||
name = "Shift+KB0::A";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} aspectCorrection;
|
||||
|
||||
struct Scale1x : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setScale(1);
|
||||
}
|
||||
|
||||
Scale1x() : HotkeyInput("Scale 1x", "input.userInterface.videoSettings.scale1x") {
|
||||
name = "Shift+KB0::Num1";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scale1x;
|
||||
|
||||
struct Scale2x : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setScale(2);
|
||||
}
|
||||
|
||||
Scale2x() : HotkeyInput("Scale 2x", "input.userInterface.videoSettings.scale2x") {
|
||||
name = "Shift+KB0::Num2";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scale2x;
|
||||
|
||||
struct Scale3x : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setScale(3);
|
||||
}
|
||||
|
||||
Scale3x() : HotkeyInput("Scale 3x", "input.userInterface.videoSettings.scale3x") {
|
||||
name = "Shift+KB0::Num3";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scale3x;
|
||||
|
||||
struct Scale4x : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setScale(4);
|
||||
}
|
||||
|
||||
Scale4x() : HotkeyInput("Scale 4x", "input.userInterface.videoSettings.scale4x") {
|
||||
name = "Shift+KB0::Num4";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scale4x;
|
||||
|
||||
struct Scale5x : HotkeyInput {
|
||||
void pressed() {
|
||||
utility.setScale(5);
|
||||
}
|
||||
|
||||
Scale5x() : HotkeyInput("Scale 5x", "input.userInterface.videoSettings.scale5x") {
|
||||
name = "Shift+KB0::Num5";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scale5x;
|
||||
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
//==============
|
||||
//InputGroupPool
|
||||
//==============
|
||||
|
||||
void InputGroupPool::attach(InputGroup &group) {
|
||||
list.add(&group);
|
||||
}
|
||||
|
||||
void InputGroupPool::bind() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->bind();
|
||||
}
|
||||
|
||||
void InputGroupPool::clear() {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->clear();
|
||||
}
|
||||
|
||||
void InputGroupPool::poll(const int16_t *table) {
|
||||
for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table);
|
||||
}
|
||||
|
||||
InputGroupPool::InputGroupPool() : list(*this) {
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
InputUiGeneral inputUiGeneral;
|
||||
InputUiPool inputUiPool;
|
||||
|
||||
InputUiGeneral::InputUiGeneral() : InputGroup("General"),
|
||||
loadCartridge(InputObject::Button, "Load cartridge", config.input.uiGeneral.loadCartridge),
|
||||
pauseEmulation(InputObject::Button, "Pause emulation", config.input.uiGeneral.pauseEmulation),
|
||||
resetSystem(InputObject::Button, "Reset system", config.input.uiGeneral.resetSystem),
|
||||
powerCycleSystem(InputObject::Button, "Power cycle system", config.input.uiGeneral.powerCycleSystem),
|
||||
|
||||
captureScreenshot(InputObject::Button, "Capture screenshot", config.input.uiGeneral.captureScreenshot),
|
||||
showStateManager(InputObject::Button, "Show state manager window", config.input.uiGeneral.showStateManager),
|
||||
quickLoad1(InputObject::Button, "Load from temporary state 1", config.input.uiGeneral.quickLoad1),
|
||||
quickLoad2(InputObject::Button, "Load from temporary state 2", config.input.uiGeneral.quickLoad2),
|
||||
quickLoad3(InputObject::Button, "Load from temporary state 3", config.input.uiGeneral.quickLoad3),
|
||||
quickSave1(InputObject::Button, "Save to temporary state 1", config.input.uiGeneral.quickSave1),
|
||||
quickSave2(InputObject::Button, "Save to temporary state 2", config.input.uiGeneral.quickSave2),
|
||||
quickSave3(InputObject::Button, "Save to temporary state 3", config.input.uiGeneral.quickSave3),
|
||||
|
||||
lowerSpeed(InputObject::Button, "Decrease emulation speed", config.input.uiGeneral.lowerSpeed),
|
||||
raiseSpeed(InputObject::Button, "Increase emulation speed", config.input.uiGeneral.raiseSpeed),
|
||||
toggleCheatSystem(InputObject::Button, "Toggle cheat system on or off", config.input.uiGeneral.toggleCheatSystem),
|
||||
toggleFullscreen(InputObject::Button, "Toggle fullscreen mode", config.input.uiGeneral.toggleFullscreen),
|
||||
toggleMenu(InputObject::Button, "Toggle menubar", config.input.uiGeneral.toggleMenu),
|
||||
toggleStatus(InputObject::Button, "Toggle statusbar", config.input.uiGeneral.toggleStatus),
|
||||
exitEmulator(InputObject::Button, "Exit emulator", config.input.uiGeneral.exitEmulator) {
|
||||
attach(loadCartridge);
|
||||
attach(pauseEmulation);
|
||||
attach(resetSystem);
|
||||
attach(powerCycleSystem);
|
||||
|
||||
attach(captureScreenshot);
|
||||
attach(showStateManager);
|
||||
attach(quickLoad1);
|
||||
attach(quickLoad2);
|
||||
attach(quickLoad3);
|
||||
attach(quickSave1);
|
||||
attach(quickSave2);
|
||||
attach(quickSave3);
|
||||
|
||||
attach(lowerSpeed);
|
||||
attach(raiseSpeed);
|
||||
attach(toggleCheatSystem);
|
||||
attach(toggleFullscreen);
|
||||
attach(toggleMenu);
|
||||
attach(toggleStatus);
|
||||
attach(exitEmulator);
|
||||
}
|
||||
|
||||
InputUiPool::InputUiPool() {
|
||||
attach(inputUiGeneral);
|
||||
}
|
|
@ -1,41 +1,5 @@
|
|||
struct InputUiGeneral : public InputGroup {
|
||||
InputObject loadCartridge;
|
||||
InputObject pauseEmulation;
|
||||
InputObject resetSystem;
|
||||
InputObject powerCycleSystem;
|
||||
InputObject captureScreenshot;
|
||||
InputObject showStateManager;
|
||||
InputObject quickLoad1;
|
||||
InputObject quickLoad2;
|
||||
InputObject quickLoad3;
|
||||
InputObject quickSave1;
|
||||
InputObject quickSave2;
|
||||
InputObject quickSave3;
|
||||
InputObject lowerSpeed;
|
||||
InputObject raiseSpeed;
|
||||
InputObject toggleCheatSystem;
|
||||
InputObject toggleFullscreen;
|
||||
InputObject toggleMenu;
|
||||
InputObject toggleStatus;
|
||||
InputObject exitEmulator;
|
||||
|
||||
InputUiGeneral();
|
||||
};
|
||||
|
||||
struct InputGroupPool : public array<InputGroup*> {
|
||||
void attach(InputGroup &group);
|
||||
void bind();
|
||||
void clear();
|
||||
void poll(const int16_t *table);
|
||||
InputGroupPool();
|
||||
|
||||
private:
|
||||
array<InputGroup*> &list;
|
||||
};
|
||||
|
||||
struct InputUiPool : public InputGroupPool {
|
||||
InputUiPool();
|
||||
};
|
||||
|
||||
extern InputUiGeneral inputUiGeneral;
|
||||
extern InputUiPool inputUiPool;
|
||||
extern InputGroup userInterfaceGeneral;
|
||||
extern InputGroup userInterfaceSystem;
|
||||
extern InputGroup userInterfaceEmulationSpeed;
|
||||
extern InputGroup userInterfaceStates;
|
||||
extern InputGroup userInterfaceVideoSettings;
|
||||
|
|
|
@ -14,16 +14,16 @@ void Interface::video_refresh(uint16_t *data, unsigned pitch, unsigned *line, un
|
|||
}
|
||||
|
||||
void Interface::audio_sample(uint16_t left, uint16_t right) {
|
||||
if(config.audio.mute) left = right = 0;
|
||||
if(config().audio.mute) left = right = 0;
|
||||
audio.sample(left, right);
|
||||
}
|
||||
|
||||
void Interface::input_poll() {
|
||||
inputManager.poll();
|
||||
mapper().cache();
|
||||
}
|
||||
|
||||
int16_t Interface::input_poll(unsigned deviceid, unsigned id) {
|
||||
return inputManager.getStatus(deviceid, id);
|
||||
int16_t Interface::input_poll(bool port, unsigned device, unsigned index, unsigned id) {
|
||||
return mapper().status(port, device, index, id);
|
||||
}
|
||||
|
||||
void Interface::captureScreenshot(uint32_t *data, unsigned pitch, unsigned width, unsigned height) {
|
||||
|
@ -40,9 +40,9 @@ void Interface::captureScreenshot(uint32_t *data, unsigned pitch, unsigned width
|
|||
);
|
||||
filename << t << ".png";
|
||||
|
||||
string path = config.path.data;
|
||||
string path = config().path.data;
|
||||
if(path == "") path = dir(utility.cartridge.baseName);
|
||||
image.save(utf8() << path << filename);
|
||||
image.save(string() << path << filename);
|
||||
utility.showMessage("Screenshot saved.");
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ public:
|
|||
void video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height);
|
||||
void audio_sample(uint16_t left, uint16_t right);
|
||||
void input_poll();
|
||||
int16_t input_poll(unsigned deviceid, unsigned id);
|
||||
int16_t input_poll(bool port, unsigned device, unsigned index, unsigned id);
|
||||
|
||||
Interface();
|
||||
void captureScreenshot(uint32_t*, unsigned, unsigned, unsigned);
|
||||
|
|
|
@ -1,3 +1,81 @@
|
|||
//==============
|
||||
//ScanlineFilter
|
||||
//==============
|
||||
|
||||
ScanlineFilter scanlineFilter;
|
||||
|
||||
void ScanlineFilter::size(unsigned &width, unsigned &height) {
|
||||
if(enabled && height <= 240) height *= 2;
|
||||
}
|
||||
|
||||
void ScanlineFilter::render(
|
||||
const uint16_t *&input, unsigned &pitch,
|
||||
const unsigned *&line, unsigned width, unsigned &height
|
||||
) {
|
||||
if(enabled && height <= 240) {
|
||||
pitch >>= 1;
|
||||
|
||||
const uint16_t *sp = input;
|
||||
uint16_t *dp = buffer;
|
||||
unsigned *lp = linewidth;
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
for(unsigned x = 0; x < line[y]; x++) {
|
||||
uint16_t color = *sp++;
|
||||
*(dp + 0) = color;
|
||||
*(dp + 512) = adjust[color];
|
||||
dp++;
|
||||
}
|
||||
|
||||
sp += pitch - line[y];
|
||||
dp += 1024 - line[y];
|
||||
|
||||
*lp++ = line[y];
|
||||
*lp++ = line[y];
|
||||
}
|
||||
|
||||
input = buffer;
|
||||
pitch = 1024;
|
||||
line = linewidth;
|
||||
height *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void ScanlineFilter::setIntensity(unsigned intensity) {
|
||||
if(intensity >= 100) {
|
||||
enabled = false;
|
||||
} else {
|
||||
enabled = true;
|
||||
|
||||
for(unsigned i = 0; i < 32768; i++) {
|
||||
unsigned r = (i >> 0) & 31;
|
||||
unsigned g = (i >> 5) & 31;
|
||||
unsigned b = (i >> 10) & 31;
|
||||
|
||||
r = (double)r * (double)intensity / 100.0;
|
||||
g = (double)g * (double)intensity / 100.0;
|
||||
b = (double)b * (double)intensity / 100.0;
|
||||
|
||||
adjust[i] = (r << 0) + (g << 5) + (b << 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScanlineFilter::ScanlineFilter() {
|
||||
enabled = false;
|
||||
adjust = new uint16_t[32768];
|
||||
buffer = new uint16_t[512 * 480];
|
||||
setIntensity(50);
|
||||
}
|
||||
|
||||
ScanlineFilter::~ScanlineFilter() {
|
||||
delete[] adjust;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
//======
|
||||
//Filter
|
||||
//======
|
||||
|
||||
Filter filter;
|
||||
|
||||
const uint8_t Filter::gamma_ramp_table[32] = {
|
||||
|
@ -90,8 +168,10 @@ void Filter::colortable_update() {
|
|||
}
|
||||
|
||||
void Filter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
scanlineFilter.size(width, height);
|
||||
|
||||
if(opened() && renderer > 0) {
|
||||
return dl_size(renderer - 1, outwidth, outheight, width, height);
|
||||
return dl_size(renderer, outwidth, outheight, width, height);
|
||||
}
|
||||
|
||||
outwidth = width;
|
||||
|
@ -103,8 +183,10 @@ void Filter::render(
|
|||
const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
) {
|
||||
scanlineFilter.render(input, pitch, line, width, height);
|
||||
|
||||
if(opened() && renderer > 0) {
|
||||
return dl_render(renderer - 1, output, outpitch, input, pitch, line, width, height);
|
||||
return dl_render(renderer, output, outpitch, input, pitch, line, width, height);
|
||||
}
|
||||
|
||||
pitch >>= 1;
|
||||
|
@ -131,7 +213,7 @@ void Filter::render(
|
|||
|
||||
QWidget* Filter::settings() {
|
||||
if(opened() && renderer > 0) {
|
||||
return dl_settings(renderer - 1);
|
||||
return dl_settings(renderer);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -161,10 +243,10 @@ Filter::Filter() {
|
|||
dl_settings = sym("snesfilter_settings");
|
||||
|
||||
dl_colortable(colortable);
|
||||
dl_configuration(config);
|
||||
dl_configuration(config());
|
||||
} else {
|
||||
config.video.windowed.swFilter = 0;
|
||||
config.video.fullscreen.swFilter = 0;
|
||||
config().video.windowed.swFilter = 0;
|
||||
config().video.fullscreen.swFilter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
class ScanlineFilter {
|
||||
public:
|
||||
bool enabled;
|
||||
|
||||
void size(unsigned&, unsigned&);
|
||||
void render(const uint16_t*&, unsigned&, const unsigned*&, unsigned, unsigned&);
|
||||
void setIntensity(unsigned);
|
||||
|
||||
ScanlineFilter();
|
||||
~ScanlineFilter();
|
||||
|
||||
private:
|
||||
uint16_t *adjust;
|
||||
uint16_t *buffer;
|
||||
unsigned linewidth[480];
|
||||
};
|
||||
|
||||
class Filter : public library {
|
||||
public:
|
||||
function<const char* ()> dl_supported;
|
||||
|
@ -34,4 +51,5 @@ private:
|
|||
uint8_t gamma_adjust(uint8_t input);
|
||||
};
|
||||
|
||||
extern ScanlineFilter scanlineFilter;
|
||||
extern Filter filter;
|
||||
|
|
|
@ -31,13 +31,14 @@ Reader::Reader() {
|
|||
load = bind(&Reader::direct_load, this);
|
||||
}
|
||||
|
||||
filterList = supported();
|
||||
if(filterList.length() > 0) {
|
||||
filterList = string()
|
||||
compressionList = supported();
|
||||
if(compressionList.length() > 0) compressionList = string() << " " << compressionList;
|
||||
|
||||
if(opened()) {
|
||||
extensionList = string()
|
||||
<< " *.smc *.swc *.fig"
|
||||
<< " *.ufo *.gd3 *.gd7 *.dx2 *.mgd *.mgh"
|
||||
<< " *.048 *.058 *.068 *.078 *.bin"
|
||||
<< " *.usa *.eur *.jap *.aus *.bsx"
|
||||
<< " " << filterList;
|
||||
<< " *.usa *.eur *.jap *.aus *.bsx";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class Reader : public library {
|
||||
public:
|
||||
string filterList;
|
||||
string compressionList;
|
||||
string extensionList;
|
||||
|
||||
function<const char* ()> supported;
|
||||
function<bool (string&, uint8_t*&, unsigned&)> load;
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
#include "main.hpp"
|
||||
#include "resource/resource.rcc"
|
||||
|
||||
//nall::string <> QString interface: allows string streaming; automatically converts to UTF-16
|
||||
class utf8 : public nall::string {
|
||||
public:
|
||||
template<typename T> utf8& operator<<(T t) { string::operator<<(t); return *this; }
|
||||
operator const QString() const { return QString::fromUtf8(*this); }
|
||||
};
|
||||
|
||||
#if defined(PLATFORM_X)
|
||||
#include "platform/platform_x.cpp"
|
||||
#elif defined(PLATFORM_OSX)
|
||||
|
@ -27,18 +20,11 @@ const char defaultStylesheet[] =
|
|||
" margin-bottom: 5px;"
|
||||
" margin-left: -5px;"
|
||||
" margin-top: 5px;"
|
||||
"}"
|
||||
"\n"
|
||||
"}\n"
|
||||
|
||||
"#backdrop {"
|
||||
" background: #000000;"
|
||||
"}"
|
||||
"\n"
|
||||
"#mouse-capture-box {"
|
||||
" border: 1px solid #808080;"
|
||||
" color: #000000;"
|
||||
" font-weight: bold;"
|
||||
"}"
|
||||
"\n";
|
||||
"}\n";
|
||||
|
||||
#include "application/application.cpp"
|
||||
#include "debugger/debugger.cpp"
|
||||
|
|
|
@ -127,20 +127,20 @@ void AdvancedSettingsWindow::initializeUi() {
|
|||
|
||||
part.split(";", video.driver_list());
|
||||
for(unsigned i = 0; i < part.size(); i++) {
|
||||
videoDriver->addItem(utf8() << part[i]);
|
||||
if(part[i] == config.system.video) videoDriver->setCurrentIndex(i);
|
||||
videoDriver->addItem(part[i]);
|
||||
if(part[i] == config().system.video) videoDriver->setCurrentIndex(i);
|
||||
}
|
||||
|
||||
part.split(";", audio.driver_list());
|
||||
for(unsigned i = 0; i < part.size(); i++) {
|
||||
audioDriver->addItem(utf8() << part[i]);
|
||||
if(part[i] == config.system.audio) audioDriver->setCurrentIndex(i);
|
||||
audioDriver->addItem(part[i]);
|
||||
if(part[i] == config().system.audio) audioDriver->setCurrentIndex(i);
|
||||
}
|
||||
|
||||
part.split(";", input.driver_list());
|
||||
for(unsigned i = 0; i < part.size(); i++) {
|
||||
inputDriver->addItem(utf8() << part[i]);
|
||||
if(part[i] == config.system.input) inputDriver->setCurrentIndex(i);
|
||||
inputDriver->addItem(part[i]);
|
||||
if(part[i] == config().system.input) inputDriver->setCurrentIndex(i);
|
||||
}
|
||||
|
||||
regionAuto->setChecked(SNES::config.region == SNES::System::Autodetect);
|
||||
|
@ -150,21 +150,21 @@ void AdvancedSettingsWindow::initializeUi() {
|
|||
portSatellaview->setChecked(SNES::config.expansion_port == SNES::System::ExpansionBSX);
|
||||
portNone->setChecked (SNES::config.expansion_port == SNES::System::ExpansionNone);
|
||||
|
||||
focusPause->setChecked (config.input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation);
|
||||
focusIgnore->setChecked(config.input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput);
|
||||
focusAllow->setChecked (config.input.focusPolicy == Configuration::Input::FocusPolicyAllowInput);
|
||||
focusPause->setChecked (config().input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation);
|
||||
focusIgnore->setChecked(config().input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput);
|
||||
focusAllow->setChecked (config().input.focusPolicy == Configuration::Input::FocusPolicyAllowInput);
|
||||
}
|
||||
|
||||
void AdvancedSettingsWindow::videoDriverChange(int index) {
|
||||
if(index >= 0) config.system.video = videoDriver->itemText(index).toUtf8().data();
|
||||
if(index >= 0) config().system.video = videoDriver->itemText(index).toUtf8().data();
|
||||
}
|
||||
|
||||
void AdvancedSettingsWindow::audioDriverChange(int index) {
|
||||
if(index >= 0) config.system.audio = audioDriver->itemText(index).toUtf8().data();
|
||||
if(index >= 0) config().system.audio = audioDriver->itemText(index).toUtf8().data();
|
||||
}
|
||||
|
||||
void AdvancedSettingsWindow::inputDriverChange(int index) {
|
||||
if(index >= 0) config.system.input = inputDriver->itemText(index).toUtf8().data();
|
||||
if(index >= 0) config().system.input = inputDriver->itemText(index).toUtf8().data();
|
||||
}
|
||||
|
||||
void AdvancedSettingsWindow::setRegionAuto() { SNES::config.region = SNES::System::Autodetect; }
|
||||
|
@ -174,6 +174,6 @@ void AdvancedSettingsWindow::setRegionPAL() { SNES::config.region = SNES::Syste
|
|||
void AdvancedSettingsWindow::setPortSatellaview() { SNES::config.expansion_port = SNES::System::ExpansionBSX; }
|
||||
void AdvancedSettingsWindow::setPortNone() { SNES::config.expansion_port = SNES::System::ExpansionNone; }
|
||||
|
||||
void AdvancedSettingsWindow::pauseWithoutFocus() { config.input.focusPolicy = Configuration::Input::FocusPolicyPauseEmulation; }
|
||||
void AdvancedSettingsWindow::ignoreInputWithoutFocus() { config.input.focusPolicy = Configuration::Input::FocusPolicyIgnoreInput; }
|
||||
void AdvancedSettingsWindow::allowInputWithoutFocus() { config.input.focusPolicy = Configuration::Input::FocusPolicyAllowInput; }
|
||||
void AdvancedSettingsWindow::pauseWithoutFocus() { config().input.focusPolicy = Configuration::Input::FocusPolicyPauseEmulation; }
|
||||
void AdvancedSettingsWindow::ignoreInputWithoutFocus() { config().input.focusPolicy = Configuration::Input::FocusPolicyIgnoreInput; }
|
||||
void AdvancedSettingsWindow::allowInputWithoutFocus() { config().input.focusPolicy = Configuration::Input::FocusPolicyAllowInput; }
|
||||
|
|
|
@ -39,16 +39,21 @@ AudioSettingsWindow::AudioSettingsWindow() {
|
|||
layout->addSpacing(Style::WidgetSpacing);
|
||||
|
||||
sliders = new QGridLayout; {
|
||||
volumeLabel = new QLabel("Volume: 100%");
|
||||
volumeLabel = new QLabel("Volume:");
|
||||
volumeLabel->setToolTip("Warning: any volume other than 100% will result in a slight audio quality loss");
|
||||
sliders->addWidget(volumeLabel, 0, 0);
|
||||
|
||||
volumeValue = new QLabel;
|
||||
volumeValue->setAlignment(Qt::AlignHCenter);
|
||||
volumeValue->setMinimumWidth(volumeValue->fontMetrics().width("262144hz"));
|
||||
sliders->addWidget(volumeValue, 0, 1);
|
||||
|
||||
volume = new QSlider(Qt::Horizontal);
|
||||
volume->setMinimum(0);
|
||||
volume->setMaximum(200);
|
||||
sliders->addWidget(volume, 0, 1);
|
||||
sliders->addWidget(volume, 0, 2);
|
||||
|
||||
frequencySkewLabel = new QLabel("Input frequency: 32000hz");
|
||||
frequencySkewLabel = new QLabel("Input frequency:");
|
||||
frequencySkewLabel->setToolTip(
|
||||
"Adjusts audio resampling rate.\n"
|
||||
"When both video sync and audio sync are enabled, use this setting to fine-tune the output.\n"
|
||||
|
@ -57,10 +62,14 @@ AudioSettingsWindow::AudioSettingsWindow() {
|
|||
);
|
||||
sliders->addWidget(frequencySkewLabel, 1, 0);
|
||||
|
||||
frequencySkewValue = new QLabel;
|
||||
frequencySkewValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(frequencySkewValue, 1, 1);
|
||||
|
||||
frequencySkew = new QSlider(Qt::Horizontal);
|
||||
frequencySkew->setMinimum(31800);
|
||||
frequencySkew->setMaximum(32200);
|
||||
sliders->addWidget(frequencySkew);
|
||||
frequencySkew->setMinimum(31500);
|
||||
frequencySkew->setMaximum(32500);
|
||||
sliders->addWidget(frequencySkew, 1, 2);
|
||||
}
|
||||
sliders->setSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(sliders);
|
||||
|
@ -76,50 +85,50 @@ AudioSettingsWindow::AudioSettingsWindow() {
|
|||
void AudioSettingsWindow::syncUi() {
|
||||
int n;
|
||||
|
||||
n = config.audio.outputFrequency;
|
||||
n = config().audio.outputFrequency;
|
||||
if(n <= 32000) frequency->setCurrentIndex(0);
|
||||
else if(n <= 44100) frequency->setCurrentIndex(1);
|
||||
else if(n <= 48000) frequency->setCurrentIndex(2);
|
||||
else if(n <= 96000) frequency->setCurrentIndex(3);
|
||||
else frequency->setCurrentIndex(0);
|
||||
|
||||
n = config.audio.latency;
|
||||
n = config().audio.latency;
|
||||
latency->setCurrentIndex((n - 20) / 20);
|
||||
|
||||
n = config.audio.volume;
|
||||
volumeLabel->setText(utf8() << "Volume: " << n << "%");
|
||||
n = config().audio.volume;
|
||||
volumeValue->setText(string() << n << "%");
|
||||
volume->setSliderPosition(n);
|
||||
|
||||
n = config.audio.inputFrequency;
|
||||
frequencySkewLabel->setText(utf8() << "Input frequency: " << n << "hz");
|
||||
n = config().audio.inputFrequency;
|
||||
frequencySkewValue->setText(string() << n << "hz");
|
||||
frequencySkew->setSliderPosition(n);
|
||||
}
|
||||
|
||||
void AudioSettingsWindow::frequencyChange(int value) {
|
||||
switch(value) { default:
|
||||
case 0: config.audio.outputFrequency = 32000; break;
|
||||
case 1: config.audio.outputFrequency = 44100; break;
|
||||
case 2: config.audio.outputFrequency = 48000; break;
|
||||
case 3: config.audio.outputFrequency = 96000; break;
|
||||
case 0: config().audio.outputFrequency = 32000; break;
|
||||
case 1: config().audio.outputFrequency = 44100; break;
|
||||
case 2: config().audio.outputFrequency = 48000; break;
|
||||
case 3: config().audio.outputFrequency = 96000; break;
|
||||
}
|
||||
audio.set(Audio::Frequency, config.audio.outputFrequency);
|
||||
audio.set(Audio::Frequency, config().audio.outputFrequency);
|
||||
utility.updateEmulationSpeed();
|
||||
}
|
||||
|
||||
void AudioSettingsWindow::latencyChange(int value) {
|
||||
value = max(0, min(5, value));
|
||||
config.audio.latency = 20 + value * 20;
|
||||
audio.set(Audio::Latency, config.audio.latency);
|
||||
config().audio.latency = 20 + value * 20;
|
||||
audio.set(Audio::Latency, config().audio.latency);
|
||||
}
|
||||
|
||||
void AudioSettingsWindow::volumeAdjust(int value) {
|
||||
config.audio.volume = value;
|
||||
audio.set(Audio::Volume, config.audio.volume);
|
||||
config().audio.volume = value;
|
||||
audio.set(Audio::Volume, config().audio.volume);
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void AudioSettingsWindow::frequencySkewAdjust(int value) {
|
||||
config.audio.inputFrequency = value;
|
||||
config().audio.inputFrequency = value;
|
||||
utility.updateEmulationSpeed();
|
||||
syncUi();
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ public:
|
|||
QComboBox *latency;
|
||||
QGridLayout *sliders;
|
||||
QLabel *volumeLabel;
|
||||
QLabel *volumeValue;
|
||||
QSlider *volume;
|
||||
QLabel *frequencySkewLabel;
|
||||
QLabel *frequencySkewValue;
|
||||
QSlider *frequencySkew;
|
||||
|
||||
void syncUi();
|
||||
|
|
|
@ -1,26 +1,33 @@
|
|||
InputSettingsWindow::InputSettingsWindow() {
|
||||
InputSettingsWindow::InputSettingsWindow() : activeObject(0) {
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
setLayout(layout);
|
||||
|
||||
title = new QLabel("Input Configuration Editor");
|
||||
title->setProperty("class", "title");
|
||||
layout->addWidget(title);
|
||||
|
||||
selection = new QHBoxLayout; {
|
||||
port = new QComboBox;
|
||||
port->addItem("Controller Port 1");
|
||||
port->addItem("Controller Port 2");
|
||||
port->addItem("User Interface");
|
||||
selection->addWidget(port);
|
||||
comboLayout = new QHBoxLayout;
|
||||
layout->addLayout(comboLayout);
|
||||
|
||||
device = new QComboBox;
|
||||
selection->addWidget(device);
|
||||
}
|
||||
selection->setSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(selection);
|
||||
layout->addSpacing(Style::WidgetSpacing);
|
||||
port = new QComboBox;
|
||||
port->addItem("Controller Port 1");
|
||||
port->addItem("Controller Port 2");
|
||||
port->addItem("User Interface");
|
||||
comboLayout->addWidget(port);
|
||||
|
||||
device = new QComboBox;
|
||||
comboLayout->addWidget(device);
|
||||
|
||||
selectionWidget = new QWidget;
|
||||
selectionWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
layout->addWidget(selectionWidget);
|
||||
|
||||
selectionLayout = new QVBoxLayout;
|
||||
selectionLayout->setMargin(0);
|
||||
selectionLayout->setSpacing(Style::WidgetSpacing);
|
||||
selectionWidget->setLayout(selectionLayout);
|
||||
|
||||
list = new QTreeWidget;
|
||||
list->setColumnCount(3);
|
||||
|
@ -28,63 +35,94 @@ InputSettingsWindow::InputSettingsWindow() {
|
|||
list->setAllColumnsShowFocus(true);
|
||||
list->setRootIsDecorated(false);
|
||||
list->hideColumn(0); //used for default sorting
|
||||
layout->addWidget(list);
|
||||
layout->addSpacing(Style::WidgetSpacing);
|
||||
selectionLayout->addWidget(list);
|
||||
|
||||
controls = new QHBoxLayout; {
|
||||
assign = new QPushButton("Assign ...");
|
||||
controls->addWidget(assign);
|
||||
selectionControlLayout = new QHBoxLayout;
|
||||
selectionLayout->addLayout(selectionControlLayout);
|
||||
|
||||
assignAll = new QPushButton("Assign All ...");
|
||||
controls->addWidget(assignAll);
|
||||
assignButton = new QPushButton("Assign");
|
||||
selectionControlLayout->addWidget(assignButton);
|
||||
|
||||
unassign = new QPushButton("Unassign");
|
||||
controls->addWidget(unassign);
|
||||
}
|
||||
controls->setSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(controls);
|
||||
assignAllButton = new QPushButton("Assign All");
|
||||
selectionControlLayout->addWidget(assignAllButton);
|
||||
|
||||
unassignButton = new QPushButton("Unassign");
|
||||
selectionControlLayout->addWidget(unassignButton);
|
||||
|
||||
unassignAllButton = new QPushButton("Unassign All");
|
||||
selectionControlLayout->addWidget(unassignAllButton);
|
||||
|
||||
assignmentWidget = new QWidget;
|
||||
assignmentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
assignmentWidget->hide();
|
||||
layout->addWidget(assignmentWidget);
|
||||
|
||||
assignmentLayout = new QVBoxLayout;
|
||||
assignmentLayout->setMargin(0);
|
||||
assignmentLayout->setSpacing(Style::WidgetSpacing);
|
||||
assignmentWidget->setLayout(assignmentLayout);
|
||||
|
||||
assignmentLabel = new QLabel;
|
||||
assignmentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
assignmentLabel->setAlignment(Qt::AlignTop);
|
||||
assignmentLabel->setFocusPolicy(Qt::StrongFocus);
|
||||
assignmentLabel->setFrameShape(QFrame::Panel);
|
||||
assignmentLabel->setFrameShadow(QFrame::Sunken);
|
||||
assignmentLayout->addWidget(assignmentLabel);
|
||||
|
||||
assignmentControlLayout = new QHBoxLayout;
|
||||
assignmentLayout->addLayout(assignmentControlLayout);
|
||||
|
||||
xaxisButton = new QPushButton("X-axis");
|
||||
assignmentControlLayout->addWidget(xaxisButton);
|
||||
|
||||
yaxisButton = new QPushButton("Y-axis");
|
||||
assignmentControlLayout->addWidget(yaxisButton);
|
||||
|
||||
spacer = new QWidget;
|
||||
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
assignmentControlLayout->addWidget(spacer);
|
||||
|
||||
helpButton = new QPushButton("Help");
|
||||
assignmentControlLayout->addWidget(helpButton);
|
||||
|
||||
cancelButton = new QPushButton("Cancel Assignment");
|
||||
assignmentControlLayout->addWidget(cancelButton);
|
||||
|
||||
connect(port, SIGNAL(currentIndexChanged(int)), this, SLOT(portChanged()));
|
||||
connect(device, SIGNAL(currentIndexChanged(int)), this, SLOT(reloadList()));
|
||||
connect(list, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(assignKey()));
|
||||
|
||||
connect(list, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(assign()));
|
||||
connect(list, SIGNAL(itemSelectionChanged()), this, SLOT(listChanged()));
|
||||
connect(assign, SIGNAL(released()), this, SLOT(assignKey()));
|
||||
connect(assignAll, SIGNAL(released()), this, SLOT(assignAllKeys()));
|
||||
connect(unassign, SIGNAL(released()), this, SLOT(unassignKey()));
|
||||
connect(assignButton, SIGNAL(released()), this, SLOT(assign()));
|
||||
connect(assignAllButton, SIGNAL(released()), this, SLOT(assignAll()));
|
||||
connect(unassignButton, SIGNAL(released()), this, SLOT(unassign()));
|
||||
connect(unassignAllButton, SIGNAL(released()), this, SLOT(unassignAll()));
|
||||
|
||||
connect(xaxisButton, SIGNAL(released()), this, SLOT(assignXaxis()));
|
||||
connect(yaxisButton, SIGNAL(released()), this, SLOT(assignYaxis()));
|
||||
connect(helpButton, SIGNAL(released()), this, SLOT(showHelp()));
|
||||
connect(cancelButton, SIGNAL(released()), this, SLOT(cancelAssignment()));
|
||||
|
||||
portChanged();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::syncUi() {
|
||||
QList<QTreeWidgetItem*> itemList = list->selectedItems();
|
||||
assign->setEnabled(itemList.count() == 1);
|
||||
//allow rapid assign for controllers from both ports, but not for UI shortcuts
|
||||
assignAll->setEnabled(port->currentIndex() < 2);
|
||||
unassign->setEnabled(itemList.count() == 1);
|
||||
assignButton->setEnabled(itemList.count() == 1);
|
||||
assignAllButton->setEnabled(port->currentIndex() < 2); //only allow for controllers, not GUI hotkeys
|
||||
unassignButton->setEnabled(itemList.count() == 1);
|
||||
}
|
||||
|
||||
//when port combobox item is changed, device list needs to be repopulated
|
||||
void InputSettingsWindow::portChanged() {
|
||||
disconnect(device, SIGNAL(currentIndexChanged(int)), this, SLOT(reloadList()));
|
||||
|
||||
device->clear();
|
||||
deviceItem.reset();
|
||||
|
||||
int index = port->currentIndex();
|
||||
if(index < 2) {
|
||||
//this is a controller port
|
||||
for(unsigned i = 0; i < inputPool.size(); i++) {
|
||||
//only add devices for selected port
|
||||
if(inputPool[i]->port == index) {
|
||||
device->addItem(inputPool[i]->name);
|
||||
deviceItem.add(inputPool[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//user interface controls
|
||||
for(unsigned i = 0; i < inputUiPool.size(); i++) {
|
||||
device->addItem(inputUiPool[i]->name);
|
||||
deviceItem.add(inputUiPool[i]);
|
||||
unsigned index = port->currentIndex();
|
||||
for(unsigned i = 0; i < mapper().size(); i++) {
|
||||
if(mapper()[i]->category == index) {
|
||||
device->addItem(mapper()[i]->label);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,17 +134,28 @@ void InputSettingsWindow::portChanged() {
|
|||
void InputSettingsWindow::reloadList() {
|
||||
list->clear();
|
||||
list->setSortingEnabled(false);
|
||||
listItem.reset();
|
||||
|
||||
int index = device->currentIndex();
|
||||
if(index < deviceItem.size()) {
|
||||
InputGroup &group = *deviceItem[index];
|
||||
for(unsigned i = 0; i < group.size(); i++) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(list);
|
||||
item->setText(0, utf8() << (int)(1000000 + i));
|
||||
item->setText(1, group[i]->name);
|
||||
item->setText(2, (const char*)group[i]->id);
|
||||
listItem.add(item);
|
||||
unsigned portIndex = port->currentIndex();
|
||||
unsigned deviceIndex = device->currentIndex();
|
||||
unsigned index = 0;
|
||||
for(unsigned i = 0; i < mapper().size(); i++) {
|
||||
if(mapper()[i]->category == portIndex) {
|
||||
if(index != deviceIndex) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
InputGroup &group = *(mapper()[i]);
|
||||
for(unsigned i = 0; i < group.size(); i++) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(list);
|
||||
item->setData(0, Qt::UserRole, QVariant(i));
|
||||
item->setText(0, string() << (1000000 + i));
|
||||
item->setText(1, group[i]->label);
|
||||
item->setText(2, group[i]->name);
|
||||
}
|
||||
|
||||
activeGroup = &group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,54 +169,248 @@ void InputSettingsWindow::listChanged() {
|
|||
syncUi();
|
||||
}
|
||||
|
||||
//InputCaptureWindow calls this after a successful key assignment change:
|
||||
//need to update list of values to show new key assignment value.
|
||||
void InputSettingsWindow::updateList() {
|
||||
int index = device->currentIndex();
|
||||
if(index < deviceItem.size()) {
|
||||
InputGroup &group = *deviceItem[index];
|
||||
//===================
|
||||
//assignment routines
|
||||
//===================
|
||||
|
||||
for(unsigned i = 0; i < listItem.size(); i++) {
|
||||
listItem[i]->setText(2, (const char*)group[i]->id);
|
||||
}
|
||||
void InputSettingsWindow::beginAssignment() {
|
||||
settingsWindow->list->setEnabled(false);
|
||||
port->setEnabled(false);
|
||||
device->setEnabled(false);
|
||||
selectionWidget->hide();
|
||||
assignmentWidget->show();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::showHelp() {
|
||||
string message;
|
||||
|
||||
message << "<b>Digital Button Assignment:</b><br>";
|
||||
message << "To assign, do any one of the following:<br>";
|
||||
message << "• press any keyboard key<br>";
|
||||
message << "• click any mouse button inside the capture box<br>";
|
||||
message << "• move any joypad hat in the desired direction<br>";
|
||||
message << "• move any joypad axis in the desired direction<br>";
|
||||
message << "• press any joypad button<br><br>";
|
||||
message << "For multi-key assignment, hold any combination of these keys down first:<br>";
|
||||
message << "• Shift, Control, Alt, Super";
|
||||
message << "<br><br>";
|
||||
|
||||
message << "<b>Analog Axis Assignment:</b><br>";
|
||||
message << "To assign, do any one of the following:<br>";
|
||||
message << "• click the desired mouse axis button<br>";
|
||||
message << "• move any joypad axis in either direction";
|
||||
|
||||
audio.clear();
|
||||
QMessageBox::information(settingsWindow, "Input Assignment Help", message);
|
||||
}
|
||||
|
||||
void InputSettingsWindow::assignObject(MappedInput *object) {
|
||||
//flush any pending events to prevent instantaneous assignment of eg mouse buttons
|
||||
activeObject = 0;
|
||||
activeMouse = 0;
|
||||
mapper().poll();
|
||||
|
||||
activeObject = object;
|
||||
|
||||
string label;
|
||||
label << "<b>" << port->currentText().toUtf8().constData() << " :: ";
|
||||
label << device->currentText().toUtf8().constData() << " :: ";
|
||||
label << activeObject->label << "</b><br>";
|
||||
|
||||
if(dynamic_cast<DigitalInput*>(activeObject)) {
|
||||
xaxisButton->setVisible(false);
|
||||
yaxisButton->setVisible(false);
|
||||
label << "<i>Digital Button Assignment</i>";
|
||||
} else if(dynamic_cast<AnalogInput*>(activeObject)) {
|
||||
xaxisButton->setVisible(true);
|
||||
yaxisButton->setVisible(true);
|
||||
label << "<i>Analog Axis Assignment</i>";
|
||||
}
|
||||
|
||||
if(dynamic_cast<Controllers::Gamepad*>(activeGroup)
|
||||
|| dynamic_cast<Controllers::Asciipad*>(activeGroup)) {
|
||||
assignmentLabel->setStyleSheet(
|
||||
"background-image: url(:/joypad.png);"
|
||||
"background-position: bottom center;"
|
||||
"background-repeat: none;"
|
||||
);
|
||||
} else {
|
||||
assignmentLabel->setStyleSheet("");
|
||||
}
|
||||
|
||||
assignmentLabel->setText(label);
|
||||
assignmentLabel->setFocus();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::endAssignment() {
|
||||
activeObject = 0;
|
||||
|
||||
if(multiAssign == false || ++multiAssignIndex >= activeGroup->size()) {
|
||||
mapper().bind();
|
||||
reloadList();
|
||||
|
||||
assignmentWidget->hide();
|
||||
selectionWidget->show();
|
||||
settingsWindow->list->setEnabled(true);
|
||||
port->setEnabled(true);
|
||||
device->setEnabled(true);
|
||||
} else {
|
||||
assignObject((*activeGroup)[multiAssignIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
void InputSettingsWindow::assignKey() {
|
||||
int index = device->currentIndex();
|
||||
if(index < deviceItem.size()) {
|
||||
InputGroup &group = *deviceItem[index];
|
||||
void InputSettingsWindow::assign() {
|
||||
if(activeObject) return;
|
||||
multiAssign = false;
|
||||
|
||||
QTreeWidgetItem *item = list->currentItem();
|
||||
if(item && item->isSelected()) {
|
||||
signed i = listItem.find(item);
|
||||
if(i >= 0) inputCaptureWindow->activate(group[i]);
|
||||
QTreeWidgetItem *item = list->currentItem();
|
||||
if(!item) return;
|
||||
unsigned index = item->data(0, Qt::UserRole).toUInt();
|
||||
|
||||
beginAssignment();
|
||||
assignObject((*activeGroup)[index]);
|
||||
}
|
||||
|
||||
void InputSettingsWindow::assignAll() {
|
||||
if(activeObject) return;
|
||||
multiAssign = true;
|
||||
|
||||
beginAssignment();
|
||||
assignObject((*activeGroup)[multiAssignIndex = 0]);
|
||||
}
|
||||
|
||||
void InputSettingsWindow::unassign() {
|
||||
QTreeWidgetItem *item = list->currentItem();
|
||||
if(!item) return;
|
||||
unsigned index = item->data(0, Qt::UserRole).toUInt();
|
||||
MappedInput *object = (*activeGroup)[index];
|
||||
object->name = "None";
|
||||
mapper().bind();
|
||||
reloadList();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::unassignAll() {
|
||||
for(unsigned i = 0; i < activeGroup->size(); i++) {
|
||||
MappedInput *object = (*activeGroup)[i];
|
||||
object->name = "None";
|
||||
}
|
||||
mapper().bind();
|
||||
reloadList();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::cancelAssignment() {
|
||||
multiAssign = false;
|
||||
endAssignment();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::setAssignment(string name) {
|
||||
if(multiAssign == true) {
|
||||
//make sure this mapping was not previously used
|
||||
for(unsigned i = 0; i < multiAssignIndex; i++) {
|
||||
if(name == (*activeGroup)[i]->name) return;
|
||||
}
|
||||
}
|
||||
|
||||
activeObject->name = name;
|
||||
endAssignment();
|
||||
}
|
||||
|
||||
void InputSettingsWindow::assignXaxis() {
|
||||
setAssignment(Scancode::encode(mouse(activeMouse).axis(0)));
|
||||
}
|
||||
|
||||
void InputSettingsWindow::assignYaxis() {
|
||||
setAssignment(Scancode::encode(mouse(activeMouse).axis(1)));
|
||||
}
|
||||
|
||||
void InputSettingsWindow::inputEvent(uint16_t scancode) {
|
||||
if(dynamic_cast<DigitalInput*>(activeObject)) {
|
||||
digitalInputEvent(scancode);
|
||||
} else if(dynamic_cast<AnalogInput*>(activeObject)) {
|
||||
analogInputEvent(scancode);
|
||||
}
|
||||
}
|
||||
|
||||
void InputSettingsWindow::assignAllKeys() {
|
||||
int index = port->currentIndex();
|
||||
if(index < 2) {
|
||||
index = device->currentIndex();
|
||||
if(index < deviceItem.size()) {
|
||||
inputCaptureWindow->activate(deviceItem[index]);
|
||||
void InputSettingsWindow::digitalInputEvent(uint16_t scancode) {
|
||||
if(!isActiveWindow() || isMinimized()) return;
|
||||
|
||||
if(Keyboard::isAnyKey(scancode) && mapper().state(scancode)) {
|
||||
for(unsigned i = 0; i < Keyboard::Count; i++) {
|
||||
//don't map escape key, as it is reserved by the user interface
|
||||
if(scancode == keyboard(i)[Keyboard::Escape]) return;
|
||||
}
|
||||
|
||||
setAssignment(string() << mapper().modifierString() << Scancode::encode(scancode));
|
||||
} else if(Mouse::isAnyButton(scancode) && mapper().state(scancode)) {
|
||||
//ensure button was clicked inside assignment label box
|
||||
QRect windowRect = settingsWindow->geometry();
|
||||
QRect splitterRect = settingsWindow->splitter->geometry();
|
||||
QRect panelRect = settingsWindow->panel->geometry();
|
||||
QRect captureRect = assignmentWidget->geometry();
|
||||
QRect widgetRect = assignmentLabel->geometry();
|
||||
unsigned wx = windowRect.x() + splitterRect.x() + panelRect.x() + captureRect.x();
|
||||
unsigned wy = windowRect.y() + splitterRect.y() + panelRect.y() + captureRect.y();
|
||||
unsigned px = QCursor::pos().x();
|
||||
unsigned py = QCursor::pos().y();
|
||||
|
||||
if(px < wx || px >= wx + widgetRect.size().width()) return;
|
||||
if(py < wy || py >= wy + widgetRect.size().height()) return;
|
||||
|
||||
setAssignment(string() << mapper().modifierString() << Scancode::encode(scancode));
|
||||
} else if(Joypad::isAnyHat(scancode)) {
|
||||
int16_t state = mapper().state(scancode);
|
||||
string position;
|
||||
if(state == Joypad::HatUp) position = ".Up";
|
||||
if(state == Joypad::HatDown) position = ".Down";
|
||||
if(state == Joypad::HatLeft) position = ".Left";
|
||||
if(state == Joypad::HatRight) position = ".Right";
|
||||
if(position == "") return;
|
||||
|
||||
setAssignment(string() << mapper().modifierString() << Scancode::encode(scancode) << position);
|
||||
} else if(Joypad::isAnyAxis(scancode) && mapper().distance(scancode) > 64) {
|
||||
if(mapper().calibrated == false) {
|
||||
MappedInput *temp = activeObject;
|
||||
activeObject = 0;
|
||||
mapper().calibrate();
|
||||
activeObject = temp;
|
||||
}
|
||||
|
||||
if(mapper().isTrigger[Joypad::numberDecode(scancode)][Joypad::axisDecode(scancode)] == false) {
|
||||
int16_t state = mapper().state(scancode);
|
||||
string position;
|
||||
if(state < -24576) position = ".Lo";
|
||||
if(state > +24576) position = ".Hi";
|
||||
if(position == "") return;
|
||||
|
||||
setAssignment(string() << mapper().modifierString() << Scancode::encode(scancode) << position);
|
||||
} else {
|
||||
int16_t state = mapper().state(scancode);
|
||||
if(state >= 0) return;
|
||||
|
||||
setAssignment(string() << mapper().modifierString() << Scancode::encode(scancode) << ".Trigger");
|
||||
}
|
||||
} else if(Joypad::isAnyButton(scancode) && mapper().state(scancode)) {
|
||||
setAssignment(string() << mapper().modifierString() << Scancode::encode(scancode));
|
||||
}
|
||||
}
|
||||
|
||||
void InputSettingsWindow::unassignKey() {
|
||||
int index = device->currentIndex();
|
||||
if(index < deviceItem.size()) {
|
||||
InputGroup &group = *deviceItem[index];
|
||||
void InputSettingsWindow::analogInputEvent(uint16_t scancode) {
|
||||
if(!isActiveWindow() || isMinimized()) return;
|
||||
|
||||
QTreeWidgetItem *item = list->currentItem();
|
||||
if(item && item->isSelected()) {
|
||||
signed i = listItem.find(item);
|
||||
if(i >= 0) {
|
||||
group[i]->id = "none";
|
||||
inputManager.bind(); //update key bindings to reflect object ID change above
|
||||
item->setText(2, (const char*)group[i]->id);
|
||||
if(Mouse::isAnyButton(scancode)) {
|
||||
activeMouse = Mouse::numberDecode(scancode);
|
||||
} else if(Joypad::isAnyAxis(scancode) && mapper().distance(scancode) > 64) {
|
||||
if(mapper().calibrated == false) {
|
||||
MappedInput *temp = activeObject;
|
||||
activeObject = 0;
|
||||
mapper().calibrate();
|
||||
activeObject = temp;
|
||||
}
|
||||
|
||||
if(mapper().isTrigger[Joypad::numberDecode(scancode)][Joypad::axisDecode(scancode)] == false) {
|
||||
int16_t state = mapper().state(scancode);
|
||||
if(state < -24576 || state > +24576) {
|
||||
setAssignment(string() << Scancode::encode(scancode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,28 +4,58 @@ class InputSettingsWindow : public QWidget {
|
|||
public:
|
||||
QVBoxLayout *layout;
|
||||
QLabel *title;
|
||||
QHBoxLayout *selection;
|
||||
QHBoxLayout *comboLayout;
|
||||
QComboBox *port;
|
||||
QComboBox *device;
|
||||
QTreeWidget *list;
|
||||
QHBoxLayout *controls;
|
||||
QPushButton *assign;
|
||||
QPushButton *assignAll;
|
||||
QPushButton *unassign;
|
||||
|
||||
QWidget *selectionWidget;
|
||||
QVBoxLayout *selectionLayout;
|
||||
QTreeWidget *list;
|
||||
QHBoxLayout *selectionControlLayout;
|
||||
QPushButton *assignButton;
|
||||
QPushButton *assignAllButton;
|
||||
QPushButton *unassignButton;
|
||||
QPushButton *unassignAllButton;
|
||||
|
||||
QWidget *assignmentWidget;
|
||||
QVBoxLayout *assignmentLayout;
|
||||
QLabel *assignmentLabel;
|
||||
QHBoxLayout *assignmentControlLayout;
|
||||
QPushButton *xaxisButton;
|
||||
QPushButton *yaxisButton;
|
||||
QWidget *spacer;
|
||||
QPushButton *helpButton;
|
||||
QPushButton *cancelButton;
|
||||
|
||||
void inputEvent(uint16_t scancode);
|
||||
void syncUi();
|
||||
InputSettingsWindow();
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void portChanged();
|
||||
void reloadList();
|
||||
void listChanged();
|
||||
void updateList();
|
||||
void assignKey();
|
||||
void assignAllKeys();
|
||||
void unassignKey();
|
||||
void assign();
|
||||
void assignAll();
|
||||
void unassign();
|
||||
void unassignAll();
|
||||
void assignXaxis();
|
||||
void assignYaxis();
|
||||
void showHelp();
|
||||
void cancelAssignment();
|
||||
|
||||
private:
|
||||
array<InputGroup*> deviceItem;
|
||||
array<QTreeWidgetItem*> listItem;
|
||||
InputGroup *activeGroup;
|
||||
MappedInput *activeObject;
|
||||
unsigned activeMouse;
|
||||
bool multiAssign;
|
||||
unsigned multiAssignIndex;
|
||||
|
||||
void setAssignment(string name);
|
||||
void digitalInputEvent(uint16_t scancode);
|
||||
void analogInputEvent(uint16_t scancode);
|
||||
|
||||
void beginAssignment();
|
||||
void assignObject(MappedInput *object);
|
||||
void endAssignment();
|
||||
} *inputSettingsWindow;
|
||||
|
|
|
@ -31,7 +31,7 @@ PathSettingWidget::PathSettingWidget(string &pathValue_, const char *labelText,
|
|||
updatePath();
|
||||
}
|
||||
|
||||
void PathSettingWidget::selectPath(const string &newPath) {
|
||||
void PathSettingWidget::assignPath(string newPath) {
|
||||
pathValue = string() << newPath << "/";
|
||||
updatePath();
|
||||
}
|
||||
|
@ -39,15 +39,19 @@ void PathSettingWidget::selectPath(const string &newPath) {
|
|||
void PathSettingWidget::updatePath() {
|
||||
if(pathValue == "") {
|
||||
path->setStyleSheet("color: #808080");
|
||||
path->setText(utf8() << pathDefaultLabel);
|
||||
path->setText(pathDefaultLabel);
|
||||
} else {
|
||||
path->setStyleSheet("color: #000000");
|
||||
path->setText(utf8() << pathValue);
|
||||
path->setText(pathValue);
|
||||
}
|
||||
}
|
||||
|
||||
void PathSettingWidget::selectPath() {
|
||||
diskBrowser->chooseFolder(this, pathBrowseLabel);
|
||||
diskBrowser->chooseFolder(
|
||||
bind(&PathSettingWidget::assignPath, this),
|
||||
config().path.current.folder,
|
||||
pathBrowseLabel
|
||||
);
|
||||
}
|
||||
|
||||
void PathSettingWidget::defaultPath() {
|
||||
|
@ -66,12 +70,12 @@ PathSettingsWindow::PathSettingsWindow() {
|
|||
title->setProperty("class", "title");
|
||||
layout->addWidget(title);
|
||||
|
||||
gamePath = new PathSettingWidget(config.path.rom, "Games:", "Startup path", "Default Game Path");
|
||||
savePath = new PathSettingWidget(config.path.save, "Save RAM:", "Same as loaded game", "Default Save RAM Path");
|
||||
statePath = new PathSettingWidget(config.path.state, "Save states:", "Same as loaded game", "Default Save State Path");
|
||||
patchPath = new PathSettingWidget(config.path.patch, "UPS patches:", "Same as loaded game", "Default UPS Patch Path");
|
||||
cheatPath = new PathSettingWidget(config.path.cheat, "Cheat codes:", "Same as loaded game", "Default Cheat Code Path");
|
||||
dataPath = new PathSettingWidget(config.path.data, "Exported data:", "Same as loaded game", "Default Exported Data Path");
|
||||
gamePath = new PathSettingWidget(config().path.rom, "Games:", "Remember last path", "Default Game Path");
|
||||
savePath = new PathSettingWidget(config().path.save, "Save RAM:", "Same as loaded game", "Default Save RAM Path");
|
||||
statePath = new PathSettingWidget(config().path.state, "Save states:", "Same as loaded game", "Default Save State Path");
|
||||
patchPath = new PathSettingWidget(config().path.patch, "UPS patches:", "Same as loaded game", "Default UPS Patch Path");
|
||||
cheatPath = new PathSettingWidget(config().path.cheat, "Cheat codes:", "Same as loaded game", "Default Cheat Code Path");
|
||||
dataPath = new PathSettingWidget(config().path.data, "Exported data:", "Same as loaded game", "Default Exported Data Path");
|
||||
|
||||
layout->addWidget(gamePath);
|
||||
layout->addWidget(savePath);
|
||||
|
|
|
@ -12,8 +12,9 @@ public:
|
|||
string &pathValue;
|
||||
string pathDefaultLabel;
|
||||
string pathBrowseLabel;
|
||||
void selectPath(const string&);
|
||||
void assignPath(string);
|
||||
void updatePath();
|
||||
|
||||
PathSettingWidget(string&, const char*, const char*, const char*);
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
PixelShaderWindow::PixelShaderWindow() {
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
title = new QLabel("Pixel Shader Selection");
|
||||
title->setProperty("class", "title");
|
||||
layout->addWidget(title);
|
||||
|
||||
gridLayout = new QGridLayout;
|
||||
gridLayout->setHorizontalSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(gridLayout);
|
||||
|
||||
fragmentLabel = new QLabel("Fragment shader:");
|
||||
gridLayout->addWidget(fragmentLabel, 0, 0, 1, 3);
|
||||
|
||||
fragmentPath = new QLineEdit;
|
||||
gridLayout->addWidget(fragmentPath, 1, 0);
|
||||
|
||||
fragmentSelect = new QPushButton("Select ...");
|
||||
gridLayout->addWidget(fragmentSelect, 1, 1);
|
||||
|
||||
fragmentDefault = new QPushButton("Default");
|
||||
gridLayout->addWidget(fragmentDefault, 1, 2);
|
||||
|
||||
vertexLabel = new QLabel("Vertex shader:");
|
||||
gridLayout->addWidget(vertexLabel, 2, 0, 1, 3);
|
||||
|
||||
vertexPath = new QLineEdit;
|
||||
gridLayout->addWidget(vertexPath, 3, 0);
|
||||
|
||||
vertexSelect = new QPushButton("Select ...");
|
||||
gridLayout->addWidget(vertexSelect, 3, 1);
|
||||
|
||||
vertexDefault = new QPushButton("Default");
|
||||
gridLayout->addWidget(vertexDefault, 3, 2);
|
||||
|
||||
synchronize();
|
||||
|
||||
connect(fragmentSelect, SIGNAL(released()), this, SLOT(selectFragmentShader()));
|
||||
connect(vertexSelect, SIGNAL(released()), this, SLOT(selectVertexShader()));
|
||||
connect(fragmentDefault, SIGNAL(released()), this, SLOT(defaultFragmentShader()));
|
||||
connect(vertexDefault, SIGNAL(released()), this, SLOT(defaultVertexShader()));
|
||||
}
|
||||
|
||||
void PixelShaderWindow::synchronize() {
|
||||
fragmentPath->setText(config().path.fragmentShader);
|
||||
vertexPath->setText(config().path.vertexShader);
|
||||
}
|
||||
|
||||
void PixelShaderWindow::selectFragmentShader() {
|
||||
diskBrowser->chooseFile(
|
||||
bind(&PixelShaderWindow::assignFragmentShader, this),
|
||||
config().path.current.shader,
|
||||
"Select Fragment Shader"
|
||||
);
|
||||
}
|
||||
|
||||
void PixelShaderWindow::selectVertexShader() {
|
||||
diskBrowser->chooseFile(
|
||||
bind(&PixelShaderWindow::assignVertexShader, this),
|
||||
config().path.current.shader,
|
||||
"Select Vertex Shader"
|
||||
);
|
||||
}
|
||||
|
||||
void PixelShaderWindow::defaultFragmentShader() { assignFragmentShader(""); }
|
||||
void PixelShaderWindow::defaultVertexShader() { assignVertexShader(""); }
|
||||
|
||||
void PixelShaderWindow::assignFragmentShader(string filename) {
|
||||
config().path.fragmentShader = filename;
|
||||
synchronize();
|
||||
utility.updatePixelShader();
|
||||
}
|
||||
|
||||
void PixelShaderWindow::assignVertexShader(string filename) {
|
||||
config().path.vertexShader = filename;
|
||||
synchronize();
|
||||
utility.updatePixelShader();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
class PixelShaderWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QVBoxLayout *layout;
|
||||
QLabel *title;
|
||||
QGridLayout *gridLayout;
|
||||
QLabel *fragmentLabel;
|
||||
QLineEdit *fragmentPath;
|
||||
QPushButton *fragmentSelect;
|
||||
QPushButton *fragmentDefault;
|
||||
QLabel *vertexLabel;
|
||||
QLineEdit *vertexPath;
|
||||
QPushButton *vertexSelect;
|
||||
QPushButton *vertexDefault;
|
||||
|
||||
void synchronize();
|
||||
PixelShaderWindow();
|
||||
|
||||
public slots:
|
||||
void selectFragmentShader();
|
||||
void selectVertexShader();
|
||||
void defaultFragmentShader();
|
||||
void defaultVertexShader();
|
||||
|
||||
void assignFragmentShader(string);
|
||||
void assignVertexShader(string);
|
||||
} *pixelShaderWindow;
|
|
@ -1,11 +1,11 @@
|
|||
#include "video.cpp"
|
||||
#include "pixelshader.cpp"
|
||||
#include "audio.cpp"
|
||||
#include "input.cpp"
|
||||
#include "paths.cpp"
|
||||
#include "advanced.cpp"
|
||||
#include "utility/inputcapture.cpp"
|
||||
|
||||
SettingsWindow::SettingsWindow() : QbWindow(config.geometry.settingsWindow) {
|
||||
SettingsWindow::SettingsWindow() : QbWindow(config().geometry.settingsWindow) {
|
||||
setObjectName("settings-window");
|
||||
setWindowTitle("Configuration Settings");
|
||||
resize(625, 360);
|
||||
|
@ -18,14 +18,20 @@ SettingsWindow::SettingsWindow() : QbWindow(config.geometry.settingsWindow) {
|
|||
splitter = new QSplitter;
|
||||
layout->addWidget(splitter);
|
||||
|
||||
video = new QTreeWidgetItem(QStringList() << "Video");
|
||||
audio = new QTreeWidgetItem(QStringList() << "Audio");
|
||||
input = new QTreeWidgetItem(QStringList() << "Input");
|
||||
paths = new QTreeWidgetItem(QStringList() << "Paths");
|
||||
advanced = new QTreeWidgetItem(QStringList() << "Advanced");
|
||||
|
||||
//use QTreeWidget instead of QListWidget, as only the former has setAllColumnsShowFocus()
|
||||
//this is needed to have the dotted-selection rectangle encompass the icons
|
||||
list = new QTreeWidget;
|
||||
list->addTopLevelItem(video = new QTreeWidgetItem(QStringList() << "Video"));
|
||||
list->addTopLevelItem(audio = new QTreeWidgetItem(QStringList() << "Audio"));
|
||||
list->addTopLevelItem(input = new QTreeWidgetItem(QStringList() << "Input"));
|
||||
list->addTopLevelItem(paths = new QTreeWidgetItem(QStringList() << "Paths"));
|
||||
list->addTopLevelItem(advanced = new QTreeWidgetItem(QStringList() << "Advanced"));
|
||||
list->addTopLevelItem(video);
|
||||
list->addTopLevelItem(audio);
|
||||
list->addTopLevelItem(input);
|
||||
list->addTopLevelItem(paths);
|
||||
list->addTopLevelItem(advanced);
|
||||
list->setCurrentItem(input); //select most frequently used panel by default
|
||||
list->setHeaderHidden(true);
|
||||
list->setRootIsDecorated(false);
|
||||
|
@ -52,8 +58,6 @@ SettingsWindow::SettingsWindow() : QbWindow(config.geometry.settingsWindow) {
|
|||
pathSettingsWindow = new PathSettingsWindow;
|
||||
advancedSettingsWindow = new AdvancedSettingsWindow;
|
||||
|
||||
inputCaptureWindow = new InputCaptureWindow;
|
||||
|
||||
panelLayout = new QStackedLayout(panel);
|
||||
panelLayout->addWidget(videoSettingsWindow);
|
||||
panelLayout->addWidget(audioSettingsWindow);
|
||||
|
@ -70,9 +74,9 @@ SettingsWindow::SettingsWindow() : QbWindow(config.geometry.settingsWindow) {
|
|||
void SettingsWindow::itemChanged() {
|
||||
QTreeWidgetItem *item = list->currentItem();
|
||||
|
||||
if(item == video) panelLayout->setCurrentWidget(videoSettingsWindow);
|
||||
if(item == audio) panelLayout->setCurrentWidget(audioSettingsWindow);
|
||||
if(item == input) panelLayout->setCurrentWidget(inputSettingsWindow);
|
||||
if(item == paths) panelLayout->setCurrentWidget(pathSettingsWindow);
|
||||
if(item == video) panelLayout->setCurrentWidget(videoSettingsWindow);
|
||||
if(item == audio) panelLayout->setCurrentWidget(audioSettingsWindow);
|
||||
if(item == input) panelLayout->setCurrentWidget(inputSettingsWindow);
|
||||
if(item == paths) panelLayout->setCurrentWidget(pathSettingsWindow);
|
||||
if(item == advanced) panelLayout->setCurrentWidget(advancedSettingsWindow);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "video.moc"
|
||||
#include "pixelshader.moc"
|
||||
#include "audio.moc"
|
||||
#include "input.moc"
|
||||
#include "paths.moc"
|
||||
#include "advanced.moc"
|
||||
#include "utility/inputcapture.moc"
|
||||
|
||||
class SettingsWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -1,451 +0,0 @@
|
|||
InputCaptureWindow::InputCaptureWindow() : QbWindow(config.geometry.inputCaptureWindow) {
|
||||
activeObject = 0;
|
||||
activeGroup = 0;
|
||||
groupIndex = 0;
|
||||
inputLock = false;
|
||||
|
||||
setObjectName("input-capture-window");
|
||||
setWindowTitle("Input Capture");
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
hlayout = new QHBoxLayout;
|
||||
hlayout->setSpacing(Style::WidgetSpacing); {
|
||||
title = new QLabel;
|
||||
hlayout->addWidget(title, 0, Qt::AlignTop);
|
||||
|
||||
mouseAxes = new QPushButton(" Assign Mouse Axis ");
|
||||
mouseAxes->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
hlayout->addWidget(mouseAxes, 0, Qt::AlignTop);
|
||||
|
||||
mouseButtons = new QPushButton(" Assign Mouse Button ");
|
||||
mouseButtons->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
hlayout->addWidget(mouseButtons, 0, Qt::AlignTop);
|
||||
}
|
||||
layout->addLayout(hlayout);
|
||||
|
||||
imageSpacer = new QWidget;
|
||||
imageSpacer->setFixedSize(Style::WidgetSpacing, Style::WidgetSpacing);
|
||||
layout->addWidget(imageSpacer);
|
||||
|
||||
imageWidget = new ImageWidget;
|
||||
layout->addWidget(imageWidget, 0, Qt::AlignHCenter);
|
||||
|
||||
connect(mouseAxes, SIGNAL(released()), this, SLOT(assignMouseAxis()));
|
||||
connect(mouseButtons, SIGNAL(released()), this, SLOT(assignMouseButton()));
|
||||
|
||||
inputMouseCaptureWindow = new InputMouseCaptureWindow;
|
||||
inputCalibrationWindow = new InputCalibrationWindow;
|
||||
}
|
||||
|
||||
void InputCaptureWindow::activate(InputObject *object) {
|
||||
if(!activeGroup) hide();
|
||||
|
||||
utf8 info;
|
||||
info << "<b>ID:</b> ";
|
||||
if(object->parent) {
|
||||
InputDevice *device = dynamic_cast<InputDevice*>(object->parent);
|
||||
if(device) info << "Controller port " << (int)(device->port + 1) << " <b>::</b> ";
|
||||
else info << "User interface <b>::</b> ";
|
||||
info << object->parent->name << " <b>::</b> ";
|
||||
}
|
||||
info << object->name << "<br>";
|
||||
|
||||
activeObject = object;
|
||||
if(activeObject->type == InputObject::Button) {
|
||||
mouseAxes->hide();
|
||||
mouseButtons->show();
|
||||
|
||||
info << "Press any key or button to assign to this ID.";
|
||||
} else /*(activeObject->type == InputObject::Axis)*/ {
|
||||
mouseAxes->show();
|
||||
mouseButtons->hide();
|
||||
|
||||
info << "Move any axis to assign to this ID.";
|
||||
}
|
||||
|
||||
if(dynamic_cast<Joypad*>(activeObject->parent)) {
|
||||
imageSpacer->show();
|
||||
imageWidget->setFixedSize(480, 210);
|
||||
imageWidget->show();
|
||||
} else {
|
||||
imageSpacer->hide();
|
||||
imageWidget->hide();
|
||||
}
|
||||
|
||||
title->setText(info);
|
||||
show();
|
||||
shrink();
|
||||
}
|
||||
|
||||
void InputCaptureWindow::activate(InputGroup *group) {
|
||||
activeGroup = group;
|
||||
groupIndex = 0;
|
||||
hide();
|
||||
activate((*activeGroup)[groupIndex]);
|
||||
}
|
||||
|
||||
void InputCaptureWindow::inputEvent(uint16_t code, bool forceAssign /* = false */) {
|
||||
if(!activeObject || inputLock == true) return;
|
||||
|
||||
//input polling is global, need to block mouse actions that may be UI interactions.
|
||||
//custom controls on window allow mouse assignment instead.
|
||||
if(forceAssign == false) {
|
||||
if(inputMouseCaptureWindow->isActiveWindow()) {
|
||||
inputMouseCaptureWindow->inputEvent(code);
|
||||
return;
|
||||
}
|
||||
if(!isActiveWindow()) return;
|
||||
|
||||
//get as much info as possible about this code
|
||||
InputCode::type_t type = InputCode::type(code);
|
||||
InputCode::axistype_t axisType = InputCode::axisType(code);
|
||||
int joypadNumber = InputCode::joypadNumber(code);
|
||||
int16_t state = inputManager.state(code);
|
||||
unsigned distance = abs(state - inputManager.lastState(code));
|
||||
|
||||
if(type == InputCode::JoypadHat) {
|
||||
//hats can be in any of nine clock-wise states (4x direct, 4x angled and centered.)
|
||||
//only map when hat is moved to an explicit direction.
|
||||
if(state != joypad<>::hat_up && state != joypad<>::hat_down
|
||||
&& state != joypad<>::hat_left && state != joypad<>::hat_right) return;
|
||||
}
|
||||
|
||||
if(type == InputCode::JoypadAxis) {
|
||||
//require a degree of resistance to prevent accidental mapping
|
||||
if(axisType == InputCode::Stick) {
|
||||
//require axis to be pressed almost completely toward a specific direction
|
||||
if(state > -28672 && state < +28672) return;
|
||||
} else if(axisType == InputCode::Trigger) {
|
||||
//require trigger to be at least 75% pressed down
|
||||
if(state > -16384) return;
|
||||
} else {
|
||||
//invalid axis type: most likely the controller has yet to be calibrated
|
||||
if(joypadNumber < 0) return; //should never occur
|
||||
|
||||
//some analog triggers report phantom motion even when user does not touch gamepad
|
||||
if(distance < 64) return; //require some degree of force to trigger calibration
|
||||
if(state > -8192 && state < +8192) return; //ignore center motion
|
||||
|
||||
if(inputManager.calibrated(joypadNumber) == false) {
|
||||
inputCalibrationWindow->activate(joypadNumber);
|
||||
}
|
||||
|
||||
//block assignment until controller is fully calibrated
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(activeObject->type == InputObject::Axis) {
|
||||
if(type == InputCode::KeyboardButton
|
||||
|| type == InputCode::MouseAxis
|
||||
|| type == InputCode::MouseButton
|
||||
|| type == InputCode::JoypadHat
|
||||
|| type == InputCode::JoypadButton
|
||||
) return;
|
||||
|
||||
//uni-directional trigger cannot map to bi-directional axis
|
||||
if(type == InputCode::JoypadAxis && axisType == InputCode::Trigger) return;
|
||||
}
|
||||
|
||||
if(activeObject->type == InputObject::Button) {
|
||||
if(type == InputCode::MouseAxis
|
||||
|| type == InputCode::MouseButton
|
||||
) return;
|
||||
|
||||
//only capture on button press, not release
|
||||
if(type != InputCode::JoypadAxis && state == false) return;
|
||||
}
|
||||
|
||||
//if assigning a complete controller set, ensure requested key has not been assigned
|
||||
//to a previous entry in the group already. this prevents slow motion of joypad axes
|
||||
//from assigning the same value to multiple entries in rapid succession.
|
||||
if(activeGroup && groupIndex > 0) {
|
||||
for(unsigned i = 0; i < groupIndex; i++) {
|
||||
if(code == (*activeGroup)[i]->code) {
|
||||
//joypad hats and axes have multiple states, and are differentiated by modifier.
|
||||
//allow mapping only if requested modifier is unique.
|
||||
if(type == InputCode::JoypadHat) {
|
||||
if(state == joypad<>::hat_up && (*activeGroup)[i]->modifier == InputObject::Up ) return;
|
||||
if(state == joypad<>::hat_down && (*activeGroup)[i]->modifier == InputObject::Down ) return;
|
||||
if(state == joypad<>::hat_left && (*activeGroup)[i]->modifier == InputObject::Left ) return;
|
||||
if(state == joypad<>::hat_right && (*activeGroup)[i]->modifier == InputObject::Right) return;
|
||||
} else if(type == InputCode::JoypadAxis) {
|
||||
if(axisType == InputCode::Stick) {
|
||||
if(state < 0 && (*activeGroup)[i]->modifier == InputObject::Lo) return;
|
||||
if(state >= 0 && (*activeGroup)[i]->modifier == InputObject::Hi) return;
|
||||
} else if(axisType == InputCode::Trigger) {
|
||||
if((*activeGroup)[i]->modifier == InputObject::Trigger) return;
|
||||
}
|
||||
} else {
|
||||
//this code has already been used, do not map it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//bind code and update GUI input assignment list
|
||||
activeObject->bind(code);
|
||||
inputSettingsWindow->updateList();
|
||||
activeObject = 0;
|
||||
|
||||
//ignore multiple simultaneous state changes.
|
||||
//this helps with joypads that only activate
|
||||
//analog inputs after the first button press.
|
||||
inputLock = true;
|
||||
for(unsigned i = 0; i < 2; i++) inputManager.refresh();
|
||||
inputLock = false;
|
||||
|
||||
if(!activeGroup) {
|
||||
hide();
|
||||
inputMouseCaptureWindow->hide();
|
||||
} else {
|
||||
//try and map the next code in this input group
|
||||
groupIndex++;
|
||||
if(groupIndex < activeGroup->size()) {
|
||||
activate((*activeGroup)[groupIndex]);
|
||||
} else {
|
||||
//all group codes mapped
|
||||
hide();
|
||||
inputMouseCaptureWindow->hide();
|
||||
activeGroup = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputCaptureWindow::closeEvent(QCloseEvent *event) {
|
||||
QbWindow::closeEvent(event);
|
||||
|
||||
//window closed by user, cancel key assignment
|
||||
activeObject = 0;
|
||||
activeGroup = 0;
|
||||
|
||||
inputMouseCaptureWindow->hide();
|
||||
inputCalibrationWindow->dismiss();
|
||||
}
|
||||
|
||||
void InputCaptureWindow::assignMouseAxis() {
|
||||
//refresh input state so that mouse release event (from SIGNAL(released())
|
||||
//is not sent immediately after window is visible.
|
||||
inputManager.refresh();
|
||||
inputMouseCaptureWindow->activate(InputMouseCaptureWindow::AxisMode);
|
||||
}
|
||||
|
||||
void InputCaptureWindow::assignMouseButton() {
|
||||
inputManager.refresh();
|
||||
inputMouseCaptureWindow->activate(InputMouseCaptureWindow::ButtonMode);
|
||||
}
|
||||
|
||||
void InputCaptureWindow::ImageWidget::paintEvent(QPaintEvent*) {
|
||||
//currently, there is only an image available for the joypad.
|
||||
//in the future, this routine should determine which type of
|
||||
//image to draw via activeObject->parent's derived class type.
|
||||
QPainter painter(this);
|
||||
QPixmap pixmap(":/joypad.png");
|
||||
painter.drawPixmap(0, 0, pixmap);
|
||||
}
|
||||
|
||||
//=======================
|
||||
//InputMouseCaptureWindow
|
||||
//=======================
|
||||
|
||||
InputMouseCaptureWindow::InputMouseCaptureWindow() : QbWindow(config.geometry.inputMouseCaptureWindow) {
|
||||
setObjectName("input-mouse-capture-window");
|
||||
setWindowTitle("Mouse Input Capture");
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
info = new QLabel;
|
||||
layout->addWidget(info);
|
||||
layout->addSpacing(Style::WidgetSpacing);
|
||||
|
||||
captureBox = new QLabel("[ capture box ]");
|
||||
captureBox->setObjectName("mouse-capture-box");
|
||||
captureBox->setAlignment(Qt::AlignCenter);
|
||||
captureBox->setFixedHeight(120);
|
||||
layout->addWidget(captureBox);
|
||||
|
||||
buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->setSpacing(Style::WidgetSpacing);
|
||||
buttonLayout->setAlignment(Qt::AlignRight);
|
||||
layout->addLayout(buttonLayout);
|
||||
|
||||
xAxis = new QPushButton("X-axis");
|
||||
buttonLayout->addWidget(xAxis);
|
||||
|
||||
yAxis = new QPushButton("Y-axis");
|
||||
buttonLayout->addWidget(yAxis);
|
||||
|
||||
connect(xAxis, SIGNAL(released()), this, SLOT(assignAxisX()));
|
||||
connect(yAxis, SIGNAL(released()), this, SLOT(assignAxisY()));
|
||||
}
|
||||
|
||||
void InputMouseCaptureWindow::activate(InputMouseCaptureWindow::Mode mode_) {
|
||||
hide();
|
||||
activeMode = mode_;
|
||||
|
||||
if(activeMode == AxisMode) {
|
||||
captureBox->hide();
|
||||
xAxis->show();
|
||||
yAxis->show();
|
||||
|
||||
info->setText(utf8()
|
||||
<< "To assign a mouse axis to this ID, please click the desired axis button<br>"
|
||||
<< "below, using the mouse that you want the axis to be assigned to."
|
||||
);
|
||||
|
||||
activeMouse = -1;
|
||||
} else /*(activeMode == ButtonMode) */ {
|
||||
captureBox->show();
|
||||
xAxis->hide();
|
||||
yAxis->hide();
|
||||
|
||||
info->setText(utf8()
|
||||
<< "To assign a mouse button to this ID, please place the mouse you wish to map<br>"
|
||||
<< "over the capture box below, and then click any mouse button to set assignment."
|
||||
);
|
||||
}
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
//this is only called when isActiveWindow() == true
|
||||
void InputMouseCaptureWindow::inputEvent(uint16_t code) {
|
||||
InputCode::type_t type = InputCode::type(code);
|
||||
int16_t state = inputManager.state(code);
|
||||
|
||||
if(activeMode == AxisMode) {
|
||||
//when pressing down mouse button (eg to select "X-axis" or "Y-axis"),
|
||||
//record mouse index for later assignment
|
||||
if(type == InputCode::MouseButton && state == true) {
|
||||
activeMouse = InputCode::mouseNumber(code);
|
||||
return;
|
||||
}
|
||||
} else if(activeMode == ButtonMode) {
|
||||
//if this is a mouse button that is being released ...
|
||||
if(type == InputCode::MouseButton && state == false) {
|
||||
//ensure button was clicked inside active capture box
|
||||
QRect windowRect = geometry();
|
||||
QRect widgetRect = captureBox->geometry();
|
||||
unsigned wx = windowRect.left() + widgetRect.left();
|
||||
unsigned wy = windowRect.top() + widgetRect.top();
|
||||
unsigned px = QCursor::pos().x();
|
||||
unsigned py = QCursor::pos().y();
|
||||
|
||||
if(px < wx || px >= wx + widgetRect.size().width() ) return;
|
||||
if(py < wy || py >= wy + widgetRect.size().height()) return;
|
||||
|
||||
inputCaptureWindow->inputEvent(code, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputMouseCaptureWindow::assignAxisX() {
|
||||
if(activeMouse >= 0) {
|
||||
inputCaptureWindow->inputEvent(mouse<>::index(activeMouse, mouse<>::x), true);
|
||||
}
|
||||
}
|
||||
|
||||
void InputMouseCaptureWindow::assignAxisY() {
|
||||
if(activeMouse >= 0) {
|
||||
inputCaptureWindow->inputEvent(mouse<>::index(activeMouse, mouse<>::y), true);
|
||||
}
|
||||
}
|
||||
|
||||
//====================
|
||||
//InputCalibrateWindow
|
||||
//====================
|
||||
|
||||
//background:
|
||||
//===========
|
||||
//HID devices work by sending device state *changes* only. what this means is that when an application is started,
|
||||
//it does not know the current state of said device. the keyboard and mouse are exceptions, as the OS globally
|
||||
//tracks their states. but this does apply to joypads. once a button is pressed, or an axis is moved, the entire
|
||||
//joypad state will be sent in a message, that APIs such as DirectInput and SDL will buffer.
|
||||
//
|
||||
//to complicate matters, recent joypads have added pressure-sensitive buttons (triggers), in addition to the
|
||||
//existing analog sticks. but this functionality was not extended to the USB HID state or to various platform
|
||||
//input APIs. instead, they are treated exactly like axes.
|
||||
//
|
||||
//however, an application needs to treat these two input types distinctly:
|
||||
//a stick is a bi-directional input. the stick starts off centered, and can be moved left or right, or up or down.
|
||||
//a trigger is a uni-directional input. it can only be pushed down.
|
||||
//
|
||||
//a stick's default, unpressed state is centered (0), whereas a trigger's default state is fully depressed (+32767.)
|
||||
//but because the default state is not available until the user presses a button on a joypad, it is not possible to
|
||||
//calibrate a joypad on startup. all axes will report a value of 0, even if buttons are depressed.
|
||||
//
|
||||
//thusly, this class is needed. it will spawn a window upon the first attempt to map a joypad axis after startup.
|
||||
//by the point this window appears, an axis must have been moved, so the joypad state is now valid. but since it's
|
||||
//not possible to tell which button was pressed or which axis was moved, it's possible the axis that we're trying to
|
||||
//map was moved. so querying its state now might result in improper mapping. so instead, this window is shown, and
|
||||
//the user is asked not to press any buttons or move any axes. after hitting okay to confirm the joypad is idle,
|
||||
//the joypad can finally be calibrated properly.
|
||||
//
|
||||
//upon assignment, the calibration data is appended to the input assignment value (eg "joypad00.axis00::trigger"),
|
||||
//so that calibration is not necessary every time the emulator is run -- only when modifying input mapping on an axis.
|
||||
|
||||
void InputCalibrationWindow::activate(unsigned joy) {
|
||||
//do not override an already active calibration window
|
||||
if(isVisible()) return;
|
||||
|
||||
activeJoypad = joy;
|
||||
info->setText(utf8()
|
||||
<< "Joypad #" << joy << " needs to be calibrated before it can be mapped. "
|
||||
<< "Please ensure<br>that no buttons are pressed, "
|
||||
<< "and all axes are centered before pressing ok."
|
||||
);
|
||||
|
||||
show();
|
||||
ok->setFocus();
|
||||
}
|
||||
|
||||
InputCalibrationWindow::InputCalibrationWindow() : QbWindow(config.geometry.inputCalibrationWindow) {
|
||||
activeJoypad = -1;
|
||||
|
||||
setObjectName("input-calibrate-window");
|
||||
setWindowTitle("Joypad Calibration");
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(Style::WindowMargin);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
info = new QLabel;
|
||||
layout->addWidget(info);
|
||||
layout->addSpacing(Style::WidgetSpacing);
|
||||
|
||||
controlLayout = new QHBoxLayout;
|
||||
controlLayout->setAlignment(Qt::AlignRight);
|
||||
layout->addLayout(controlLayout);
|
||||
|
||||
ok = new QPushButton("Ok");
|
||||
controlLayout->addWidget(ok);
|
||||
|
||||
connect(ok, SIGNAL(released()), this, SLOT(dismiss()));
|
||||
}
|
||||
|
||||
void InputCalibrationWindow::dismiss() {
|
||||
hide();
|
||||
if(activeJoypad != -1) {
|
||||
inputManager.calibrate(activeJoypad);
|
||||
activeJoypad = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void InputCalibrationWindow::closeEvent(QCloseEvent *event) {
|
||||
QbWindow::closeEvent(event);
|
||||
dismiss();
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
class InputCaptureWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QVBoxLayout *layout;
|
||||
QHBoxLayout *hlayout;
|
||||
QLabel *title;
|
||||
QPushButton *mouseAxes;
|
||||
QPushButton *mouseButtons;
|
||||
QWidget *imageSpacer;
|
||||
struct ImageWidget : public QWidget {
|
||||
void paintEvent(QPaintEvent*);
|
||||
} *imageWidget;
|
||||
|
||||
void activate(InputObject *object);
|
||||
void activate(InputGroup *group);
|
||||
void inputEvent(uint16_t code, bool forceAssign = false);
|
||||
void closeEvent(QCloseEvent*);
|
||||
InputCaptureWindow();
|
||||
|
||||
public slots:
|
||||
void assignMouseAxis();
|
||||
void assignMouseButton();
|
||||
|
||||
private:
|
||||
InputObject *activeObject;
|
||||
InputGroup *activeGroup;
|
||||
unsigned groupIndex;
|
||||
bool inputLock;
|
||||
} *inputCaptureWindow;
|
||||
|
||||
class InputMouseCaptureWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Mode { AxisMode, ButtonMode };
|
||||
|
||||
QVBoxLayout *layout;
|
||||
QLabel *info;
|
||||
QLabel *captureBox;
|
||||
QHBoxLayout *buttonLayout;
|
||||
QPushButton *xAxis;
|
||||
QPushButton *yAxis;
|
||||
|
||||
void activate(Mode);
|
||||
void inputEvent(uint16_t code);
|
||||
InputMouseCaptureWindow();
|
||||
|
||||
public slots:
|
||||
void assignAxisX();
|
||||
void assignAxisY();
|
||||
|
||||
private:
|
||||
Mode activeMode;
|
||||
signed activeMouse;
|
||||
} *inputMouseCaptureWindow;
|
||||
|
||||
class InputCalibrationWindow : public QbWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QVBoxLayout *layout;
|
||||
QLabel *info;
|
||||
QHBoxLayout *controlLayout;
|
||||
QPushButton *ok;
|
||||
|
||||
void activate(unsigned joy);
|
||||
void closeEvent(QCloseEvent*);
|
||||
InputCalibrationWindow();
|
||||
|
||||
public slots:
|
||||
void dismiss();
|
||||
|
||||
private:
|
||||
int activeJoypad;
|
||||
} *inputCalibrationWindow;
|
|
@ -10,29 +10,55 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
|||
layout->addWidget(title);
|
||||
|
||||
sliders = new QGridLayout; {
|
||||
lcontrast = new QLabel("Contrast adjust: +100%");
|
||||
sliders->addWidget(lcontrast, 0, 0);
|
||||
contrastLabel = new QLabel("Contrast adjust:");
|
||||
sliders->addWidget(contrastLabel, 0, 0);
|
||||
|
||||
contrastValue = new QLabel;
|
||||
contrastValue->setAlignment(Qt::AlignHCenter);
|
||||
contrastValue->setMinimumWidth(contrastValue->fontMetrics().width("+100%"));
|
||||
sliders->addWidget(contrastValue, 0, 1);
|
||||
|
||||
contrast = new QSlider(Qt::Horizontal);
|
||||
contrast->setMinimum(-95);
|
||||
contrast->setMaximum(+95);
|
||||
sliders->addWidget(contrast, 0, 1);
|
||||
sliders->addWidget(contrast, 0, 2);
|
||||
|
||||
lbrightness = new QLabel("Brightness adjust: +100%");
|
||||
sliders->addWidget(lbrightness, 1, 0);
|
||||
brightnessLabel = new QLabel("Brightness adjust:");
|
||||
sliders->addWidget(brightnessLabel, 1, 0);
|
||||
|
||||
brightnessValue = new QLabel;
|
||||
brightnessValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(brightnessValue, 1, 1);
|
||||
|
||||
brightness = new QSlider(Qt::Horizontal);
|
||||
brightness->setMinimum(-95);
|
||||
brightness->setMaximum(+95);
|
||||
sliders->addWidget(brightness, 1, 1);
|
||||
sliders->addWidget(brightness, 1, 2);
|
||||
|
||||
lgamma = new QLabel("Gamma adjust: +100%");
|
||||
sliders->addWidget(lgamma, 2, 0);
|
||||
gammaLabel = new QLabel("Gamma adjust:");
|
||||
sliders->addWidget(gammaLabel, 2, 0);
|
||||
|
||||
gammaValue = new QLabel;
|
||||
gammaValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(gammaValue, 2, 1);
|
||||
|
||||
gamma = new QSlider(Qt::Horizontal);
|
||||
gamma->setMinimum(-95);
|
||||
gamma->setMaximum(+95);
|
||||
sliders->addWidget(gamma, 2, 1);
|
||||
sliders->addWidget(gamma, 2, 2);
|
||||
|
||||
scanlineLabel = new QLabel("Scanline adjust:");
|
||||
sliders->addWidget(scanlineLabel, 3, 0);
|
||||
|
||||
scanlineValue = new QLabel;
|
||||
scanlineValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(scanlineValue, 3, 1);
|
||||
|
||||
scanline = new QSlider(Qt::Horizontal);
|
||||
scanline->setMinimum(0);
|
||||
scanline->setMaximum(20);
|
||||
scanline->setPageStep(4);
|
||||
sliders->addWidget(scanline, 3, 2);
|
||||
}
|
||||
sliders->setSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(sliders);
|
||||
|
@ -48,9 +74,13 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
|||
options->setSpacing(Style::WidgetSpacing);
|
||||
layout->addLayout(options);
|
||||
|
||||
pixelShaderWindow = new PixelShaderWindow;
|
||||
layout->addWidget(pixelShaderWindow);
|
||||
|
||||
connect(contrast, SIGNAL(valueChanged(int)), this, SLOT(contrastAdjust(int)));
|
||||
connect(brightness, SIGNAL(valueChanged(int)), this, SLOT(brightnessAdjust(int)));
|
||||
connect(gamma, SIGNAL(valueChanged(int)), this, SLOT(gammaAdjust(int)));
|
||||
connect(scanline, SIGNAL(valueChanged(int)), this, SLOT(scanlineAdjust(int)));
|
||||
connect(enableGammaRamp, SIGNAL(stateChanged(int)), this, SLOT(gammaRampToggle(int)));
|
||||
|
||||
syncUi();
|
||||
|
@ -59,41 +89,51 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
|||
void VideoSettingsWindow::syncUi() {
|
||||
int n;
|
||||
|
||||
n = config.video.contrastAdjust;
|
||||
lcontrast->setText(utf8() << "Contrast adjust: " << (n > 0 ? "+" : "") << n << "%");
|
||||
n = config().video.contrastAdjust;
|
||||
contrastValue->setText(string() << (n > 0 ? "+" : "") << n << "%");
|
||||
contrast->setSliderPosition(n);
|
||||
|
||||
n = config.video.brightnessAdjust;
|
||||
lbrightness->setText(utf8() << "Brightness adjust: " << (n > 0 ? "+" : "") << n << "%");
|
||||
n = config().video.brightnessAdjust;
|
||||
brightnessValue->setText(string() << (n > 0 ? "+" : "") << n << "%");
|
||||
brightness->setSliderPosition(n);
|
||||
|
||||
n = config.video.gammaAdjust;
|
||||
lgamma->setText(utf8() << "Gamma adjust: " << (n > 0 ? "+" : "") << n << "%");
|
||||
n = config().video.gammaAdjust;
|
||||
gammaValue->setText(string() << (n > 0 ? "+" : "") << n << "%");
|
||||
gamma->setSliderPosition(n);
|
||||
|
||||
enableGammaRamp->setChecked(config.video.enableGammaRamp);
|
||||
}
|
||||
n = config().video.scanlineAdjust;
|
||||
scanlineValue->setText(string() << n << "%");
|
||||
scanline->setSliderPosition(n / 5);
|
||||
|
||||
void VideoSettingsWindow::gammaRampToggle(int state) {
|
||||
config.video.enableGammaRamp = (state == Qt::Checked);
|
||||
syncUi();
|
||||
utility.updateColorFilter();
|
||||
enableGammaRamp->setChecked(config().video.enableGammaRamp);
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::contrastAdjust(int value) {
|
||||
config.video.contrastAdjust = value;
|
||||
config().video.contrastAdjust = value;
|
||||
syncUi();
|
||||
utility.updateColorFilter();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::brightnessAdjust(int value) {
|
||||
config.video.brightnessAdjust = value;
|
||||
config().video.brightnessAdjust = value;
|
||||
syncUi();
|
||||
utility.updateColorFilter();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::gammaAdjust(int value) {
|
||||
config.video.gammaAdjust = value;
|
||||
config().video.gammaAdjust = value;
|
||||
syncUi();
|
||||
utility.updateColorFilter();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::scanlineAdjust(int value) {
|
||||
config().video.scanlineAdjust = value * 5;
|
||||
syncUi();
|
||||
scanlineFilter.setIntensity(value * 5);
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::gammaRampToggle(int state) {
|
||||
config().video.enableGammaRamp = (state == Qt::Checked);
|
||||
syncUi();
|
||||
utility.updateColorFilter();
|
||||
}
|
||||
|
|
|
@ -5,12 +5,18 @@ public:
|
|||
QVBoxLayout *layout;
|
||||
QLabel *title;
|
||||
QGridLayout *sliders;
|
||||
QLabel *lcontrast;
|
||||
QLabel *contrastLabel;
|
||||
QLabel *contrastValue;
|
||||
QSlider *contrast;
|
||||
QLabel *lbrightness;
|
||||
QLabel *brightnessLabel;
|
||||
QLabel *brightnessValue;
|
||||
QSlider *brightness;
|
||||
QLabel *lgamma;
|
||||
QLabel *gammaLabel;
|
||||
QLabel *gammaValue;
|
||||
QSlider *gamma;
|
||||
QLabel *scanlineLabel;
|
||||
QLabel *scanlineValue;
|
||||
QSlider *scanline;
|
||||
QHBoxLayout *options;
|
||||
QCheckBox *enableGammaRamp;
|
||||
|
||||
|
@ -18,8 +24,9 @@ public:
|
|||
VideoSettingsWindow();
|
||||
|
||||
public slots:
|
||||
void gammaRampToggle(int);
|
||||
void contrastAdjust(int);
|
||||
void brightnessAdjust(int);
|
||||
void gammaAdjust(int);
|
||||
void scanlineAdjust(int);
|
||||
void gammaRampToggle(int);
|
||||
} *videoSettingsWindow;
|
||||
|
|
|
@ -115,8 +115,8 @@ void CheatEditorWindow::updateItem(QTreeWidgetItem *item) {
|
|||
if(lcode.size() > 1) lcode[0] << "+" << lcode.size() - 1;
|
||||
|
||||
item->setCheckState(1, code.enabled ? Qt::Checked : Qt::Unchecked);
|
||||
item->setText(1, utf8() << lcode[0]);
|
||||
item->setText(2, utf8() << code.desc);
|
||||
item->setText(1, lcode[0]);
|
||||
item->setText(2, code.desc);
|
||||
}
|
||||
|
||||
void CheatEditorWindow::popupMenu(const QPoint &point) {
|
||||
|
@ -138,7 +138,7 @@ void CheatEditorWindow::reloadList() {
|
|||
item->setData(0, Qt::UserRole, QVariant(n));
|
||||
char slot[16];
|
||||
sprintf(slot, "%3u", n + 1);
|
||||
item->setText(0, utf8() << slot);
|
||||
item->setText(0, slot);
|
||||
updateItem(item);
|
||||
}
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ void CheatEditorWindow::listChanged() {
|
|||
SNES::Cheat::cheat_t code;
|
||||
SNES::cheat.get(n, code);
|
||||
|
||||
descEdit->setText(utf8() << code.desc);
|
||||
codeEdit->setText(utf8() << code.code);
|
||||
descEdit->setText(code.desc);
|
||||
codeEdit->setText(code.code);
|
||||
}
|
||||
|
||||
syncUi();
|
||||
|
|
|
@ -144,7 +144,7 @@ void CheatFinderWindow::searchMemory() {
|
|||
string text = valueEdit->text().toUtf8().constData();
|
||||
|
||||
//auto-detect input data type
|
||||
if(strbegin(text, "0x")) data = strhex(text + 2);
|
||||
if(strbegin(text, "0x")) data = strhex((const char*)text + 2);
|
||||
else if(strbegin(text, "-")) data = strsigned(text);
|
||||
else data = strunsigned(text);
|
||||
|
||||
|
|
|
@ -116,9 +116,9 @@ void StateManagerWindow::reloadList() {
|
|||
lstring part;
|
||||
part.split("\t", state[n]);
|
||||
item->setData(0, Qt::UserRole, QVariant(n));
|
||||
item->setText(0, utf8() << part[0]);
|
||||
item->setText(1, utf8() << part[1]);
|
||||
item->setText(2, utf8() << part[2]);
|
||||
item->setText(0, part[0]);
|
||||
item->setText(1, part[1]);
|
||||
item->setText(2, part[2]);
|
||||
}
|
||||
|
||||
list->setSortingEnabled(true);
|
||||
|
@ -131,9 +131,9 @@ void StateManagerWindow::updateItem(QTreeWidgetItem *item) {
|
|||
lstring state, part;
|
||||
utility.loadStateInfo(state);
|
||||
part.split("\t", state[n]);
|
||||
item->setText(0, utf8() << part[0]);
|
||||
item->setText(1, utf8() << part[1]);
|
||||
item->setText(2, utf8() << part[2]);
|
||||
item->setText(0, part[0]);
|
||||
item->setText(1, part[1]);
|
||||
item->setText(2, part[2]);
|
||||
}
|
||||
|
||||
void StateManagerWindow::listChanged() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "cheatfinder.cpp"
|
||||
#include "statemanager.cpp"
|
||||
|
||||
ToolsWindow::ToolsWindow() : QbWindow(config.geometry.toolsWindow) {
|
||||
ToolsWindow::ToolsWindow() : QbWindow(config().geometry.toolsWindow) {
|
||||
setObjectName("tools-window");
|
||||
setWindowTitle("Tools");
|
||||
resize(625, 360);
|
||||
|
|
|
@ -6,6 +6,7 @@ bool Utility::loadCartridgeNormal(const char *base) {
|
|||
loadMemory(cartridge.baseName, ".srm", SNES::memory::cartram);
|
||||
loadMemory(cartridge.baseName, ".rtc", SNES::memory::cartrtc);
|
||||
|
||||
cartridge.fileName = cartridge.baseName;
|
||||
cartridge.name = notdir(nall::basename(cartridge.baseName));
|
||||
|
||||
modifySystemState(LoadCartridge);
|
||||
|
@ -21,6 +22,7 @@ bool Utility::loadCartridgeBsxSlotted(const char *base, const char *slot) {
|
|||
loadMemory(cartridge.baseName, ".srm", SNES::memory::cartram);
|
||||
loadMemory(cartridge.baseName, ".rtc", SNES::memory::cartrtc);
|
||||
|
||||
cartridge.fileName = cartridge.baseName;
|
||||
cartridge.name = notdir(nall::basename(cartridge.baseName));
|
||||
if(*slot) cartridge.name << " + " << notdir(nall::basename(cartridge.slotAName));
|
||||
|
||||
|
@ -37,6 +39,7 @@ bool Utility::loadCartridgeBsx(const char *base, const char *slot) {
|
|||
loadMemory(cartridge.baseName, ".srm", SNES::memory::bsxram );
|
||||
loadMemory(cartridge.baseName, ".psr", SNES::memory::bsxpram);
|
||||
|
||||
cartridge.fileName = cartridge.slotAName;
|
||||
cartridge.name = *slot
|
||||
? notdir(nall::basename(cartridge.slotAName))
|
||||
: notdir(nall::basename(cartridge.baseName));
|
||||
|
@ -55,6 +58,7 @@ bool Utility::loadCartridgeSufamiTurbo(const char *base, const char *slotA, cons
|
|||
loadMemory(cartridge.slotAName, ".srm", SNES::memory::stAram);
|
||||
loadMemory(cartridge.slotBName, ".srm", SNES::memory::stBram);
|
||||
|
||||
cartridge.fileName = cartridge.slotAName;
|
||||
if(!*slotA && !*slotB) cartridge.name = notdir(nall::basename(cartridge.baseName));
|
||||
else if(!*slotB) cartridge.name = notdir(nall::basename(cartridge.slotAName));
|
||||
else if(!*slotA) cartridge.name = notdir(nall::basename(cartridge.slotBName));
|
||||
|
@ -73,6 +77,7 @@ bool Utility::loadCartridgeSuperGameBoy(const char *base, const char *slot) {
|
|||
loadMemory(cartridge.slotAName, ".sav", SNES::memory::gbram);
|
||||
loadMemory(cartridge.slotBName, ".rtc", SNES::memory::gbrtc);
|
||||
|
||||
cartridge.fileName = cartridge.slotAName;
|
||||
cartridge.name = *slot
|
||||
? notdir(nall::basename(cartridge.slotAName))
|
||||
: notdir(nall::basename(cartridge.baseName));
|
||||
|
@ -134,16 +139,16 @@ void Utility::modifySystemState(system_state_t state) {
|
|||
else if(SNES::cartridge.has_st011()) chip = "ST011";
|
||||
else if(SNES::cartridge.has_st018()) chip = "ST018";
|
||||
if(chip != "") {
|
||||
QMessageBox::warning(mainWindow, "Warning", utf8()
|
||||
QMessageBox::warning(mainWindow, "Warning", string()
|
||||
<< "<p><b>Warning:</b><br> The " << chip << " chip was detected, which is not fully emulated yet.<br>"
|
||||
<< "It is unlikely that this title will work properly.</p>");
|
||||
}
|
||||
|
||||
showMessage(utf8()
|
||||
showMessage(string()
|
||||
<< "Loaded " << cartridge.name
|
||||
<< (cartridge.patchApplied ? ", and applied UPS patch." : "."));
|
||||
mainWindow->setWindowTitle(utf8() << bsnesTitle << " v" << bsnesVersion << " - " << cartridge.name);
|
||||
debugger->echo(utf8() << "Loaded " << cartridge.name << ".<br>");
|
||||
mainWindow->setWindowTitle(string() << bsnesTitle << " v" << bsnesVersion << " - " << cartridge.name);
|
||||
debugger->echo(string() << "Loaded " << cartridge.name << ".<br>");
|
||||
} break;
|
||||
|
||||
case UnloadCartridge: {
|
||||
|
@ -157,8 +162,8 @@ void Utility::modifySystemState(system_state_t state) {
|
|||
application.power = false;
|
||||
application.pause = true;
|
||||
|
||||
showMessage(utf8() << "Unloaded " << cartridge.name << ".");
|
||||
mainWindow->setWindowTitle(utf8() << bsnesTitle << " v" << bsnesVersion);
|
||||
showMessage(string() << "Unloaded " << cartridge.name << ".");
|
||||
mainWindow->setWindowTitle(string() << bsnesTitle << " v" << bsnesVersion);
|
||||
} break;
|
||||
|
||||
case PowerOn: {
|
||||
|
@ -217,7 +222,7 @@ bool Utility::loadCartridge(string &filename, SNES::MappedRAM &memory) {
|
|||
|
||||
cartridge.patchApplied = false;
|
||||
string name;
|
||||
name << filepath(nall::basename(filename), config.path.patch);
|
||||
name << filepath(nall::basename(filename), config().path.patch);
|
||||
name << ".ups";
|
||||
|
||||
file fp;
|
||||
|
@ -235,7 +240,7 @@ bool Utility::loadCartridge(string &filename, SNES::MappedRAM &memory) {
|
|||
|
||||
bool apply = false;
|
||||
if(result == ups::ok) apply = true;
|
||||
if(config.file.bypass_patch_crc32) {
|
||||
if(config().file.bypass_patch_crc32) {
|
||||
if(result == ups::input_crc32_invalid ) apply = true;
|
||||
if(result == ups::output_crc32_invalid) apply = true;
|
||||
}
|
||||
|
@ -259,7 +264,7 @@ bool Utility::loadMemory(const char *filename, const char *extension, SNES::Mapp
|
|||
if(memory.size() == 0 || memory.size() == -1U) return false;
|
||||
|
||||
string name;
|
||||
name << filepath(nall::basename(filename), config.path.save);
|
||||
name << filepath(nall::basename(filename), config().path.save);
|
||||
name << extension;
|
||||
|
||||
file fp;
|
||||
|
@ -279,7 +284,7 @@ bool Utility::saveMemory(const char *filename, const char *extension, SNES::Mapp
|
|||
if(memory.size() == 0 || memory.size() == -1U) return false;
|
||||
|
||||
string name;
|
||||
name << filepath(nall::basename(filename), config.path.save);
|
||||
name << filepath(nall::basename(filename), config().path.save);
|
||||
name << extension;
|
||||
|
||||
file fp;
|
||||
|
@ -292,7 +297,7 @@ bool Utility::saveMemory(const char *filename, const char *extension, SNES::Mapp
|
|||
|
||||
void Utility::loadCheats() {
|
||||
string name, data;
|
||||
name << filepath(nall::basename(cartridge.baseName), config.path.cheat);
|
||||
name << filepath(nall::basename(cartridge.baseName), config().path.cheat);
|
||||
name << ".cht";
|
||||
|
||||
SNES::cheat.clear();
|
||||
|
@ -301,7 +306,7 @@ void Utility::loadCheats() {
|
|||
|
||||
void Utility::saveCheats() {
|
||||
string name;
|
||||
name << filepath(nall::basename(cartridge.baseName), config.path.cheat);
|
||||
name << filepath(nall::basename(cartridge.baseName), config().path.cheat);
|
||||
name << ".cht";
|
||||
|
||||
file fp;
|
||||
|
@ -327,7 +332,7 @@ string Utility::filepath(const char *filename, const char *pathname) {
|
|||
//replace relative path with absolute path
|
||||
if(strbegin(path, "./")) {
|
||||
ltrim(path, "./");
|
||||
path = string() << config.path.base << path;
|
||||
path = string() << config().path.base << path;
|
||||
}
|
||||
|
||||
//remove folder part of filename
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//this function is used to disable save state support globally for these titles.
|
||||
bool Utility::saveStatesSupported() {
|
||||
if(SNES::cartridge.mode() == SNES::Cartridge::ModeBsx) return false;
|
||||
if(SNES::cartridge.mode() == SNES::Cartridge::ModeSuperGameBoy) return false;
|
||||
|
||||
if(SNES::cartridge.has_superfx()) return false;
|
||||
if(SNES::cartridge.has_sa1()) return false;
|
||||
|
@ -18,17 +17,17 @@ bool Utility::saveStatesSupported() {
|
|||
void Utility::quickLoad(uint8 slot) {
|
||||
if(SNES::cartridge.loaded() == false || application.power == false) return;
|
||||
if(saveStatesSupported() == false) {
|
||||
showMessage(utf8() << "Error: cannot save state due to unserializable special chip.");
|
||||
showMessage(string() << "Error: cannot save state due to unserializable special chip.");
|
||||
return;
|
||||
}
|
||||
|
||||
string name;
|
||||
name << filepath(nall::basename(cartridge.baseName), config.path.state);
|
||||
name << filepath(nall::basename(cartridge.fileName), config().path.state);
|
||||
name << "-" << (unsigned)(slot + 1) << ".bst";
|
||||
|
||||
file fp;
|
||||
if(fp.open(name, file::mode_read) == false) {
|
||||
showMessage(utf8() << "Error: unable to load quick state " << (unsigned)(slot + 1) << ".");
|
||||
showMessage(string() << "Error: unable to load quick state " << (unsigned)(slot + 1) << ".");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -39,64 +38,64 @@ void Utility::quickLoad(uint8 slot) {
|
|||
|
||||
serializer state(data, size);
|
||||
if(SNES::system.unserialize(state) == true) {
|
||||
showMessage(utf8() << "Quick state " << (unsigned)(slot + 1) << " loaded.");
|
||||
showMessage(string() << "Quick state " << (unsigned)(slot + 1) << " loaded.");
|
||||
} else {
|
||||
showMessage(utf8() << "Error: unable to load quick state " << (unsigned)(slot + 1) << ".");
|
||||
showMessage(string() << "Error: unable to load quick state " << (unsigned)(slot + 1) << ".");
|
||||
}
|
||||
}
|
||||
|
||||
void Utility::quickSave(uint8 slot) {
|
||||
if(SNES::cartridge.loaded() == false || application.power == false) return;
|
||||
if(saveStatesSupported() == false) {
|
||||
showMessage(utf8() << "Error: cannot save state due to unserializable special chip.");
|
||||
showMessage(string() << "Error: cannot save state due to unserializable special chip.");
|
||||
return;
|
||||
}
|
||||
|
||||
SNES::system.runtosave();
|
||||
|
||||
string name;
|
||||
name << filepath(nall::basename(cartridge.baseName), config.path.state);
|
||||
name << filepath(nall::basename(cartridge.fileName), config().path.state);
|
||||
name << "-" << (unsigned)(slot + 1) << ".bst";
|
||||
|
||||
serializer state = SNES::system.serialize();
|
||||
file fp;
|
||||
if(fp.open(name, file::mode_write) == false) {
|
||||
showMessage(utf8() << "Error: unable to save quick state " << (unsigned)(slot + 1) << ".");
|
||||
showMessage(string() << "Error: unable to save quick state " << (unsigned)(slot + 1) << ".");
|
||||
return;
|
||||
}
|
||||
|
||||
fp.write(state.data(), state.size());
|
||||
fp.close();
|
||||
showMessage(utf8() << "Quick state " << (unsigned)(slot + 1) << " saved.");
|
||||
showMessage(string() << "Quick state " << (unsigned)(slot + 1) << " saved.");
|
||||
}
|
||||
|
||||
void Utility::loadStateInfo(lstring &info) {
|
||||
info.reset();
|
||||
string name = string() << filepath(nall::basename(cartridge.baseName), config.path.state) << ".bsa";
|
||||
string name = string() << filepath(nall::basename(cartridge.fileName), config().path.state) << ".bsa";
|
||||
if(SNES::statemanager.load(name) == false) return;
|
||||
SNES::statemanager.list(info);
|
||||
}
|
||||
|
||||
void Utility::setStateDescription(uint8 slot, const char *description) {
|
||||
if(SNES::cartridge.loaded() == false) return;
|
||||
string name = string() << filepath(nall::basename(cartridge.baseName), config.path.state) << ".bsa";
|
||||
string name = string() << filepath(nall::basename(cartridge.fileName), config().path.state) << ".bsa";
|
||||
SNES::statemanager.set_description(name, slot, description);
|
||||
}
|
||||
|
||||
void Utility::loadState(uint8 slot) {
|
||||
if(SNES::cartridge.loaded() == false || application.power == false) return;
|
||||
string name = string() << filepath(nall::basename(cartridge.baseName), config.path.state) << ".bsa";
|
||||
string name = string() << filepath(nall::basename(cartridge.fileName), config().path.state) << ".bsa";
|
||||
|
||||
try {
|
||||
serializer state = SNES::statemanager.load(name, slot);
|
||||
|
||||
if(SNES::system.unserialize(state) == true) {
|
||||
showMessage(utf8() << "State loaded.");
|
||||
showMessage(string() << "State loaded.");
|
||||
} else {
|
||||
showMessage(utf8() << "Error: unable to load state.");
|
||||
showMessage(string() << "Error: unable to load state.");
|
||||
}
|
||||
} catch(...) {
|
||||
showMessage(utf8() << "Error: unable to load state.");
|
||||
showMessage(string() << "Error: unable to load state.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -106,20 +105,20 @@ void Utility::saveState(uint8 slot, const char *description) {
|
|||
SNES::system.runtosave();
|
||||
|
||||
serializer state = SNES::system.serialize();
|
||||
string name = string() << filepath(nall::basename(cartridge.baseName), config.path.state) << ".bsa";
|
||||
string name = string() << filepath(nall::basename(cartridge.fileName), config().path.state) << ".bsa";
|
||||
if(SNES::statemanager.save(name, slot, state, description) == true) {
|
||||
showMessage(utf8() << "State saved.");
|
||||
showMessage(string() << "State saved.");
|
||||
} else {
|
||||
showMessage(utf8() << "Error: unable to save state.");
|
||||
showMessage(string() << "Error: unable to save state.");
|
||||
}
|
||||
}
|
||||
|
||||
void Utility::deleteState(uint8 slot) {
|
||||
if(SNES::cartridge.loaded() == false) return;
|
||||
string name = string() << filepath(nall::basename(cartridge.baseName), config.path.state) << ".bsa";
|
||||
string name = string() << filepath(nall::basename(cartridge.fileName), config().path.state) << ".bsa";
|
||||
if(SNES::statemanager.erase(name, slot) == true) {
|
||||
showMessage(utf8() << "State deleted.");
|
||||
showMessage(string() << "State deleted.");
|
||||
} else {
|
||||
showMessage(utf8() << "Error: unable to delete state.");
|
||||
showMessage(string() << "Error: unable to delete state.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,46 +2,9 @@
|
|||
#include "state.cpp"
|
||||
#include "window.cpp"
|
||||
|
||||
//returns true if requested code is a button, and it has just been pressed down
|
||||
bool Utility::isButtonDown(uint16_t inputCode, InputObject &object) {
|
||||
if(inputCode != object.code) return false;
|
||||
|
||||
if(object.codetype != InputCode::KeyboardButton
|
||||
&& object.codetype != InputCode::MouseButton
|
||||
&& object.codetype != InputCode::JoypadHat
|
||||
&& object.codetype != InputCode::JoypadAxis
|
||||
&& object.codetype != InputCode::JoypadButton) return false;
|
||||
|
||||
int16_t state = inputManager.state(object.code);
|
||||
int16_t lastState = inputManager.lastState(object.code);
|
||||
|
||||
if(object.codetype == InputCode::JoypadHat) {
|
||||
switch(object.modifier) {
|
||||
case InputObject::Up: return (state & joypad<>::hat_up ) && !(lastState & joypad<>::hat_up );
|
||||
case InputObject::Down: return (state & joypad<>::hat_down ) && !(lastState & joypad<>::hat_down );
|
||||
case InputObject::Left: return (state & joypad<>::hat_left ) && !(lastState & joypad<>::hat_left );
|
||||
case InputObject::Right: return (state & joypad<>::hat_right) && !(lastState & joypad<>::hat_right);
|
||||
}
|
||||
} else if(object.codetype == InputCode::JoypadAxis) {
|
||||
switch(object.modifier) {
|
||||
case InputObject::Lo: return (state < -16384) && !(lastState < -16384);
|
||||
case InputObject::Hi: return (state > +16384) && !(lastState > +16384);
|
||||
case InputObject::Trigger: return (state < 0) && !(lastState < 0);
|
||||
}
|
||||
} else {
|
||||
return (state == 1) && !(lastState == 1);
|
||||
}
|
||||
|
||||
return false; //fall-through for modifier-less hats / axes
|
||||
}
|
||||
|
||||
void Utility::inputEvent(uint16_t code) {
|
||||
//forward key-press event
|
||||
//(in case window is currently active and capturing a new button / axis assignment)
|
||||
inputCaptureWindow->inputEvent(code);
|
||||
|
||||
for(unsigned i = 0; i < keyboard<>::count; i++) {
|
||||
if(code == keyboard<>::index(i, keyboard<>::escape) && inputManager.state(code)) {
|
||||
void Utility::inputEvent(uint16_t scancode) {
|
||||
for(unsigned i = 0; i < Keyboard::Count; i++) {
|
||||
if(scancode == keyboard(i)[Keyboard::Escape] && mapper().state(scancode)) {
|
||||
if(mainWindow->isActive() && input.acquired()) {
|
||||
//release mouse capture
|
||||
input.unacquire();
|
||||
|
@ -49,96 +12,11 @@ void Utility::inputEvent(uint16_t code) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mainWindow->isActive()) {
|
||||
bool resizeWindow = false;
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.loadCartridge)) {
|
||||
diskBrowser->loadCartridge();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.pauseEmulation)) {
|
||||
application.pause = !application.pause;
|
||||
if(application.pause) audio.clear();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.resetSystem)) {
|
||||
modifySystemState(Reset);
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.powerCycleSystem)) {
|
||||
modifySystemState(PowerCycle);
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.captureScreenshot)) {
|
||||
//tell SNES::Interface to save a screenshot at the next video_refresh() event
|
||||
interface.saveScreenshot = true;
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.showStateManager)) {
|
||||
toolsWindow->showStateManager();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.quickLoad1)) utility.quickLoad(0);
|
||||
if(isButtonDown(code, inputUiGeneral.quickLoad2)) utility.quickLoad(1);
|
||||
if(isButtonDown(code, inputUiGeneral.quickLoad3)) utility.quickLoad(2);
|
||||
if(isButtonDown(code, inputUiGeneral.quickSave1)) utility.quickSave(0);
|
||||
if(isButtonDown(code, inputUiGeneral.quickSave2)) utility.quickSave(1);
|
||||
if(isButtonDown(code, inputUiGeneral.quickSave3)) utility.quickSave(2);
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.lowerSpeed)) {
|
||||
config.system.speed--;
|
||||
updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.raiseSpeed)) {
|
||||
config.system.speed++;
|
||||
updateEmulationSpeed();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.toggleCheatSystem)) {
|
||||
if(SNES::cheat.enabled() == false) {
|
||||
SNES::cheat.enable();
|
||||
showMessage("Cheat system enabled.");
|
||||
} else {
|
||||
SNES::cheat.disable();
|
||||
showMessage("Cheat system disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.toggleFullscreen)) {
|
||||
config.video.isFullscreen = !config.video.isFullscreen;
|
||||
updateFullscreenState();
|
||||
resizeMainWindow();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.toggleMenu)) {
|
||||
mainWindow->menuBar->setVisible(!mainWindow->menuBar->isVisibleTo(mainWindow));
|
||||
resizeWindow = true;
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.toggleStatus)) {
|
||||
mainWindow->statusBar->setVisible(!mainWindow->statusBar->isVisibleTo(mainWindow));
|
||||
resizeWindow = true;
|
||||
}
|
||||
|
||||
//prevent calling twice when toggleMenu == toggleStatus
|
||||
if(resizeWindow == true) {
|
||||
resizeMainWindow();
|
||||
}
|
||||
|
||||
if(isButtonDown(code, inputUiGeneral.exitEmulator)) {
|
||||
application.terminate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//display message in main window statusbar area for three seconds
|
||||
void Utility::showMessage(const char *message) {
|
||||
mainWindow->statusBar->showMessage(utf8() << message, 3000);
|
||||
mainWindow->statusBar->showMessage(string() << message, 3000);
|
||||
}
|
||||
|
||||
//updates system state text at bottom-right of main window statusbar
|
||||
|
@ -160,7 +38,7 @@ void Utility::updateSystemState() {
|
|||
return;
|
||||
}
|
||||
|
||||
mainWindow->systemState->setText(utf8() << text);
|
||||
mainWindow->systemState->setText(text);
|
||||
}
|
||||
|
||||
void Utility::acquireMouse() {
|
||||
|
@ -179,12 +57,12 @@ void Utility::unacquireMouse() {
|
|||
}
|
||||
|
||||
void Utility::updateAvSync() {
|
||||
video.set(Video::Synchronize, config.video.synchronize);
|
||||
audio.set(Audio::Synchronize, config.audio.synchronize);
|
||||
video.set(Video::Synchronize, config().video.synchronize);
|
||||
audio.set(Audio::Synchronize, config().audio.synchronize);
|
||||
}
|
||||
|
||||
void Utility::updateVideoMode() {
|
||||
if(config.video.context->region == 0) {
|
||||
if(config().video.context->region == 0) {
|
||||
SNES::video.set_mode(SNES::Video::ModeNTSC);
|
||||
} else {
|
||||
SNES::video.set_mode(SNES::Video::ModePAL);
|
||||
|
@ -192,42 +70,43 @@ void Utility::updateVideoMode() {
|
|||
}
|
||||
|
||||
void Utility::updateColorFilter() {
|
||||
filter.contrast = config.video.contrastAdjust;
|
||||
filter.brightness = config.video.brightnessAdjust;
|
||||
filter.gamma = 100 + config.video.gammaAdjust;
|
||||
filter.gamma_ramp = config.video.enableGammaRamp;
|
||||
filter.contrast = config().video.contrastAdjust;
|
||||
filter.brightness = config().video.brightnessAdjust;
|
||||
filter.gamma = 100 + config().video.gammaAdjust;
|
||||
filter.gamma_ramp = config().video.enableGammaRamp;
|
||||
filter.colortable_update();
|
||||
}
|
||||
|
||||
void Utility::updatePixelShader() {
|
||||
string filedata;
|
||||
|
||||
if(filedata.readfile(config().path.fragmentShader)) {
|
||||
video.set(Video::FragmentShader, (const char*)filedata);
|
||||
} else {
|
||||
video.set(Video::FragmentShader, (const char*)0);
|
||||
}
|
||||
|
||||
if(filedata.readfile(config().path.vertexShader)) {
|
||||
video.set(Video::VertexShader, (const char*)filedata);
|
||||
} else {
|
||||
video.set(Video::VertexShader, (const char*)0);
|
||||
}
|
||||
}
|
||||
|
||||
void Utility::updateHardwareFilter() {
|
||||
video.set(Video::Filter, config.video.context->hwFilter);
|
||||
video.set(Video::Filter, config().video.context->hwFilter);
|
||||
}
|
||||
|
||||
void Utility::updateSoftwareFilter() {
|
||||
filter.renderer = config.video.context->swFilter;
|
||||
|
||||
/*libfilter::FilterInterface::FilterType type;
|
||||
switch(config.video.context->swFilter) { default:
|
||||
case 0: type = libfilter::FilterInterface::Direct; break;
|
||||
case 1: type = libfilter::FilterInterface::Scanline; break;
|
||||
case 2: type = libfilter::FilterInterface::Scale2x; break;
|
||||
case 3: type = libfilter::FilterInterface::LQ2x; break;
|
||||
case 4: type = libfilter::FilterInterface::HQ2x; break;
|
||||
case 5: type = libfilter::FilterInterface::NTSC; break;
|
||||
}
|
||||
libfilter::filter.set(type);
|
||||
|
||||
if(type == libfilter::FilterInterface::NTSC) {
|
||||
libfilter::filter_ntsc.adjust(0, 0, 0, 0, 0, config.video.enableNtscMergeFields);
|
||||
}*/
|
||||
filter.renderer = config().video.context->swFilter;
|
||||
}
|
||||
|
||||
void Utility::updateEmulationSpeed() {
|
||||
config.system.speed = max(0, min(4, (signed)config.system.speed));
|
||||
config().system.speed = max(0, min(4, (signed)config().system.speed));
|
||||
|
||||
double scale[] = { 0.50, 0.75, 1.00, 1.50, 2.00 };
|
||||
unsigned outfreq = config.audio.outputFrequency;
|
||||
unsigned infreq = config.audio.inputFrequency * scale[config.system.speed] + 0.5;
|
||||
unsigned outfreq = config().audio.outputFrequency;
|
||||
unsigned infreq = config().audio.inputFrequency * scale[config().system.speed] + 0.5;
|
||||
|
||||
audio.set(Audio::Resample, true); //always resample (required for volume adjust + frequency scaler)
|
||||
audio.set(Audio::ResampleRatio, (double)infreq / (double)outfreq);
|
||||
|
@ -236,4 +115,25 @@ void Utility::updateEmulationSpeed() {
|
|||
void Utility::updateControllers() {
|
||||
SNES::input.port_set_device(0, SNES::config.controller_port1);
|
||||
SNES::input.port_set_device(1, SNES::config.controller_port2);
|
||||
|
||||
switch(config().input.port1) { default:
|
||||
case ControllerPort1::None: mapper().port1 = 0; break;
|
||||
case ControllerPort1::Gamepad: mapper().port1 = &Controllers::gamepad1; break;
|
||||
case ControllerPort1::Asciipad: mapper().port1 = &Controllers::asciipad1; break;
|
||||
case ControllerPort1::Multitap: mapper().port1 = &Controllers::multitap1; break;
|
||||
case ControllerPort1::Mouse: mapper().port1 = &Controllers::mouse1; break;
|
||||
}
|
||||
|
||||
switch(config().input.port2) { default:
|
||||
case ControllerPort2::None: mapper().port2 = 0; break;
|
||||
case ControllerPort2::Gamepad: mapper().port2 = &Controllers::gamepad2; break;
|
||||
case ControllerPort2::Asciipad: mapper().port2 = &Controllers::asciipad2; break;
|
||||
case ControllerPort2::Multitap: mapper().port2 = &Controllers::multitap2; break;
|
||||
case ControllerPort2::Mouse: mapper().port2 = &Controllers::mouse2; break;
|
||||
case ControllerPort2::SuperScope: mapper().port2 = &Controllers::superscope; break;
|
||||
case ControllerPort2::Justifier: mapper().port2 = &Controllers::justifier1; break;
|
||||
case ControllerPort2::Justifiers: mapper().port2 = &Controllers::justifiers; break;
|
||||
}
|
||||
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
class Utility {
|
||||
public:
|
||||
//utility.cpp
|
||||
bool isButtonDown(uint16_t inputCode, InputObject &object);
|
||||
void inputEvent(uint16_t code);
|
||||
void inputEvent(uint16_t scancode);
|
||||
void showMessage(const char *message);
|
||||
void updateSystemState();
|
||||
void acquireMouse();
|
||||
|
@ -11,6 +10,7 @@ public:
|
|||
void updateAvSync();
|
||||
void updateVideoMode();
|
||||
void updateColorFilter();
|
||||
void updatePixelShader();
|
||||
void updateHardwareFilter();
|
||||
void updateSoftwareFilter();
|
||||
void updateEmulationSpeed();
|
||||
|
@ -18,7 +18,8 @@ public:
|
|||
|
||||
//cartridge.cpp
|
||||
struct Cartridge {
|
||||
string name; //printable cartridge name
|
||||
string name; //printable cartridge name
|
||||
string fileName; //ideal file name for saving eg states to disk
|
||||
string baseName, slotAName, slotBName;
|
||||
bool patchApplied;
|
||||
} cartridge;
|
||||
|
@ -56,4 +57,14 @@ public:
|
|||
void updateFullscreenState();
|
||||
void constrainSize(unsigned &x, unsigned &y, unsigned max);
|
||||
void resizeMainWindow();
|
||||
void toggleSynchronizeVideo();
|
||||
void toggleSynchronizeAudio();
|
||||
void setNtscMode();
|
||||
void setPalMode();
|
||||
void toggleSmoothVideoOutput();
|
||||
void toggleAspectCorrection();
|
||||
void setScale(unsigned);
|
||||
void toggleFullscreen();
|
||||
void toggleMenubar();
|
||||
void toggleStatusbar();
|
||||
} utility;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
void Utility::updateFullscreenState() {
|
||||
video.clear();
|
||||
|
||||
if(config.video.isFullscreen == false) {
|
||||
config.video.context = &config.video.windowed;
|
||||
if(config().video.isFullscreen == false) {
|
||||
config().video.context = &config().video.windowed;
|
||||
mainWindow->showNormal();
|
||||
mainWindow->menuBar->setVisible(true);
|
||||
mainWindow->statusBar->setVisible(true);
|
||||
} else {
|
||||
config.video.context = &config.video.fullscreen;
|
||||
config().video.context = &config().video.fullscreen;
|
||||
mainWindow->showFullScreen();
|
||||
mainWindow->menuBar->setVisible(!config.system.autoHideMenus);
|
||||
mainWindow->statusBar->setVisible(!config.system.autoHideMenus);
|
||||
mainWindow->menuBar->setVisible(!config().system.autoHideMenus);
|
||||
mainWindow->statusBar->setVisible(!config().system.autoHideMenus);
|
||||
}
|
||||
|
||||
QApplication::processEvents();
|
||||
|
@ -37,20 +37,20 @@ void Utility::constrainSize(unsigned &x, unsigned &y, unsigned max) {
|
|||
}
|
||||
|
||||
void Utility::resizeMainWindow() {
|
||||
unsigned region = config.video.context->region;
|
||||
unsigned multiplier = config.video.context->multiplier;
|
||||
unsigned region = config().video.context->region;
|
||||
unsigned multiplier = config().video.context->multiplier;
|
||||
unsigned width = 256 * multiplier;
|
||||
unsigned height = (region == 0 ? 224 : 239) * multiplier;
|
||||
|
||||
if(config.video.context->correctAspectRatio) {
|
||||
if(config().video.context->correctAspectRatio) {
|
||||
if(region == 0) {
|
||||
width = (double)width * config.video.ntscAspectRatio + 0.5; //NTSC adjust
|
||||
width = (double)width * config().video.ntscAspectRatio + 0.5; //NTSC adjust
|
||||
} else {
|
||||
width = (double)width * config.video.palAspectRatio + 0.5; //PAL adjust
|
||||
width = (double)width * config().video.palAspectRatio + 0.5; //PAL adjust
|
||||
}
|
||||
}
|
||||
|
||||
if(config.video.isFullscreen == false) {
|
||||
if(config().video.isFullscreen == false) {
|
||||
//get effective desktop work area region (ignore Windows taskbar, OS X dock, etc.)
|
||||
QRect deskRect = QApplication::desktop()->availableGeometry(mainWindow);
|
||||
|
||||
|
@ -88,3 +88,72 @@ void Utility::resizeMainWindow() {
|
|||
//window resizing sometimes breaks audio sync, this call re-initializes it
|
||||
updateAvSync();
|
||||
}
|
||||
|
||||
void Utility::toggleSynchronizeVideo() {
|
||||
mainWindow->settings_emulationSpeed_syncVideo->toggleChecked();
|
||||
config().video.synchronize = mainWindow->settings_emulationSpeed_syncVideo->isChecked();
|
||||
updateAvSync();
|
||||
}
|
||||
|
||||
void Utility::toggleSynchronizeAudio() {
|
||||
mainWindow->settings_emulationSpeed_syncAudio->toggleChecked();
|
||||
config().audio.synchronize = mainWindow->settings_emulationSpeed_syncAudio->isChecked();
|
||||
updateAvSync();
|
||||
}
|
||||
|
||||
void Utility::setNtscMode() {
|
||||
config().video.context->region = 0;
|
||||
updateVideoMode();
|
||||
resizeMainWindow();
|
||||
mainWindow->shrink();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
void Utility::setPalMode() {
|
||||
config().video.context->region = 1;
|
||||
updateVideoMode();
|
||||
resizeMainWindow();
|
||||
mainWindow->shrink();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
void Utility::toggleSmoothVideoOutput() {
|
||||
mainWindow->settings_smoothVideo->toggleChecked();
|
||||
config().video.context->hwFilter = mainWindow->settings_smoothVideo->isChecked();
|
||||
updateHardwareFilter();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
void Utility::toggleAspectCorrection() {
|
||||
mainWindow->settings_videoMode_correctAspectRatio->toggleChecked();
|
||||
config().video.context->correctAspectRatio = mainWindow->settings_videoMode_correctAspectRatio->isChecked();
|
||||
resizeMainWindow();
|
||||
mainWindow->shrink();
|
||||
}
|
||||
|
||||
void Utility::setScale(unsigned scale) {
|
||||
config().video.context->multiplier = scale;
|
||||
resizeMainWindow();
|
||||
mainWindow->shrink();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
void Utility::toggleFullscreen() {
|
||||
mainWindow->settings_videoMode_fullscreen->toggleChecked();
|
||||
config().video.isFullscreen = mainWindow->settings_videoMode_fullscreen->isChecked();
|
||||
updateFullscreenState();
|
||||
resizeMainWindow();
|
||||
mainWindow->syncUi();
|
||||
}
|
||||
|
||||
void Utility::toggleMenubar() {
|
||||
mainWindow->menuBar->setVisible(!mainWindow->menuBar->isVisibleTo(mainWindow));
|
||||
resizeMainWindow();
|
||||
mainWindow->shrink();
|
||||
}
|
||||
|
||||
void Utility::toggleStatusbar() {
|
||||
mainWindow->statusBar->setVisible(!mainWindow->statusBar->isVisibleTo(mainWindow));
|
||||
resizeMainWindow();
|
||||
mainWindow->shrink();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue