bsnes/ananke/phoenix/windows/utility.cpp

151 lines
7.8 KiB
C++
Raw Normal View History

Update to v091r11 release. byuu says: This release refines HSU1 support as a bidirectional protocol, nests SFC manifests as "release/cartridge" and "release/information" (but release/ is not guaranteed to be finalized just yet), removes the database integration, and adds support for ananke. ananke represents inevitability. It's a library that, when installed, higan can use to load files from the command-line, and also from a new File -> Load Game menu option. I need to change the build rules a bit for it to work on Windows (need to make phoenix a DLL, basically), but it works now on Linux. Right now, it only takes *.sfc file names, looks them up in the included database, converts them to game folders, and returns the game folder path for higan to load. The idea is to continue expanding it to support everything we can that I don't want in the higan core: - load *.sfc, *.smc, *.swc, *.fig files - remove SNES copier headers - split apart merged firmware files - pull in external firmware files (eg dsp1b.rom - these are staying merged, just as SPC7110 prg+dat are merged) - load *.zip and *.7z archives - prompt for selection on multi-file archives - generate manifest files based on heuristics - apply BPS patches The "Load" menu option has been renamed to "Library", to represent games in your library. I'm going to add some sort of suffix to indicate unverified games, and use a different folder icon for those (eg manifests built on heuristics rather than from the database.) So basically, to future end users: File -> Load Game will be how they play games. Library -> (specific system) can be thought of as an infinitely-sized recent games list. purify will likely become a simple stub that invokes ananke's functions. No reason to duplicate all that code.
2012-11-05 08:22:50 +00:00
static const unsigned Windows2000 = 0x0500;
static const unsigned WindowsXP = 0x0501;
static const unsigned WindowsVista = 0x0600;
static const unsigned Windows7 = 0x0601;
static unsigned OsVersion() {
OSVERSIONINFO versionInfo = { 0 };
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&versionInfo);
return (versionInfo.dwMajorVersion << 8) + (versionInfo.dwMajorVersion << 0);
}
static HBITMAP CreateBitmap(const image &image) {
HDC hdc = GetDC(0);
BITMAPINFO bitmapInfo;
memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = image.width;
bitmapInfo.bmiHeader.biHeight = -image.height; //bitmaps are stored upside down unless we negate height
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = image.width * image.height * 4;
void *bits = nullptr;
HBITMAP hbitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
if(bits) memcpy(bits, image.data, image.width * image.height * 4);
ReleaseDC(0, hdc);
return hbitmap;
}
static Keyboard::Keycode Keysym(unsigned keysym, unsigned keyflags) {
#define pressed(keysym) (GetAsyncKeyState(keysym) & 0x8000)
#define enabled(keysym) (GetKeyState(keysym))
#define shifted() (pressed(VK_LSHIFT) || pressed(VK_RSHIFT))
#define extended() (keyflags & (1 << 24))
switch(keysym) {
case VK_ESCAPE: return Keyboard::Keycode::Escape;
case VK_F1: return Keyboard::Keycode::F1;
case VK_F2: return Keyboard::Keycode::F2;
case VK_F3: return Keyboard::Keycode::F3;
case VK_F4: return Keyboard::Keycode::F4;
case VK_F5: return Keyboard::Keycode::F5;
case VK_F6: return Keyboard::Keycode::F6;
case VK_F7: return Keyboard::Keycode::F7;
case VK_F8: return Keyboard::Keycode::F8;
case VK_F9: return Keyboard::Keycode::F9;
//Keyboard::Keycode::F10 (should be captured under VK_MENU from WM_SYSKEY(UP,DOWN); but this is not working...)
case VK_F11: return Keyboard::Keycode::F11;
case VK_F12: return Keyboard::Keycode::F12;
//Keyboard::Keycode::PrintScreen
//Keyboard::Keycode::SysRq
case VK_SCROLL: return Keyboard::Keycode::ScrollLock;
case VK_PAUSE: return Keyboard::Keycode::Pause;
//Keyboard::Keycode::Break
case VK_INSERT: return extended() ? Keyboard::Keycode::Insert : Keyboard::Keycode::KeypadInsert;
case VK_DELETE: return extended() ? Keyboard::Keycode::Delete : Keyboard::Keycode::KeypadDelete;
case VK_HOME: return extended() ? Keyboard::Keycode::Home : Keyboard::Keycode::KeypadHome;
case VK_END: return extended() ? Keyboard::Keycode::End : Keyboard::Keycode::KeypadEnd;
case VK_PRIOR: return extended() ? Keyboard::Keycode::PageUp : Keyboard::Keycode::KeypadPageUp;
case VK_NEXT: return extended() ? Keyboard::Keycode::PageDown : Keyboard::Keycode::KeypadPageDown;
case VK_UP: return extended() ? Keyboard::Keycode::Up : Keyboard::Keycode::KeypadUp;
case VK_DOWN: return extended() ? Keyboard::Keycode::Down : Keyboard::Keycode::KeypadDown;
case VK_LEFT: return extended() ? Keyboard::Keycode::Left : Keyboard::Keycode::KeypadLeft;
case VK_RIGHT: return extended() ? Keyboard::Keycode::Right : Keyboard::Keycode::KeypadRight;
case VK_OEM_3: return !shifted() ? Keyboard::Keycode::Grave : Keyboard::Keycode::Tilde;
case '1': return !shifted() ? Keyboard::Keycode::Number1 : Keyboard::Keycode::Exclamation;
case '2': return !shifted() ? Keyboard::Keycode::Number2 : Keyboard::Keycode::At;
case '3': return !shifted() ? Keyboard::Keycode::Number3 : Keyboard::Keycode::Pound;
case '4': return !shifted() ? Keyboard::Keycode::Number4 : Keyboard::Keycode::Dollar;
case '5': return !shifted() ? Keyboard::Keycode::Number5 : Keyboard::Keycode::Percent;
case '6': return !shifted() ? Keyboard::Keycode::Number6 : Keyboard::Keycode::Power;
case '7': return !shifted() ? Keyboard::Keycode::Number7 : Keyboard::Keycode::Ampersand;
case '8': return !shifted() ? Keyboard::Keycode::Number8 : Keyboard::Keycode::Asterisk;
case '9': return !shifted() ? Keyboard::Keycode::Number9 : Keyboard::Keycode::ParenthesisLeft;
case '0': return !shifted() ? Keyboard::Keycode::Number0 : Keyboard::Keycode::ParenthesisRight;
case VK_OEM_MINUS: return !shifted() ? Keyboard::Keycode::Minus : Keyboard::Keycode::Underscore;
case VK_OEM_PLUS: return !shifted() ? Keyboard::Keycode::Equal : Keyboard::Keycode::Plus;
case VK_BACK: return Keyboard::Keycode::Backspace;
case VK_OEM_4: return !shifted() ? Keyboard::Keycode::BracketLeft : Keyboard::Keycode::BraceLeft;
case VK_OEM_6: return !shifted() ? Keyboard::Keycode::BracketRight : Keyboard::Keycode::BraceRight;
case VK_OEM_5: return !shifted() ? Keyboard::Keycode::Backslash : Keyboard::Keycode::Pipe;
case VK_OEM_1: return !shifted() ? Keyboard::Keycode::Semicolon : Keyboard::Keycode::Colon;
case VK_OEM_7: return !shifted() ? Keyboard::Keycode::Apostrophe : Keyboard::Keycode::Quote;
case VK_OEM_COMMA: return !shifted() ? Keyboard::Keycode::Comma : Keyboard::Keycode::CaretLeft;
case VK_OEM_PERIOD: return !shifted() ? Keyboard::Keycode::Period : Keyboard::Keycode::CaretRight;
case VK_OEM_2: return !shifted() ? Keyboard::Keycode::Slash : Keyboard::Keycode::Question;
case VK_TAB: return Keyboard::Keycode::Tab;
case VK_CAPITAL: return Keyboard::Keycode::CapsLock;
case VK_RETURN: return !extended() ? Keyboard::Keycode::Return : Keyboard::Keycode::Enter;
case VK_SHIFT: return !pressed(VK_RSHIFT) ? Keyboard::Keycode::ShiftLeft : Keyboard::Keycode::ShiftRight;
case VK_CONTROL: return !pressed(VK_RCONTROL) ? Keyboard::Keycode::ControlLeft : Keyboard::Keycode::ControlRight;
case VK_LWIN: return Keyboard::Keycode::SuperLeft;
case VK_RWIN: return Keyboard::Keycode::SuperRight;
case VK_MENU:
if(keyflags & (1 << 24)) return Keyboard::Keycode::AltRight;
return Keyboard::Keycode::AltLeft;
case VK_SPACE: return Keyboard::Keycode::Space;
case VK_APPS: return Keyboard::Keycode::Menu;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M':
case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
if(enabled(VK_CAPITAL)) {
if(shifted()) {
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::a + keysym - 'A');
} else {
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::A + keysym - 'A');
}
} else {
if(shifted()) {
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::A + keysym - 'A');
} else {
return (Keyboard::Keycode)((unsigned)Keyboard::Keycode::a + keysym - 'A');
}
}
break;
case VK_NUMLOCK: return Keyboard::Keycode::NumLock;
case VK_DIVIDE: return Keyboard::Keycode::Divide;
case VK_MULTIPLY: return Keyboard::Keycode::Multiply;
case VK_SUBTRACT: return Keyboard::Keycode::Subtract;
case VK_ADD: return Keyboard::Keycode::Add;
case VK_DECIMAL: return Keyboard::Keycode::Point;
case VK_NUMPAD1: return Keyboard::Keycode::Keypad1;
case VK_NUMPAD2: return Keyboard::Keycode::Keypad2;
case VK_NUMPAD3: return Keyboard::Keycode::Keypad3;
case VK_NUMPAD4: return Keyboard::Keycode::Keypad4;
case VK_NUMPAD5: return Keyboard::Keycode::Keypad5;
case VK_NUMPAD6: return Keyboard::Keycode::Keypad6;
case VK_NUMPAD7: return Keyboard::Keycode::Keypad7;
case VK_NUMPAD8: return Keyboard::Keycode::Keypad8;
case VK_NUMPAD9: return Keyboard::Keycode::Keypad9;
case VK_NUMPAD0: return Keyboard::Keycode::Keypad0;
case VK_CLEAR: return Keyboard::Keycode::KeypadCenter;
}
return Keyboard::Keycode::None;
#undef pressed
#undef enabled
#undef shifted
#undef extended
}