2015-06-12 13:14:38 +00:00
|
|
|
namespace hiro {
|
2013-03-15 13:11:33 +00:00
|
|
|
|
2012-01-15 08:29:57 +00:00
|
|
|
static const unsigned Windows2000 = 0x0500;
|
|
|
|
static const unsigned WindowsXP = 0x0501;
|
|
|
|
static const unsigned WindowsVista = 0x0600;
|
|
|
|
static const unsigned Windows7 = 0x0601;
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
static auto OsVersion() -> unsigned {
|
2013-05-02 11:25:45 +00:00
|
|
|
OSVERSIONINFO versionInfo = {0};
|
2012-01-15 08:29:57 +00:00
|
|
|
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
GetVersionEx(&versionInfo);
|
|
|
|
return (versionInfo.dwMajorVersion << 8) + (versionInfo.dwMajorVersion << 0);
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
static auto CreateBitmap(const image& image) -> HBITMAP {
|
2012-01-15 08:29:57 +00:00
|
|
|
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;
|
2013-05-02 11:25:45 +00:00
|
|
|
void* bits = nullptr;
|
2012-01-15 08:29:57 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
static auto CreateRGB(const Color& color) -> COLORREF {
|
|
|
|
return RGB(color.red(), color.green(), color.blue());
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto DropPaths(WPARAM wparam) -> lstring {
|
2013-07-29 09:42:45 +00:00
|
|
|
auto dropList = HDROP(wparam);
|
|
|
|
auto fileCount = DragQueryFile(dropList, ~0u, nullptr, 0);
|
|
|
|
|
|
|
|
lstring paths;
|
2015-06-12 13:14:38 +00:00
|
|
|
for(auto n : range(fileCount)) {
|
2013-07-29 09:42:45 +00:00
|
|
|
auto length = DragQueryFile(dropList, n, nullptr, 0);
|
|
|
|
auto buffer = new wchar_t[length + 1];
|
|
|
|
|
|
|
|
if(DragQueryFile(dropList, n, buffer, length + 1)) {
|
|
|
|
string path = (const char*)utf8_t(buffer);
|
|
|
|
path.transform("\\", "/");
|
2013-12-03 10:01:59 +00:00
|
|
|
if(directory::exists(path) && !path.endsWith("/")) path.append("/");
|
2013-07-29 09:42:45 +00:00
|
|
|
paths.append(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
static auto GetWindowZOrder(HWND hwnd) -> unsigned {
|
2013-11-28 10:29:01 +00:00
|
|
|
unsigned z = 0;
|
|
|
|
for(HWND next = hwnd; next != NULL; next = GetWindow(next, GW_HWNDPREV)) z++;
|
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
static auto ImageList_Append(HIMAGELIST imageList, const image& source, unsigned scale) -> void {
|
2013-11-28 10:32:53 +00:00
|
|
|
auto image = source;
|
|
|
|
if(image.empty()) {
|
|
|
|
image.allocate(scale, scale);
|
|
|
|
image.fill(GetSysColor(COLOR_WINDOW));
|
|
|
|
}
|
|
|
|
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
|
|
|
image.scale(scale, scale);
|
|
|
|
HBITMAP bitmap = CreateBitmap(image);
|
|
|
|
ImageList_Add(imageList, bitmap, NULL);
|
|
|
|
DeleteObject(bitmap);
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
//post message only if said message is not already pending in the queue
|
|
|
|
static auto PostMessageOnce(HWND hwnd, UINT id, WPARAM wparam, LPARAM lparam) -> void {
|
|
|
|
MSG msg;
|
|
|
|
if(!PeekMessage(&msg, hwnd, id, id, PM_NOREMOVE)) {
|
|
|
|
PostMessage(hwnd, id, wparam, lparam);
|
2012-01-15 08:29:57 +00:00
|
|
|
}
|
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
static auto ScrollEvent(HWND hwnd, WPARAM wparam) -> unsigned {
|
2013-11-28 10:29:01 +00:00
|
|
|
SCROLLINFO info;
|
|
|
|
memset(&info, 0, sizeof(SCROLLINFO));
|
|
|
|
info.cbSize = sizeof(SCROLLINFO);
|
|
|
|
info.fMask = SIF_ALL;
|
|
|
|
GetScrollInfo(hwnd, SB_CTL, &info);
|
|
|
|
|
|
|
|
switch(LOWORD(wparam)) {
|
|
|
|
case SB_LEFT: info.nPos = info.nMin; break;
|
|
|
|
case SB_RIGHT: info.nPos = info.nMax; break;
|
|
|
|
case SB_LINELEFT: info.nPos--; break;
|
|
|
|
case SB_LINERIGHT: info.nPos++; break;
|
|
|
|
case SB_PAGELEFT: info.nPos -= info.nMax >> 3; break;
|
|
|
|
case SB_PAGERIGHT: info.nPos += info.nMax >> 3; break;
|
|
|
|
case SB_THUMBTRACK: info.nPos = info.nTrackPos; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
info.fMask = SIF_POS;
|
|
|
|
SetScrollInfo(hwnd, SB_CTL, &info, TRUE);
|
|
|
|
|
|
|
|
//Windows may clamp position to scroller range
|
|
|
|
GetScrollInfo(hwnd, SB_CTL, &info);
|
|
|
|
return info.nPos;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
//separate because PopupMenu HWND does not contain GWLP_USERDATA pointing at Window needed for Shared_windowProc
|
|
|
|
static auto CALLBACK Menu_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
|
|
|
switch(msg) {
|
|
|
|
case WM_MENUCOMMAND: {
|
|
|
|
MENUITEMINFO mii{sizeof(MENUITEMINFO)};
|
|
|
|
mii.fMask = MIIM_DATA;
|
|
|
|
GetMenuItemInfo((HMENU)lparam, wparam, true, &mii);
|
|
|
|
|
|
|
|
auto object = (mObject*)mii.dwItemData;
|
|
|
|
if(!object) break;
|
|
|
|
|
|
|
|
#if defined(Hiro_MenuItem)
|
|
|
|
if(auto menuItem = dynamic_cast<mMenuItem*>(object)) {
|
|
|
|
return menuItem->self()->onActivate(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_MenuCheckItem)
|
|
|
|
if(auto menuCheckItem = dynamic_cast<mMenuCheckItem*>(object)) {
|
|
|
|
return menuCheckItem->self()->onToggle(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_MenuRadioItem)
|
|
|
|
if(auto menuRadioItem = dynamic_cast<mMenuRadioItem*>(object)) {
|
|
|
|
return menuRadioItem->self()->onActivate(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static auto CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
|
|
|
auto object = (mObject*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if(!object) return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
|
auto window = dynamic_cast<mWindow*>(object);
|
|
|
|
if(!window) window = object->parentWindow(true);
|
|
|
|
if(!window) return DefWindowProc(hwnd, msg, wparam, lparam);
|
2013-11-28 10:29:01 +00:00
|
|
|
|
|
|
|
bool process = true;
|
2015-06-12 13:14:38 +00:00
|
|
|
if(pWindow::modal && !pWindow::modal.find(window->self())) process = false;
|
|
|
|
if(Application::state.quit) process = false;
|
|
|
|
if(!process) return DefWindowProc(hwnd, msg, wparam, lparam);
|
2013-11-28 10:29:01 +00:00
|
|
|
|
|
|
|
switch(msg) {
|
2013-11-28 10:32:53 +00:00
|
|
|
case WM_CTLCOLORBTN:
|
Update to v094r09 release.
byuu says:
This will easily be the biggest diff in the history of higan. And not in
a good way.
* target-higan and target-loki have been blown away completely
* nall and ruby massively updated
* phoenix replaced with hiro (pretty near a total rewrite)
* target-higan restarted using hiro (just a window for now)
* all emulation cores updated to compile again
* installation changed to not require root privileges (installs locally)
For the foreseeable future (maybe even permanently?), the new higan UI
will only build under Linux/BSD with GTK+ 2.20+. Probably the most
likely route for Windows/OS X will be to try and figure out how to build
hiro/GTK on those platforms, as awful as that would be. The other
alternative would be to produce new UIs for those platforms ... which
would actually be a good opportunity to make something much more user
friendly.
Being that I just started on this a few hours ago, that means that for
at least a few weeks, don't expect to be able to actually play any
games. Right now, you can pretty much just compile the binary and that's
it. It's quite possible that some nall changes didn't produce
compilation errors, but will produce runtime errors. So until the UI can
actually load games, we won't know if anything is broken. But we should
mostly be okay. It was mostly just trim<1> -> trim changes, moving to
Hash::SHA256 (much cleaner), and patching some reckless memory copy
functions enough to compile.
Progress isn't going to be like it was before: I'm now dividing my time
much thinner between studying and other hobbies.
My aim this time is not to produce a binary for everyone to play games
on. Rather, it's to keep the emulator alive. I want to be able to apply
critical patches again. And I would also like the base of the emulator
to live on, for use in other emulator frontends that utilize higan.
2015-02-26 10:10:46 +00:00
|
|
|
case WM_CTLCOLOREDIT:
|
2013-11-28 10:32:53 +00:00
|
|
|
case WM_CTLCOLORSTATIC: {
|
2015-06-12 13:14:38 +00:00
|
|
|
auto object = (mObject*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
|
|
|
if(!object) break;
|
|
|
|
|
Update to v094r09 release.
byuu says:
This will easily be the biggest diff in the history of higan. And not in
a good way.
* target-higan and target-loki have been blown away completely
* nall and ruby massively updated
* phoenix replaced with hiro (pretty near a total rewrite)
* target-higan restarted using hiro (just a window for now)
* all emulation cores updated to compile again
* installation changed to not require root privileges (installs locally)
For the foreseeable future (maybe even permanently?), the new higan UI
will only build under Linux/BSD with GTK+ 2.20+. Probably the most
likely route for Windows/OS X will be to try and figure out how to build
hiro/GTK on those platforms, as awful as that would be. The other
alternative would be to produce new UIs for those platforms ... which
would actually be a good opportunity to make something much more user
friendly.
Being that I just started on this a few hours ago, that means that for
at least a few weeks, don't expect to be able to actually play any
games. Right now, you can pretty much just compile the binary and that's
it. It's quite possible that some nall changes didn't produce
compilation errors, but will produce runtime errors. So until the UI can
actually load games, we won't know if anything is broken. But we should
mostly be okay. It was mostly just trim<1> -> trim changes, moving to
Hash::SHA256 (much cleaner), and patching some reckless memory copy
functions enough to compile.
Progress isn't going to be like it was before: I'm now dividing my time
much thinner between studying and other hobbies.
My aim this time is not to produce a binary for everyone to play games
on. Rather, it's to keep the emulator alive. I want to be able to apply
critical patches again. And I would also like the base of the emulator
to live on, for use in other emulator frontends that utilize higan.
2015-02-26 10:10:46 +00:00
|
|
|
//allow custom colors for various widgets
|
|
|
|
//note that this happens always: default colors are black text on a white background, unless overridden
|
|
|
|
//this intentionally overrides the default behavior of Windows to paint disabled controls with the window background color
|
2015-06-12 13:14:38 +00:00
|
|
|
|
|
|
|
#if defined(Hiro_Window) && defined(Hiro_TabFrame)
|
|
|
|
if(!object->parentTabFrame(true) && window->self()->hbrush) {
|
|
|
|
SetBkColor((HDC)wparam, window->self()->hbrushColor);
|
|
|
|
return (LRESULT)window->self()->hbrush;
|
2013-12-21 10:45:58 +00:00
|
|
|
}
|
2015-06-12 13:14:38 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_HexEdit)
|
|
|
|
if(auto hexEdit = dynamic_cast<mHexEdit*>(object)) {
|
|
|
|
if(auto background = hexEdit->backgroundColor()) SetBkColor((HDC)wparam, CreateRGB(background));
|
|
|
|
if(auto foreground = hexEdit->foregroundColor()) SetTextColor((HDC)wparam, CreateRGB(foreground));
|
|
|
|
return (LRESULT)hexEdit->self()->backgroundBrush;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_LineEdit)
|
|
|
|
if(auto lineEdit = dynamic_cast<mLineEdit*>(object)) {
|
|
|
|
if(auto background = lineEdit->backgroundColor()) SetBkColor((HDC)wparam, CreateRGB(background));
|
|
|
|
if(auto foreground = lineEdit->foregroundColor()) SetTextColor((HDC)wparam, CreateRGB(foreground));
|
|
|
|
return (LRESULT)lineEdit->self()->backgroundBrush;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_TextEdit)
|
|
|
|
if(auto textEdit = dynamic_cast<mTextEdit*>(object)) {
|
|
|
|
if(auto background = textEdit->backgroundColor()) SetBkColor((HDC)wparam, CreateRGB(background));
|
|
|
|
if(auto foreground = textEdit->foregroundColor()) SetTextColor((HDC)wparam, CreateRGB(foreground));
|
|
|
|
return (LRESULT)textEdit->self()->backgroundBrush;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 10:32:53 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
case WM_DRAWITEM: {
|
2015-06-12 13:14:38 +00:00
|
|
|
auto drawItem = (LPDRAWITEMSTRUCT)lparam;
|
|
|
|
auto object = (mObject*)GetWindowLongPtr((HWND)drawItem->hwndItem, GWLP_USERDATA);
|
|
|
|
if(!object) break;
|
|
|
|
|
|
|
|
#if defined(Hiro_TabFrame)
|
|
|
|
if(auto tabFrame = dynamic_cast<mTabFrame*>(object)) {
|
|
|
|
return tabFrame->self()->onDrawItem(lparam), true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
case WM_MENUCOMMAND: {
|
|
|
|
return Menu_windowProc(hwnd, msg, wparam, lparam);
|
|
|
|
}
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
case WM_COMMAND: {
|
2015-06-12 13:14:38 +00:00
|
|
|
if(!lparam) break;
|
|
|
|
auto object = (mObject*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
|
|
|
if(!object) break;
|
|
|
|
|
|
|
|
#if defined(Hiro_Button)
|
|
|
|
if(auto button = dynamic_cast<mButton*>(object)) {
|
|
|
|
return button->self()->onActivate(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_CheckButton)
|
|
|
|
if(auto checkButton = dynamic_cast<mCheckButton*>(object)) {
|
|
|
|
return checkButton->self()->onToggle(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_CheckLabel)
|
|
|
|
if(auto checkLabel = dynamic_cast<mCheckLabel*>(object)) {
|
|
|
|
return checkLabel->self()->onToggle(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_ComboButton)
|
|
|
|
if(auto comboButton = dynamic_cast<mComboButton*>(object)) {
|
|
|
|
if(HIWORD(wparam) == CBN_SELCHANGE) {
|
|
|
|
return comboButton->self()->onChange(), false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_LineEdit)
|
|
|
|
if(auto lineEdit = dynamic_cast<mLineEdit*>(object)) {
|
|
|
|
if(HIWORD(wparam) == EN_CHANGE) {
|
|
|
|
return lineEdit->self()->onChange(), false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_RadioButton)
|
|
|
|
if(auto radioButton = dynamic_cast<mRadioButton*>(object)) {
|
|
|
|
return radioButton->self()->onActivate(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_RadioLabel)
|
|
|
|
if(auto radioLabel = dynamic_cast<mRadioLabel*>(object)) {
|
|
|
|
return radioLabel->self()->onActivate(), false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_TextEdit)
|
|
|
|
if(auto textEdit = dynamic_cast<mTextEdit*>(object)) {
|
|
|
|
if(HIWORD(wparam) == EN_CHANGE) {
|
|
|
|
return textEdit->self()->onChange(), false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_NOTIFY: {
|
2015-06-12 13:14:38 +00:00
|
|
|
auto header = (LPNMHDR)lparam;
|
|
|
|
auto object = (mObject*)GetWindowLongPtr((HWND)header->hwndFrom, GWLP_USERDATA);
|
|
|
|
if(!object) break;
|
|
|
|
|
|
|
|
#if defined(Hiro_ListView)
|
|
|
|
if(auto listView = dynamic_cast<mListView*>(object)) {
|
|
|
|
if(header->code == LVN_ITEMACTIVATE) {
|
|
|
|
listView->self()->onActivate(lparam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(header->code == LVN_ITEMCHANGED) {
|
|
|
|
listView->self()->onChange(lparam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(header->code == LVN_COLUMNCLICK) {
|
|
|
|
listView->self()->onSort(lparam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(header->code == NM_RCLICK) {
|
|
|
|
listView->self()->onContext(lparam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(header->code == NM_CUSTOMDRAW) {
|
|
|
|
return listView->self()->onCustomDraw(lparam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_TabFrame)
|
|
|
|
if(auto tabFrame = dynamic_cast<mTabFrame*>(object)) {
|
|
|
|
if(header->code == TCN_SELCHANGE) {
|
|
|
|
tabFrame->self()->onChange();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
#if defined(Hiro_ListView)
|
|
|
|
case AppMessage::ListView_onActivate: {
|
|
|
|
if(auto listView = (mListView*)lparam) listView->doActivate();
|
Update to v094 release.
byuu says:
This release adds support for game libraries, and substantially improves
Game Boy and Game Boy Color emulation with cycle-based renderers. Many
other changes are also present.
It's very important to note that this release now defaults to optimal
drivers rather than safe drivers. This is particularly important if you
do not have strong OpenGL 3.2 drivers. If performance is bad, go to
Settings -> Configuration -> Advanced, change the video driver, and
restart higan. In the rare case that you have trouble opening higan, you
can edit settings.bml directly and change the setting there. The Windows
safe driver is Direct3D, and the Linux safe driver is XShm.
Also note that although display emulation shaders are now supported,
they have not been included in this release as they are not ready yet.
The support has been built-in anyway, so that they can be tested by
everyone. Once refined, future releases of higan will come with built-in
shaders for each emulated system that simulates the unique display
characteristics of each.
Changelog (since v093):
- sfc: added SA-1 MDR support (fixes SD Gundam G-Next bug)
- sfc: remove random/ and config/, merge to system/ with better
randomization
- gb: improved color emulation palette contrast
- gbc: do not sort sprites by X-priority
- gbc: allow transparency on BG priority pixels
- gbc: VRAM DMA timing and register fixes
- gbc: block invalid VRAM DMA transfer source and target addresses
- gba: added LCD color emulation (without it, colors are grossly
over-saturated)
- gba: removed internal frame blending (use shaders to simulate motion
blur if desired)
- gba: added Game Boy Player support (adds joypad rumble support to
supported games)
- gba: SOUND_CTL_H is readable
- gb/gbc: PPU renderer is now cycle-based (major accuracy improvement)
- gb/gbc: OAM DMA runs in parallel with the CPU
- gb/gbc: only HRAM can be accessed during OAM DMA
- gb/gbc: fixed serialization of games with SRAM
- gb/gbc: disallow up+down or left+right at the same time
- gb/gbc: added weak hipass filter to remove DC bias
- gb/gbc: STAT OAM+Hblank IRQs only trigger during active display
- gb/gbc: fixed underflow in window clamping
- gb/gbc/gba: audio mixes internally at 2MHz now instead of 4MHz (does
not affect accuracy)
- gb/gbc/gba: audio volume reduced for consistency with other systems
- fc/sfc/gb/gbc/gba: cheat codes are now stored in universal, decrypted
format
- ethos: replaced file loader with a proper game library
- ethos: added display emulation shader support
- ethos: added color emulation option to video settings
- ethos: program icon upgraded from 48x48 to 512x512
- ethos: settings and tools windows now use tab frames (less wasted
screen space)
- ethos: default to optimal (video, audio, input) drivers instead of
safest drivers
- ethos: input mapping system completely rewritten to support
hotplugging and unique device mappings
- ruby: added fixes for OpenGL 3.2 on AMD graphics cards
- ruby: quark shaders now support user settings inside of manifest
- ruby: quark shaders can use integral textures (allows display
emulation shaders to work with raw colors)
- ruby: add joypad rumble support
- ruby: XInput (Xbox 360) controllers now support hotplugging
- ruby: added Linux udev joypad driver with hotplug support
- phoenix: fixed a rare null pointer dereference issue on Windows
- port: target -std=c++11 instead of -std=gnu++11 (do not rely on GNU
C++ extensions)
- port: added out-of-the-box compilation support for BSD/Clang 3.3+
- port: applied a few Debian upstream patches
- cheats: updated to mightymo's 2014-01-02 release; decrypted all Game
Genie codes
2014-01-20 08:55:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-12 13:14:38 +00:00
|
|
|
case AppMessage::ListView_onChange: {
|
|
|
|
if(auto listView = (mListView*)lparam) listView->doChange();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
case WM_HSCROLL:
|
|
|
|
case WM_VSCROLL: {
|
2015-06-12 13:14:38 +00:00
|
|
|
if(!lparam) break;
|
|
|
|
auto object = (mObject*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
|
|
|
if(!object) break;
|
|
|
|
|
|
|
|
#if defined(Hiro_HorizontalScroller)
|
|
|
|
if(auto horizontalScroller = dynamic_cast<mHorizontalScroller*>(object)) {
|
|
|
|
return horizontalScroller->self()->onChange(wparam), true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_HorizontalSlider)
|
|
|
|
if(auto horizontalSlider = dynamic_cast<mHorizontalSlider*>(object)) {
|
|
|
|
return horizontalSlider->self()->onChange(), true;
|
2013-11-28 10:29:01 +00:00
|
|
|
}
|
2015-06-12 13:14:38 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_VerticalScroller)
|
|
|
|
if(auto verticalScroller = dynamic_cast<mVerticalScroller*>(object)) {
|
|
|
|
return verticalScroller->self()->onChange(wparam), true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(Hiro_VerticalSlider)
|
|
|
|
if(auto verticalSlider = dynamic_cast<mVerticalSlider*>(object)) {
|
|
|
|
return verticalSlider->self()->onChange(), true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 10:29:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return windowProc(hwnd, msg, wparam, lparam);
|
|
|
|
}
|
|
|
|
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|