2011-09-05 03:48:23 +00:00
|
|
|
#include "platform.hpp"
|
2012-01-15 08:29:57 +00:00
|
|
|
#include "utility.cpp"
|
2012-01-26 06:50:09 +00:00
|
|
|
#include "settings.cpp"
|
2012-01-15 08:29:57 +00:00
|
|
|
|
|
|
|
#include "desktop.cpp"
|
|
|
|
#include "keyboard.cpp"
|
|
|
|
#include "mouse.cpp"
|
|
|
|
#include "dialog-window.cpp"
|
|
|
|
#include "message-window.cpp"
|
2011-02-24 09:25:20 +00:00
|
|
|
|
|
|
|
#include "object.cpp"
|
|
|
|
#include "font.cpp"
|
2011-06-05 03:45:04 +00:00
|
|
|
#include "timer.cpp"
|
2011-02-24 09:25:20 +00:00
|
|
|
#include "window.cpp"
|
|
|
|
|
|
|
|
#include "action/action.cpp"
|
|
|
|
#include "action/menu.cpp"
|
2011-02-27 09:05:10 +00:00
|
|
|
#include "action/separator.cpp"
|
|
|
|
#include "action/item.cpp"
|
|
|
|
#include "action/check-item.cpp"
|
|
|
|
#include "action/radio-item.cpp"
|
2011-02-24 09:25:20 +00:00
|
|
|
|
|
|
|
#include "widget/widget.cpp"
|
|
|
|
#include "widget/button.cpp"
|
2011-03-26 11:31:07 +00:00
|
|
|
#include "widget/canvas.cpp"
|
2011-02-24 09:25:20 +00:00
|
|
|
#include "widget/check-box.cpp"
|
|
|
|
#include "widget/combo-box.cpp"
|
|
|
|
#include "widget/hex-edit.cpp"
|
2011-08-06 14:03:52 +00:00
|
|
|
#include "widget/horizontal-scroll-bar.cpp"
|
2011-02-24 09:25:20 +00:00
|
|
|
#include "widget/horizontal-slider.cpp"
|
|
|
|
#include "widget/label.cpp"
|
|
|
|
#include "widget/line-edit.cpp"
|
|
|
|
#include "widget/list-view.cpp"
|
|
|
|
#include "widget/progress-bar.cpp"
|
|
|
|
#include "widget/radio-box.cpp"
|
|
|
|
#include "widget/text-edit.cpp"
|
2011-08-06 14:03:52 +00:00
|
|
|
#include "widget/vertical-scroll-bar.cpp"
|
2011-02-24 09:25:20 +00:00
|
|
|
#include "widget/vertical-slider.cpp"
|
|
|
|
#include "widget/viewport.cpp"
|
|
|
|
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
static bool OS_keyboardProc(HWND, UINT, WPARAM, LPARAM);
|
2011-09-09 04:16:25 +00:00
|
|
|
static void OS_processDialogMessage(MSG&);
|
2011-02-24 09:25:20 +00:00
|
|
|
static LRESULT CALLBACK OS_windowProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
|
|
|
|
void pOS::main() {
|
|
|
|
MSG msg;
|
|
|
|
while(GetMessage(&msg, 0, 0, 0)) {
|
2011-09-09 04:16:25 +00:00
|
|
|
OS_processDialogMessage(msg);
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-27 09:05:10 +00:00
|
|
|
bool pOS::pendingEvents() {
|
2011-02-24 09:25:20 +00:00
|
|
|
MSG msg;
|
|
|
|
return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
|
|
|
|
}
|
|
|
|
|
2011-02-27 09:05:10 +00:00
|
|
|
void pOS::processEvents() {
|
|
|
|
while(pendingEvents()) {
|
2011-02-24 09:25:20 +00:00
|
|
|
MSG msg;
|
|
|
|
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
2011-09-09 04:16:25 +00:00
|
|
|
OS_processDialogMessage(msg);
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-09 04:16:25 +00:00
|
|
|
void OS_processDialogMessage(MSG &msg) {
|
2012-01-15 08:29:57 +00:00
|
|
|
if(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP
|
|
|
|
|| msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) {
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
if(OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam)) {
|
|
|
|
DispatchMessage(&msg);
|
|
|
|
return;
|
|
|
|
}
|
2011-09-09 04:16:25 +00:00
|
|
|
}
|
|
|
|
|
2011-11-04 11:57:54 +00:00
|
|
|
if(!IsDialogMessage(GetForegroundWindow(), &msg)) {
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessage(&msg);
|
2011-09-09 04:16:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-24 09:25:20 +00:00
|
|
|
void pOS::quit() {
|
2012-01-15 08:29:57 +00:00
|
|
|
osQuit = true;
|
2011-02-24 09:25:20 +00:00
|
|
|
PostQuitMessage(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pOS::initialize() {
|
|
|
|
CoInitialize(0);
|
|
|
|
InitCommonControls();
|
|
|
|
|
|
|
|
WNDCLASS wc;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
2011-08-06 14:03:52 +00:00
|
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
2011-02-24 09:25:20 +00:00
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(2));
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = OS_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_window";
|
|
|
|
wc.lpszMenuName = 0;
|
2011-02-27 09:11:01 +00:00
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
2011-02-24 09:25:20 +00:00
|
|
|
RegisterClass(&wc);
|
|
|
|
|
2011-03-26 11:31:07 +00:00
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
2011-11-04 11:57:54 +00:00
|
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
2011-03-26 11:31:07 +00:00
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Canvas_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_canvas";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
2011-02-24 09:25:20 +00:00
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
2011-08-06 14:03:52 +00:00
|
|
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
2011-02-24 09:25:20 +00:00
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Label_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_label";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
|
|
|
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
|
|
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wc.hInstance = GetModuleHandle(0);
|
|
|
|
wc.lpfnWndProc = Viewport_windowProc;
|
|
|
|
wc.lpszClassName = L"phoenix_viewport";
|
|
|
|
wc.lpszMenuName = 0;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
RegisterClass(&wc);
|
2012-01-15 08:29:57 +00:00
|
|
|
|
2012-01-26 06:50:09 +00:00
|
|
|
settings = new Settings;
|
2012-01-15 08:29:57 +00:00
|
|
|
pKeyboard::initialize();
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
static bool OS_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
2012-01-15 08:29:57 +00:00
|
|
|
if(msg != WM_KEYDOWN && msg != WM_SYSKEYDOWN && msg != WM_KEYUP && msg != WM_SYSKEYUP) return false;
|
|
|
|
|
|
|
|
GUITHREADINFO info;
|
|
|
|
memset(&info, 0, sizeof(GUITHREADINFO));
|
|
|
|
info.cbSize = sizeof(GUITHREADINFO);
|
|
|
|
GetGUIThreadInfo(GetCurrentThreadId(), &info);
|
|
|
|
Object *object = (Object*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
|
|
|
|
if(object == nullptr) return false;
|
|
|
|
|
|
|
|
if(dynamic_cast<Window*>(object)) {
|
|
|
|
Window &window = (Window&)*object;
|
Update to v088r11 release.
byuu says:
Changelog:
- phoenix has added Window::setModal(bool modal = true);
- file dialog is now modal. This allows emulation cores to request data
and get it immediately before continuing the loading process
- save data is hooked up for most systems, still need to handle
subsystem slot saves (Sufami Turbo, basically.)
- toggle fullscreen key binding added (Alt+Enter for now. I think F11 is
probably better though, Enter is often mapped to game start button.)
- video scaling is in (center, scale, stretch), works the same in
windowed and fullscreen mode (stretch hides resize window option), all
in the settings menu now
- enough structure to map all saved paths for the browser and to load
BS-X slotted carts, BS-X carts, single Sufami Turbo carts
Caveats / Missing:
- Super Game Boy input doesn't work yet (due to change in callback
binding)
- doesn't load secondary Sufami Turbo slot yet
- BS-X BIOS isn't show the data pack games to load for some reason (ugh,
I hate the shit out of debugging BS-X stuff ...)
- need mute audio, sync audio+video toggle, save/load state menu and
quick keys, XML mapping information window
- need cheat editor and cheat database
- need state manager
- need to sort subsystems below main systems in load menu (basically
just see if media.slot.size() > 0)
- need video shaders (will probably leave off filters for the time being
... due to that 24/30-bit thing)
- need video adjustments (contrast etc, overscan masks)
- need audio adjustments (frequency, latency, resampler, volume,
per-system frequency)
- need driver selection and input focus policy (driver crash detection
would be nice too)
- need NSS DIP switch settings (that one will be really fun)
- need to save and load window geometry settings
- need to hook up controller selection (won't be fun), create a map to
hide controllers with no inputs to reassign
2012-05-03 12:36:47 +00:00
|
|
|
if(pWindow::modal.size() > 0 && !pWindow::modal.find(&window.p)) return false;
|
2012-01-15 08:29:57 +00:00
|
|
|
Keyboard::Keycode keysym = Keysym(wparam, lparam);
|
|
|
|
if(keysym != Keyboard::Keycode::None) {
|
|
|
|
if((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && window.onKeyPress) window.onKeyPress(keysym);
|
|
|
|
if((msg == WM_KEYUP || msg == WM_SYSKEYUP) && window.onKeyRelease) window.onKeyRelease(keysym);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-24 09:25:20 +00:00
|
|
|
if(msg == WM_KEYDOWN) {
|
|
|
|
if(dynamic_cast<ListView*>(object)) {
|
|
|
|
ListView &listView = (ListView&)*object;
|
|
|
|
if(wparam == VK_RETURN) {
|
|
|
|
if(listView.onActivate) listView.onActivate();
|
|
|
|
}
|
|
|
|
} else if(dynamic_cast<LineEdit*>(object)) {
|
|
|
|
LineEdit &lineEdit = (LineEdit&)*object;
|
|
|
|
if(wparam == VK_RETURN) {
|
|
|
|
if(lineEdit.onActivate) lineEdit.onActivate();
|
|
|
|
}
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
} else if(dynamic_cast<TextEdit*>(object)) {
|
|
|
|
TextEdit &textEdit = (TextEdit&)*object;
|
|
|
|
if(wparam == 'A' && GetKeyState(VK_CONTROL) < 0) {
|
|
|
|
//Ctrl+A = select all text
|
|
|
|
//note: this is not a standard accelerator on Windows
|
|
|
|
Edit_SetSel(textEdit.p.hwnd, 0, ~0);
|
|
|
|
return true;
|
|
|
|
} else if(wparam == 'V' && GetKeyState(VK_CONTROL) < 0) {
|
|
|
|
//Ctrl+V = paste text
|
|
|
|
//note: this formats Unix (LF) and OS9 (CR) line-endings to Windows (CR+LF) line-endings
|
|
|
|
//this is necessary as the EDIT control only supports Windows line-endings
|
|
|
|
OpenClipboard(hwnd);
|
|
|
|
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
|
|
|
|
if(handle) {
|
|
|
|
wchar_t *text = (wchar_t*)GlobalLock(handle);
|
|
|
|
if(text) {
|
|
|
|
string data = (const char*)utf8_t(text);
|
|
|
|
data.replace("\r\n", "\n");
|
|
|
|
data.replace("\r", "\n");
|
|
|
|
data.replace("\n", "\r\n");
|
|
|
|
GlobalUnlock(handle);
|
|
|
|
utf16_t output(data);
|
|
|
|
HGLOBAL resource = GlobalAlloc(GMEM_MOVEABLE, (wcslen(output) + 1) * sizeof(wchar_t));
|
|
|
|
if(resource) {
|
|
|
|
wchar_t *write = (wchar_t*)GlobalLock(resource);
|
|
|
|
if(write) {
|
|
|
|
wcscpy(write, output);
|
|
|
|
GlobalUnlock(write);
|
|
|
|
if(SetClipboardData(CF_UNICODETEXT, resource) == FALSE) {
|
|
|
|
GlobalFree(resource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CloseClipboard();
|
|
|
|
return false;
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
Update to v084r05 release.
(note: before the post announcing this release, there had been
a discussion of a performance optimisation that made the Super Scope
emulation a lot faster, but caused problems for the Justifier perpheral)
byuu says:
Spent a good two hours trying things to no avail.
I was trying to allow the CPU to run ahead, and sync on accesses to
$4016/4017/4201/4213, but that doesn't work because the controllers have
access to strobe IObit at will.
The codebase is really starting to get difficult to work with. I am
guessing because the days of massive development are long over, and the
code is starting to age.
Jonas' fix works 98% of the time, but there's still a few missed shots
here and there. So that's not going to work either.
So ... I give up. I've disabled the speed hack, so that it works 100% of
the time.
Did the same for the Super Scope: it may not have the same problem, but
I like consistency and don't feel like taking the chance.
This doesn't affect the mouse, since the mouse does not latch the
counters to indicate its X/Y position.
Speed hit is 92->82fps (accuracy profile), but only for Super Scope and
Justifier games.
But ... at least it works now. Slow and working is better than fast and
broken.
I appreciate the help in researching the issue, Jonas and krom.
Also pulled in phoenix/Makefile, which simplifies ui/Makefile.
Linux port defaults to GTK+ now. I can't get QGtkStyle to look good on
Debian.
2011-12-18 03:19:45 +00:00
|
|
|
|
|
|
|
return false;
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT CALLBACK OS_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
|
|
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if(!object || !dynamic_cast<Window*>(object)) return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
|
Window &window = (Window&)*object;
|
|
|
|
|
Update to v088r11 release.
byuu says:
Changelog:
- phoenix has added Window::setModal(bool modal = true);
- file dialog is now modal. This allows emulation cores to request data
and get it immediately before continuing the loading process
- save data is hooked up for most systems, still need to handle
subsystem slot saves (Sufami Turbo, basically.)
- toggle fullscreen key binding added (Alt+Enter for now. I think F11 is
probably better though, Enter is often mapped to game start button.)
- video scaling is in (center, scale, stretch), works the same in
windowed and fullscreen mode (stretch hides resize window option), all
in the settings menu now
- enough structure to map all saved paths for the browser and to load
BS-X slotted carts, BS-X carts, single Sufami Turbo carts
Caveats / Missing:
- Super Game Boy input doesn't work yet (due to change in callback
binding)
- doesn't load secondary Sufami Turbo slot yet
- BS-X BIOS isn't show the data pack games to load for some reason (ugh,
I hate the shit out of debugging BS-X stuff ...)
- need mute audio, sync audio+video toggle, save/load state menu and
quick keys, XML mapping information window
- need cheat editor and cheat database
- need state manager
- need to sort subsystems below main systems in load menu (basically
just see if media.slot.size() > 0)
- need video shaders (will probably leave off filters for the time being
... due to that 24/30-bit thing)
- need video adjustments (contrast etc, overscan masks)
- need audio adjustments (frequency, latency, resampler, volume,
per-system frequency)
- need driver selection and input focus policy (driver crash detection
would be nice too)
- need NSS DIP switch settings (that one will be really fun)
- need to save and load window geometry settings
- need to hook up controller selection (won't be fun), create a map to
hide controllers with no inputs to reassign
2012-05-03 12:36:47 +00:00
|
|
|
bool process = true;
|
|
|
|
if(pWindow::modal.size() > 0 && !pWindow::modal.find(&window.p)) process = false;
|
|
|
|
if(osQuit) process = false;
|
|
|
|
|
|
|
|
if(process) switch(msg) {
|
2011-02-24 09:25:20 +00:00
|
|
|
case WM_CLOSE: {
|
2011-09-05 03:48:23 +00:00
|
|
|
window.state.ignore = false;
|
2011-02-24 09:25:20 +00:00
|
|
|
if(window.onClose) window.onClose();
|
Update to v088r11 release.
byuu says:
Changelog:
- phoenix has added Window::setModal(bool modal = true);
- file dialog is now modal. This allows emulation cores to request data
and get it immediately before continuing the loading process
- save data is hooked up for most systems, still need to handle
subsystem slot saves (Sufami Turbo, basically.)
- toggle fullscreen key binding added (Alt+Enter for now. I think F11 is
probably better though, Enter is often mapped to game start button.)
- video scaling is in (center, scale, stretch), works the same in
windowed and fullscreen mode (stretch hides resize window option), all
in the settings menu now
- enough structure to map all saved paths for the browser and to load
BS-X slotted carts, BS-X carts, single Sufami Turbo carts
Caveats / Missing:
- Super Game Boy input doesn't work yet (due to change in callback
binding)
- doesn't load secondary Sufami Turbo slot yet
- BS-X BIOS isn't show the data pack games to load for some reason (ugh,
I hate the shit out of debugging BS-X stuff ...)
- need mute audio, sync audio+video toggle, save/load state menu and
quick keys, XML mapping information window
- need cheat editor and cheat database
- need state manager
- need to sort subsystems below main systems in load menu (basically
just see if media.slot.size() > 0)
- need video shaders (will probably leave off filters for the time being
... due to that 24/30-bit thing)
- need video adjustments (contrast etc, overscan masks)
- need audio adjustments (frequency, latency, resampler, volume,
per-system frequency)
- need driver selection and input focus policy (driver crash detection
would be nice too)
- need NSS DIP switch settings (that one will be really fun)
- need to save and load window geometry settings
- need to hook up controller selection (won't be fun), create a map to
hide controllers with no inputs to reassign
2012-05-03 12:36:47 +00:00
|
|
|
if(window.state.ignore == false) {
|
|
|
|
window.setVisible(false);
|
|
|
|
window.setModal(false);
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_MOVE: {
|
|
|
|
if(window.p.locked) break;
|
|
|
|
|
|
|
|
Geometry geometry = window.geometry();
|
|
|
|
window.state.geometry.x = geometry.x;
|
|
|
|
window.state.geometry.y = geometry.y;
|
|
|
|
|
|
|
|
if(window.onMove) window.onMove();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_SIZE: {
|
|
|
|
if(window.p.locked) break;
|
|
|
|
SetWindowPos(window.p.hstatus, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
|
|
|
|
|
|
Geometry geometry = window.geometry();
|
|
|
|
window.state.geometry.width = geometry.width;
|
|
|
|
window.state.geometry.height = geometry.height;
|
|
|
|
|
2011-09-27 11:55:02 +00:00
|
|
|
for(auto &layout : window.state.layout) {
|
2011-02-24 09:25:20 +00:00
|
|
|
Geometry geom = window.geometry();
|
|
|
|
geom.x = geom.y = 0;
|
|
|
|
layout.setGeometry(geom);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(window.onSize) window.onSize();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_GETMINMAXINFO: {
|
|
|
|
MINMAXINFO *mmi = (MINMAXINFO*)lparam;
|
|
|
|
//mmi->ptMinTrackSize.x = 256 + window.p.frameMargin().width;
|
|
|
|
//mmi->ptMinTrackSize.y = 256 + window.p.frameMargin().height;
|
|
|
|
//return TRUE;
|
2011-10-28 09:51:43 +00:00
|
|
|
break;
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case WM_ERASEBKGND: {
|
|
|
|
if(window.p.brush == 0) break;
|
|
|
|
RECT rc;
|
|
|
|
GetClientRect(window.p.hwnd, &rc);
|
|
|
|
PAINTSTRUCT ps;
|
|
|
|
BeginPaint(window.p.hwnd, &ps);
|
|
|
|
FillRect(ps.hdc, &rc, window.p.brush);
|
|
|
|
EndPaint(window.p.hwnd, &ps);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
case WM_CTLCOLORBTN:
|
|
|
|
case WM_CTLCOLORSTATIC: {
|
|
|
|
Object *object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
|
|
|
if(object && window.p.brush) {
|
|
|
|
HDC hdc = (HDC)wparam;
|
|
|
|
SetBkColor((HDC)wparam, window.p.brushColor);
|
|
|
|
return (INT_PTR)window.p.brush;
|
|
|
|
}
|
2011-10-28 09:51:43 +00:00
|
|
|
break;
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case WM_COMMAND: {
|
|
|
|
unsigned id = LOWORD(wparam);
|
|
|
|
HWND control = GetDlgItem(window.p.hwnd, id);
|
|
|
|
if(control == 0) {
|
|
|
|
pObject *object = (pObject*)pObject::find(id);
|
|
|
|
if(!object) break;
|
2011-02-27 09:05:10 +00:00
|
|
|
if(dynamic_cast<pItem*>(object)) {
|
|
|
|
Item &item = ((pItem*)object)->item;
|
2011-12-12 10:59:53 +00:00
|
|
|
if(item.onActivate) item.onActivate();
|
2011-02-27 09:05:10 +00:00
|
|
|
} else if(dynamic_cast<pCheckItem*>(object)) {
|
|
|
|
CheckItem &checkItem = ((pCheckItem*)object)->checkItem;
|
|
|
|
checkItem.setChecked(!checkItem.state.checked);
|
2011-12-12 10:59:53 +00:00
|
|
|
if(checkItem.onToggle) checkItem.onToggle();
|
2011-02-27 09:05:10 +00:00
|
|
|
} else if(dynamic_cast<pRadioItem*>(object)) {
|
|
|
|
RadioItem &radioItem = ((pRadioItem*)object)->radioItem;
|
|
|
|
if(radioItem.state.checked == false) {
|
|
|
|
radioItem.setChecked();
|
2011-12-12 10:59:53 +00:00
|
|
|
if(radioItem.onActivate) radioItem.onActivate();
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Object *object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
|
|
|
|
if(!object) break;
|
|
|
|
if(dynamic_cast<Button*>(object)) {
|
|
|
|
Button &button = (Button&)*object;
|
2011-12-12 10:59:53 +00:00
|
|
|
if(button.onActivate) button.onActivate();
|
2011-02-24 09:25:20 +00:00
|
|
|
} else if(dynamic_cast<CheckBox*>(object)) {
|
|
|
|
CheckBox &checkBox = (CheckBox&)*object;
|
|
|
|
checkBox.setChecked(!checkBox.state.checked);
|
2011-12-12 10:59:53 +00:00
|
|
|
if(checkBox.onToggle) checkBox.onToggle();
|
2011-02-24 09:25:20 +00:00
|
|
|
} else if(dynamic_cast<ComboBox*>(object)) {
|
|
|
|
ComboBox &comboBox = (ComboBox&)*object;
|
|
|
|
if(HIWORD(wparam) == CBN_SELCHANGE) {
|
|
|
|
if(comboBox.state.selection != comboBox.selection()) {
|
|
|
|
comboBox.state.selection = comboBox.selection();
|
|
|
|
if(comboBox.onChange) comboBox.onChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if(dynamic_cast<LineEdit*>(object)) {
|
|
|
|
LineEdit &lineEdit = (LineEdit&)*object;
|
|
|
|
if(HIWORD(wparam) == EN_CHANGE) {
|
|
|
|
if(lineEdit.p.locked == false && lineEdit.onChange) lineEdit.onChange();
|
|
|
|
}
|
|
|
|
} else if(dynamic_cast<RadioBox*>(object)) {
|
|
|
|
RadioBox &radioBox = (RadioBox&)*object;
|
|
|
|
if(radioBox.state.checked == false) {
|
|
|
|
radioBox.setChecked();
|
2011-12-12 10:59:53 +00:00
|
|
|
if(radioBox.onActivate) radioBox.onActivate();
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
} else if(dynamic_cast<TextEdit*>(object)) {
|
|
|
|
TextEdit &textEdit = (TextEdit&)*object;
|
|
|
|
if(HIWORD(wparam) == EN_CHANGE) {
|
|
|
|
if(textEdit.p.locked == false && textEdit.onChange) textEdit.onChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-10-28 09:51:43 +00:00
|
|
|
break;
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case WM_NOTIFY: {
|
|
|
|
unsigned id = LOWORD(wparam);
|
|
|
|
HWND control = GetDlgItem(window.p.hwnd, id);
|
|
|
|
if(control == 0) break;
|
|
|
|
Object *object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
|
|
|
|
if(object == 0) break;
|
|
|
|
if(dynamic_cast<ListView*>(object)) {
|
|
|
|
ListView &listView = (ListView&)*object;
|
|
|
|
LPNMHDR nmhdr = (LPNMHDR)lparam;
|
|
|
|
LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam;
|
|
|
|
|
|
|
|
if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) {
|
|
|
|
unsigned imagemask = ((nmlistview->uNewState & LVIS_STATEIMAGEMASK) >> 12) - 1;
|
|
|
|
if(imagemask == 0 || imagemask == 1) {
|
2011-12-12 10:59:53 +00:00
|
|
|
if(listView.p.locked == false && listView.onToggle) listView.onToggle(nmlistview->iItem);
|
2011-02-24 09:25:20 +00:00
|
|
|
} else if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
|
|
|
|
listView.p.lostFocus = true;
|
2011-10-24 11:35:34 +00:00
|
|
|
} else if(!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) {
|
|
|
|
listView.p.lostFocus = false;
|
|
|
|
listView.state.selected = true;
|
|
|
|
listView.state.selection = listView.selection();
|
|
|
|
if(listView.p.locked == false && listView.onChange) listView.onChange();
|
|
|
|
} else if(listView.p.lostFocus == false && listView.selected() == false) {
|
2011-02-24 09:25:20 +00:00
|
|
|
listView.p.lostFocus = false;
|
2011-10-24 11:35:34 +00:00
|
|
|
listView.state.selected = false;
|
|
|
|
listView.state.selection = 0;
|
|
|
|
if(listView.p.locked == false && listView.onChange) listView.onChange();
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
|
|
|
if(listView.onActivate) listView.onActivate();
|
2012-06-25 12:49:39 +00:00
|
|
|
} else if(nmhdr->code == NM_CUSTOMDRAW) {
|
|
|
|
LPNMLVCUSTOMDRAW lvcd = (LPNMLVCUSTOMDRAW)nmhdr;
|
|
|
|
switch(lvcd->nmcd.dwDrawStage) {
|
|
|
|
case CDDS_PREPAINT:
|
|
|
|
return CDRF_NOTIFYITEMDRAW;
|
|
|
|
case CDDS_ITEMPREPAINT:
|
|
|
|
if(listView.state.headerText.size() >= 2) {
|
|
|
|
//draw alternating row colors of there are two or more columns
|
|
|
|
if(lvcd->nmcd.dwItemSpec % 2) lvcd->clrTextBk = GetSysColor(COLOR_WINDOW) ^ 0x070707;
|
|
|
|
}
|
|
|
|
return CDRF_DODEFAULT;
|
|
|
|
default:
|
|
|
|
return CDRF_DODEFAULT;
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
2011-10-28 09:51:43 +00:00
|
|
|
break;
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case WM_HSCROLL:
|
|
|
|
case WM_VSCROLL: {
|
2011-08-06 14:03:52 +00:00
|
|
|
Object *object = 0;
|
|
|
|
if(lparam) {
|
|
|
|
object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
|
|
|
} else {
|
|
|
|
unsigned id = LOWORD(wparam);
|
|
|
|
HWND control = GetDlgItem(window.p.hwnd, id);
|
|
|
|
if(control == 0) break;
|
|
|
|
object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
|
|
|
|
}
|
2011-02-24 09:25:20 +00:00
|
|
|
if(object == 0) break;
|
2011-08-06 14:03:52 +00:00
|
|
|
|
|
|
|
if(dynamic_cast<HorizontalScrollBar*>(object)
|
|
|
|
|| dynamic_cast<VerticalScrollBar*>(object)) {
|
|
|
|
SCROLLINFO info;
|
|
|
|
memset(&info, 0, sizeof(SCROLLINFO));
|
|
|
|
info.cbSize = sizeof(SCROLLINFO);
|
|
|
|
info.fMask = SIF_ALL;
|
|
|
|
GetScrollInfo((HWND)lparam, 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)lparam, SB_CTL, &info, TRUE);
|
|
|
|
|
|
|
|
//Windows may clamp position to scrollbar range
|
|
|
|
GetScrollInfo((HWND)lparam, SB_CTL, &info);
|
|
|
|
|
|
|
|
if(dynamic_cast<HorizontalScrollBar*>(object)) {
|
|
|
|
HorizontalScrollBar &horizontalScrollBar = (HorizontalScrollBar&)*object;
|
|
|
|
if(horizontalScrollBar.state.position != info.nPos) {
|
|
|
|
horizontalScrollBar.state.position = info.nPos;
|
2011-09-05 03:48:23 +00:00
|
|
|
if(horizontalScrollBar.onChange) horizontalScrollBar.onChange();
|
2011-08-06 14:03:52 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
VerticalScrollBar &verticalScrollBar = (VerticalScrollBar&)*object;
|
|
|
|
if(verticalScrollBar.state.position != info.nPos) {
|
|
|
|
verticalScrollBar.state.position = info.nPos;
|
2011-09-05 03:48:23 +00:00
|
|
|
if(verticalScrollBar.onChange) verticalScrollBar.onChange();
|
2011-08-06 14:03:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-02-24 09:25:20 +00:00
|
|
|
if(dynamic_cast<HorizontalSlider*>(object)) {
|
|
|
|
HorizontalSlider &horizontalSlider = (HorizontalSlider&)*object;
|
|
|
|
if(horizontalSlider.state.position != horizontalSlider.position()) {
|
|
|
|
horizontalSlider.state.position = horizontalSlider.position();
|
|
|
|
if(horizontalSlider.onChange) horizontalSlider.onChange();
|
|
|
|
}
|
|
|
|
} else if(dynamic_cast<VerticalSlider*>(object)) {
|
|
|
|
VerticalSlider &verticalSlider = (VerticalSlider&)*object;
|
|
|
|
if(verticalSlider.state.position != verticalSlider.position()) {
|
|
|
|
verticalSlider.state.position = verticalSlider.position();
|
|
|
|
if(verticalSlider.onChange) verticalSlider.onChange();
|
|
|
|
}
|
|
|
|
}
|
2011-10-28 09:51:43 +00:00
|
|
|
|
|
|
|
break;
|
2011-02-24 09:25:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
|
}
|