bsnes/higan/phoenix/windows/window.cpp

230 lines
6.4 KiB
C++
Raw Normal View History

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
vector<pWindow*> pWindow::modal;
void pWindow::updateModality() {
for(auto &object : pObject::objects) {
if(dynamic_cast<pWindow*>(object) == nullptr) continue;
pWindow *p = (pWindow*)object;
if(modal.size() == 0) EnableWindow(p->hwnd, true);
else EnableWindow(p->hwnd, modal.find(p));
}
}
static const unsigned FixedStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_BORDER;
static const unsigned ResizableStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
Window& pWindow::none() {
static Window *window = nullptr;
if(window == nullptr) window = new Window;
return *window;
}
void pWindow::append(Layout &layout) {
Geometry geom = window.state.geometry;
geom.x = geom.y = 0;
layout.setGeometry(geom);
}
void pWindow::append(Menu &menu) {
menu.p.parentWindow = &window;
updateMenu();
}
void pWindow::append(Widget &widget) {
widget.p.parentWindow = &window;
widget.p.orphan();
if(widget.state.font != "") widget.p.setFont(widget.state.font);
else if(window.state.widgetFont != "") widget.p.setFont(window.state.widgetFont);
else widget.p.setFont("Tahoma, 8");
}
Color pWindow::backgroundColor() {
if(window.state.backgroundColorOverride) return window.state.backgroundColor;
DWORD color = GetSysColor(COLOR_3DFACE);
return { (uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color >> 0), 255 };
}
bool pWindow::focused() {
return (GetForegroundWindow() == hwnd);
}
Geometry pWindow::frameMargin() {
unsigned style = window.state.resizable ? ResizableStyle : FixedStyle;
if(window.state.fullScreen) style = 0;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect(&rc, style, window.state.menuVisible);
unsigned statusHeight = 0;
if(window.state.statusVisible) {
RECT src;
GetClientRect(hstatus, &src);
statusHeight = src.bottom - src.top;
}
return { abs(rc.left), abs(rc.top), (rc.right - rc.left) - 640, (rc.bottom - rc.top) + statusHeight - 480 };
}
Geometry pWindow::geometry() {
Geometry margin = frameMargin();
Update to v079 release. byuu says: This release includes Nintendo Super System DIP switch emulation and improved PPU rendering accuracy, among other things. Changelog: - added Nintendo Super System DIP switch emulation [requires XML setting maps] - emulated Super Game Boy $6001 VRAM offset selection port [ikari_01] - fixed randomness initialization of S-SMP port registers [fixes DBZ:Hyper Dimension and Ninja Warriors] - mosaic V-countdown caches BGOFS registers (fixes Super Turrican 2 effect) [reported by zal16] - non-mosaic BGOFS registers are always cached at H=60 (fixes NHL '94 and Super Mario World flickering) - fixed 2xSaI family of renderers on 64-bit systems - cleaned up SMP source code - phoenix: fixed a bug when closing bsnes while minimized Please note that the mosaic BGOFS fix is only for the accuracy profile. Unfortunately the older scanline-based compatibility renderer's code is nearly unmaintainable at this point, so I haven't yet been able to backport the fixes. Also, I have written a new cycle-accurate SMP core that does not use libco. The aim is to implement it into Snes9X v1.54. But it would of course be prudent to test the new core first. [...then in the next post...] Decided to keep that Super Mario World part a surprise, so ... surprise! Realized while working on the Super Turrican 2 mosaic fix, and from looking at NHL '94 and Dai Kaijuu Monogatari 2's behavior, that BGOFS registers must be cached between H=0 and H=88 for the entire scanline ... they can't work otherwise, and it'd be stupid for the PPU to re-add the offset to the position on every pixel anyway. I chose H=60 for now. Once I am set up with the RGB monitor and the North American cartridge dumping is completed, I'll set it on getting exact timings for all these things. It'll probably require a smallish speed hit to allow exact-cycle timing events for everything in the PPU.
2011-06-05 03:45:04 +00:00
RECT rc;
if(IsIconic(hwnd)) {
//GetWindowRect returns -32000(x),-32000(y) when window is minimized
WINDOWPLACEMENT wp;
GetWindowPlacement(hwnd, &wp);
rc = wp.rcNormalPosition;
} else {
GetWindowRect(hwnd, &rc);
}
signed x = rc.left + margin.x;
signed y = rc.top + margin.y;
unsigned width = (rc.right - rc.left) - margin.width;
unsigned height = (rc.bottom - rc.top) - margin.height;
return { x, y, width, height };
}
void pWindow::remove(Layout &layout) {
}
void pWindow::remove(Menu &menu) {
updateMenu();
}
void pWindow::remove(Widget &widget) {
widget.p.orphan();
}
void pWindow::setBackgroundColor(const Color &color) {
if(brush) DeleteObject(brush);
brushColor = RGB(color.red, color.green, color.blue);
brush = CreateSolidBrush(brushColor);
}
void pWindow::setFocused() {
if(window.state.visible == false) setVisible(true);
SetFocus(hwnd);
}
void pWindow::setFullScreen(bool fullScreen) {
locked = true;
if(fullScreen == false) {
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | (window.state.resizable ? ResizableStyle : FixedStyle));
setGeometry(window.state.geometry);
} else {
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
Geometry margin = frameMargin();
setGeometry({ margin.x, margin.y, GetSystemMetrics(SM_CXSCREEN) - margin.width, GetSystemMetrics(SM_CYSCREEN) - margin.height });
}
locked = false;
}
void pWindow::setGeometry(const Geometry &geometry) {
locked = true;
Geometry margin = frameMargin();
SetWindowPos(
hwnd, NULL,
geometry.x - margin.x, geometry.y - margin.y,
geometry.width + margin.width, geometry.height + margin.height,
SWP_NOZORDER | SWP_FRAMECHANGED
);
SetWindowPos(hstatus, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_FRAMECHANGED);
for(auto &layout : window.state.layout) {
Geometry geom = this->geometry();
geom.x = geom.y = 0;
layout.setGeometry(geom);
}
locked = false;
}
void pWindow::setMenuFont(const string &font) {
}
void pWindow::setMenuVisible(bool visible) {
locked = true;
SetMenu(hwnd, visible ? hmenu : 0);
setGeometry(window.state.geometry);
locked = false;
}
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
void pWindow::setModal(bool modality) {
if(modality == false) {
if(auto position = modal.find(this)) modal.remove(position());
} else {
modal.appendonce(this);
}
updateModality();
}
void pWindow::setResizable(bool resizable) {
SetWindowLongPtr(hwnd, GWL_STYLE, window.state.resizable ? ResizableStyle : FixedStyle);
setGeometry(window.state.geometry);
}
void pWindow::setStatusFont(const string &font) {
if(hstatusfont) DeleteObject(hstatusfont);
hstatusfont = pFont::create(font);
SendMessage(hstatus, WM_SETFONT, (WPARAM)hstatusfont, 0);
}
void pWindow::setStatusText(const string &text) {
SendMessage(hstatus, SB_SETTEXT, 0, (LPARAM)(wchar_t*)utf16_t(text));
}
void pWindow::setStatusVisible(bool visible) {
locked = true;
ShowWindow(hstatus, visible ? SW_SHOWNORMAL : SW_HIDE);
setGeometry(window.state.geometry);
locked = false;
}
void pWindow::setTitle(const string &text) {
SetWindowText(hwnd, utf16_t(text));
}
void pWindow::setVisible(bool visible) {
ShowWindow(hwnd, visible ? SW_SHOWNORMAL : SW_HIDE);
Update to v088r15 release. byuu says: Changelog: - default placement of presentation window optimized for 1024x768 displays or larger (sorry if yours is smaller, move the window yourself.) - Direct3D waits until a previous Vblank ends before waiting for the next Vblank to begin (fixes video timing analysis, and ---really--- fast computers.) - Window::setVisible(false) clears modality, but also fixed in Browser code as well (fixes loading images on Windows hanging) - Browser won't consume full CPU resources (but timing analysis will, I don't want stalls to affect the results.) - closing settings window while analyzing stops analysis - you can load the SGB BIOS without a game (why the hell you would want to ...) - escape closes the Browser window (it won't close other dialogs, it has to be hooked up per-window) - just for fun, joypad hat up/down moves in Browser file list, any joypad button loads selected game [not very useful, lacks repeat, and there aren't GUI load file open buttons] - Super Scope and Justifier crosshairs render correctly (probably doesn't belong in the core, but it's not something I suspect people want to do themselves ...) - you can load GB, SGB, GB, SGB ... without problems (not happy with how I did this, but I don't want to add an Interface::setInterface() function yet) - PAL timing works as I want now (if you want 50fps on a 60hz monitor, you must not use sync video) [needed to update the DSP frequency when toggling video/audio sync] - not going to save input port selection for now (lot of work), but it will properly keep your port setting across cartridge loads at least [just goes to controller on emulator restart] - SFC overscan on and off both work as expected now (off centers image, on shows entire image) - laevateinn compiles properly now - ethos goes to ~/.config/bsnes now that target-ui is dead [honestly, I recommend deleting the old folder and starting over] - Emulator::Interface callbacks converted to virtual binding structure that GUI inherits from (simplifies binding callbacks) - this breaks Super Game Boy for a bit, I need to rethink system-specific bindings without direct inheritance Timing analysis works spectacularly well on Windows, too. You won't get your 100% perfect rate (unless maybe you leave the analysis running overnight?), but it'll get really freaking close this way.
2012-05-07 23:29:03 +00:00
if(visible == false) setModal(false);
}
void pWindow::setWidgetFont(const string &font) {
for(auto &widget : window.state.widget) {
if(widget.state.font == "") widget.setFont(font);
}
}
void pWindow::constructor() {
brush = 0;
hwnd = CreateWindow(L"phoenix_window", L"", ResizableStyle, 128, 128, 256, 256, 0, 0, GetModuleHandle(0), 0);
hmenu = CreateMenu();
hstatus = CreateWindow(STATUSCLASSNAME, L"", WS_CHILD, 0, 0, 0, 0, hwnd, 0, GetModuleHandle(0), 0);
hstatusfont = 0;
setStatusFont("Tahoma, 8");
//status bar will be capable of receiving tab focus if it is not disabled
SetWindowLongPtr(hstatus, GWL_STYLE, GetWindowLong(hstatus, GWL_STYLE) | WS_DISABLED);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&window);
setGeometry({ 128, 128, 256, 256 });
}
void pWindow::destructor() {
DeleteObject(hstatusfont);
DestroyWindow(hstatus);
DestroyMenu(hmenu);
DestroyWindow(hwnd);
}
void pWindow::updateMenu() {
if(hmenu) DestroyMenu(hmenu);
hmenu = CreateMenu();
for(auto &menu : window.state.menu) {
menu.p.update(window);
if(menu.visible()) {
AppendMenu(hmenu, MF_STRING | MF_POPUP, (UINT_PTR)menu.p.hmenu, utf16_t(menu.state.text));
}
}
SetMenu(hwnd, window.state.menuVisible ? hmenu : 0);
}