From b5b21a4ec291465d4e788bd1786829b09fa9034c Mon Sep 17 00:00:00 2001 From: byuu Date: Mon, 30 Mar 2009 18:21:47 +0000 Subject: [PATCH] Update to bsnes v042 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new release quite a bit faster than I was expecting, but a lot has changed. Most importantly is a new Windows input driver, "RawInput". The downside is that this makes bsnes require at least Windows XP, as Windows 2000 and earlier lack RawInput support. The upside is that input from multiple keyboards and mice can be distinguished from each other — very useful for dual-Justifier support in Lethal Enforcers. Users of previous versions of bsnes will need to manually select the new driver via Settings->Configuration->Advanced->Input driver, and will need to re-map all assigned input keys, including the default user interface hotkeys. Or alternatively, delete the configuration file under %APPDATA%\.bsnes or ~/.bsnes. Also new is an XInput driver, which avoids the DirectInput driver limitation of being unable to distinguish the two shoulder trigger buttons. This makes bsnes require DirectX 9.0c or later for the necessary drivers. Note that Windows Vista SP0 does not ship with these, so if you haven't installed it yet, you'll need to do so. This driver is part of the "RawInput" driver mentioned above. This part is important: if you receive an error regarding xinput1_3.dll, you need to download and install the DirectX 9.0c run-time. For those on Windows 2000, or without DirectX 9.0c, it is still possible to compile and run bsnes with the older DirectInput driver only; but I won't be providing a binary myself for this — at least not at this time. More bad news for some: hiro, my Win32 / GTK+ API wrapper, has been discontinued and removed from the source tree for this release. Qt 4.5.0+ is now required for the user interface. Very sorry to the Linux distros that do not have packages for QT 4.5 yet. You'll need to continue with v041 for now. --- src/Makefile | 18 +- src/base.hpp | 2 +- src/cart/cart_loader.cpp | 6 +- src/cc.bat | 4 +- src/chip/bsx/bsx.hpp | 2 +- src/chip/bsx/bsx_base.cpp | 24 +- src/chip/bsx/bsx_cart.cpp | 14 +- src/chip/bsx/bsx_flash.cpp | 22 +- src/lib/hiro/gtk/button.cpp | 27 - src/lib/hiro/gtk/button.hpp | 12 - src/lib/hiro/gtk/canvas.cpp | 89 --- src/lib/hiro/gtk/canvas.hpp | 19 - src/lib/hiro/gtk/checkbox.cpp | 41 - src/lib/hiro/gtk/checkbox.hpp | 16 - src/lib/hiro/gtk/combobox.cpp | 45 -- src/lib/hiro/gtk/combobox.hpp | 16 - src/lib/hiro/gtk/editbox.cpp | 74 -- src/lib/hiro/gtk/editbox.hpp | 16 - src/lib/hiro/gtk/formcontrol.cpp | 32 - src/lib/hiro/gtk/formcontrol.hpp | 15 - src/lib/hiro/gtk/frame.cpp | 20 - src/lib/hiro/gtk/frame.hpp | 12 - src/lib/hiro/gtk/hiro.cpp | 270 ------- src/lib/hiro/gtk/hiro.hpp | 78 -- src/lib/hiro/gtk/keymap.cpp | 188 ----- src/lib/hiro/gtk/label.cpp | 22 - src/lib/hiro/gtk/label.hpp | 12 - src/lib/hiro/gtk/listbox.cpp | 160 ---- src/lib/hiro/gtk/listbox.hpp | 28 - src/lib/hiro/gtk/menucheckitem.cpp | 35 - src/lib/hiro/gtk/menucheckitem.hpp | 15 - src/lib/hiro/gtk/menucontrol.cpp | 20 - src/lib/hiro/gtk/menucontrol.hpp | 12 - src/lib/hiro/gtk/menugroup.cpp | 22 - src/lib/hiro/gtk/menugroup.hpp | 13 - src/lib/hiro/gtk/menuitem.cpp | 20 - src/lib/hiro/gtk/menuitem.hpp | 11 - src/lib/hiro/gtk/menuradioitem.cpp | 37 - src/lib/hiro/gtk/menuradioitem.hpp | 14 - src/lib/hiro/gtk/menuseparator.cpp | 14 - src/lib/hiro/gtk/menuseparator.hpp | 11 - src/lib/hiro/gtk/port.cpp | 17 - src/lib/hiro/gtk/progressbar.cpp | 25 - src/lib/hiro/gtk/progressbar.hpp | 13 - src/lib/hiro/gtk/radiobox.cpp | 43 -- src/lib/hiro/gtk/radiobox.hpp | 15 - src/lib/hiro/gtk/slider.cpp | 36 - src/lib/hiro/gtk/slider.hpp | 14 - src/lib/hiro/gtk/widget.cpp | 24 - src/lib/hiro/gtk/widget.hpp | 13 - src/lib/hiro/gtk/window.cpp | 325 -------- src/lib/hiro/gtk/window.hpp | 71 -- src/lib/hiro/hiro.cpp | 274 ------- src/lib/hiro/hiro.hpp | 538 -------------- src/lib/hiro/win/button.cpp | 14 - src/lib/hiro/win/button.hpp | 8 - src/lib/hiro/win/canvas.cpp | 52 -- src/lib/hiro/win/canvas.hpp | 16 - src/lib/hiro/win/checkbox.cpp | 25 - src/lib/hiro/win/checkbox.hpp | 11 - src/lib/hiro/win/combobox.cpp | 38 - src/lib/hiro/win/combobox.hpp | 14 - src/lib/hiro/win/editbox.cpp | 84 --- src/lib/hiro/win/editbox.hpp | 14 - src/lib/hiro/win/formcontrol.cpp | 45 -- src/lib/hiro/win/formcontrol.hpp | 20 - src/lib/hiro/win/frame.cpp | 13 - src/lib/hiro/win/frame.hpp | 8 - src/lib/hiro/win/hiro.cpp | 444 ----------- src/lib/hiro/win/hiro.hpp | 97 --- src/lib/hiro/win/keymap.cpp | 74 -- src/lib/hiro/win/label.cpp | 13 - src/lib/hiro/win/label.hpp | 8 - src/lib/hiro/win/listbox.cpp | 98 --- src/lib/hiro/win/listbox.hpp | 18 - src/lib/hiro/win/menucheckitem.cpp | 40 - src/lib/hiro/win/menucheckitem.hpp | 14 - src/lib/hiro/win/menucontrol.cpp | 18 - src/lib/hiro/win/menucontrol.hpp | 14 - src/lib/hiro/win/menugroup.cpp | 48 -- src/lib/hiro/win/menugroup.hpp | 15 - src/lib/hiro/win/menuitem.cpp | 23 - src/lib/hiro/win/menuitem.hpp | 11 - src/lib/hiro/win/menuradioitem.cpp | 41 - src/lib/hiro/win/menuradioitem.hpp | 17 - src/lib/hiro/win/menuseparator.cpp | 22 - src/lib/hiro/win/menuseparator.hpp | 11 - src/lib/hiro/win/port.cpp | 40 - src/lib/hiro/win/progressbar.cpp | 20 - src/lib/hiro/win/progressbar.hpp | 9 - src/lib/hiro/win/radiobox.cpp | 24 - src/lib/hiro/win/radiobox.hpp | 13 - src/lib/hiro/win/slider.cpp | 24 - src/lib/hiro/win/slider.hpp | 12 - src/lib/hiro/win/widget.cpp | 27 - src/lib/hiro/win/widget.hpp | 19 - src/lib/hiro/win/window.cpp | 334 --------- src/lib/hiro/win/window.hpp | 74 -- src/lib/nall/input.hpp | 213 ++++-- src/lib/ruby/input.hpp | 1 - src/lib/ruby/input/directinput.cpp | 474 ++++++------ src/lib/ruby/input/rawinput.cpp | 781 ++++++++++++++++++++ src/lib/ruby/input/rawinput.hpp | 22 + src/lib/ruby/input/sdl.cpp | 77 +- src/lib/ruby/input/x.cpp | 2 +- src/lib/ruby/input/xlibkeys.hpp | 206 +++--- src/lib/ruby/ruby.cpp | 12 +- src/lib/ruby/ruby.hpp | 5 +- src/lib/ruby/ruby_impl.cpp | 9 + src/lib/sync.bat | 23 +- src/lib/sync.sh | 6 - src/ppu/bppu/bppu_render_bg.cpp | 408 +++++----- src/snes/snes.cpp | 2 +- src/ui_hiro/Makefile | 31 - src/ui_hiro/base/about.cpp | 34 - src/ui_hiro/base/about.hpp | 9 - src/ui_hiro/base/main.cpp | 499 ------------- src/ui_hiro/base/main.hpp | 98 --- src/ui_hiro/base/textview.cpp | 17 - src/ui_hiro/base/textview.hpp | 8 - src/ui_hiro/bsnes.rc | 4 - src/ui_hiro/config.cpp | 261 ------- src/ui_hiro/event/debugger.cpp | 70 -- src/ui_hiro/event/debugger.hpp | 5 - src/ui_hiro/event/event.cpp | 512 ------------- src/ui_hiro/event/event.hpp | 54 -- src/ui_hiro/inputdevices.cpp | 383 ---------- src/ui_hiro/inputmanager.cpp | 107 --- src/ui_hiro/inputui.cpp | 56 -- src/ui_hiro/interface.cpp | 82 -- src/ui_hiro/license.hpp | 87 --- src/ui_hiro/loader/bsxloader.cpp | 93 --- src/ui_hiro/loader/bsxloader.hpp | 28 - src/ui_hiro/loader/stloader.cpp | 110 --- src/ui_hiro/loader/stloader.hpp | 27 - src/ui_hiro/main.cpp | 126 ---- src/ui_hiro/main.hpp | 8 - src/ui_hiro/readme.hpp | 80 -- src/ui_hiro/resource.cpp | 12 - src/ui_hiro/settings/advanced.cpp | 104 --- src/ui_hiro/settings/advanced.hpp | 15 - src/ui_hiro/settings/audiosettings.cpp | 124 ---- src/ui_hiro/settings/audiosettings.hpp | 20 - src/ui_hiro/settings/cheateditor.cpp | 225 ------ src/ui_hiro/settings/cheateditor.hpp | 46 -- src/ui_hiro/settings/driverselect.cpp | 148 ---- src/ui_hiro/settings/driverselect.hpp | 33 - src/ui_hiro/settings/inputconfig.cpp | 267 ------- src/ui_hiro/settings/inputconfig.hpp | 47 -- src/ui_hiro/settings/pathsettings.cpp | 187 ----- src/ui_hiro/settings/pathsettings.hpp | 45 -- src/ui_hiro/settings/settings.cpp | 64 -- src/ui_hiro/settings/settings.hpp | 9 - src/ui_hiro/settings/videosettings.cpp | 103 --- src/ui_hiro/settings/videosettings.hpp | 22 - src/ui_hiro/status.cpp | 80 -- src/ui_hiro/status.hpp | 18 - src/ui_hiro/ui.cpp | 110 --- src/ui_hiro/ui.hpp | 24 - src/ui_qt/Makefile | 18 +- src/ui_qt/base/about.cpp | 16 +- src/ui_qt/base/about.hpp | 1 - src/ui_qt/base/htmlviewer.cpp | 14 +- src/ui_qt/base/loader.cpp | 31 +- src/ui_qt/base/main.cpp | 8 +- src/ui_qt/config.cpp | 97 +-- src/ui_qt/input/input.cpp | 216 ++++-- src/ui_qt/input/input.hpp | 67 +- src/ui_qt/main.cpp | 40 +- src/ui_qt/main.hpp | 10 +- src/ui_qt/platform.cpp | 40 + src/ui_qt/settings/input.cpp | 16 + src/ui_qt/settings/input.hpp | 2 + src/ui_qt/settings/paths.cpp | 12 +- src/ui_qt/settings/settings.cpp | 16 +- src/ui_qt/settings/settings.hpp | 1 - src/ui_qt/settings/utility/codeeditor.cpp | 18 +- src/ui_qt/settings/utility/inputcapture.cpp | 388 ++++++++-- src/ui_qt/settings/utility/inputcapture.hpp | 80 +- src/ui_qt/settings/video.cpp | 2 +- src/ui_qt/ui.cpp | 8 +- src/ui_qt/utility/utility.cpp | 85 ++- src/ui_qt/utility/utility.hpp | 3 +- src/ui_qt/utility/window.cpp | 96 ++- 184 files changed, 2527 insertions(+), 10391 deletions(-) delete mode 100644 src/lib/hiro/gtk/button.cpp delete mode 100644 src/lib/hiro/gtk/button.hpp delete mode 100644 src/lib/hiro/gtk/canvas.cpp delete mode 100644 src/lib/hiro/gtk/canvas.hpp delete mode 100644 src/lib/hiro/gtk/checkbox.cpp delete mode 100644 src/lib/hiro/gtk/checkbox.hpp delete mode 100644 src/lib/hiro/gtk/combobox.cpp delete mode 100644 src/lib/hiro/gtk/combobox.hpp delete mode 100644 src/lib/hiro/gtk/editbox.cpp delete mode 100644 src/lib/hiro/gtk/editbox.hpp delete mode 100644 src/lib/hiro/gtk/formcontrol.cpp delete mode 100644 src/lib/hiro/gtk/formcontrol.hpp delete mode 100644 src/lib/hiro/gtk/frame.cpp delete mode 100644 src/lib/hiro/gtk/frame.hpp delete mode 100644 src/lib/hiro/gtk/hiro.cpp delete mode 100644 src/lib/hiro/gtk/hiro.hpp delete mode 100644 src/lib/hiro/gtk/keymap.cpp delete mode 100644 src/lib/hiro/gtk/label.cpp delete mode 100644 src/lib/hiro/gtk/label.hpp delete mode 100644 src/lib/hiro/gtk/listbox.cpp delete mode 100644 src/lib/hiro/gtk/listbox.hpp delete mode 100644 src/lib/hiro/gtk/menucheckitem.cpp delete mode 100644 src/lib/hiro/gtk/menucheckitem.hpp delete mode 100644 src/lib/hiro/gtk/menucontrol.cpp delete mode 100644 src/lib/hiro/gtk/menucontrol.hpp delete mode 100644 src/lib/hiro/gtk/menugroup.cpp delete mode 100644 src/lib/hiro/gtk/menugroup.hpp delete mode 100644 src/lib/hiro/gtk/menuitem.cpp delete mode 100644 src/lib/hiro/gtk/menuitem.hpp delete mode 100644 src/lib/hiro/gtk/menuradioitem.cpp delete mode 100644 src/lib/hiro/gtk/menuradioitem.hpp delete mode 100644 src/lib/hiro/gtk/menuseparator.cpp delete mode 100644 src/lib/hiro/gtk/menuseparator.hpp delete mode 100644 src/lib/hiro/gtk/port.cpp delete mode 100644 src/lib/hiro/gtk/progressbar.cpp delete mode 100644 src/lib/hiro/gtk/progressbar.hpp delete mode 100644 src/lib/hiro/gtk/radiobox.cpp delete mode 100644 src/lib/hiro/gtk/radiobox.hpp delete mode 100644 src/lib/hiro/gtk/slider.cpp delete mode 100644 src/lib/hiro/gtk/slider.hpp delete mode 100644 src/lib/hiro/gtk/widget.cpp delete mode 100644 src/lib/hiro/gtk/widget.hpp delete mode 100644 src/lib/hiro/gtk/window.cpp delete mode 100644 src/lib/hiro/gtk/window.hpp delete mode 100644 src/lib/hiro/hiro.cpp delete mode 100644 src/lib/hiro/hiro.hpp delete mode 100644 src/lib/hiro/win/button.cpp delete mode 100644 src/lib/hiro/win/button.hpp delete mode 100644 src/lib/hiro/win/canvas.cpp delete mode 100644 src/lib/hiro/win/canvas.hpp delete mode 100644 src/lib/hiro/win/checkbox.cpp delete mode 100644 src/lib/hiro/win/checkbox.hpp delete mode 100644 src/lib/hiro/win/combobox.cpp delete mode 100644 src/lib/hiro/win/combobox.hpp delete mode 100644 src/lib/hiro/win/editbox.cpp delete mode 100644 src/lib/hiro/win/editbox.hpp delete mode 100644 src/lib/hiro/win/formcontrol.cpp delete mode 100644 src/lib/hiro/win/formcontrol.hpp delete mode 100644 src/lib/hiro/win/frame.cpp delete mode 100644 src/lib/hiro/win/frame.hpp delete mode 100644 src/lib/hiro/win/hiro.cpp delete mode 100644 src/lib/hiro/win/hiro.hpp delete mode 100644 src/lib/hiro/win/keymap.cpp delete mode 100644 src/lib/hiro/win/label.cpp delete mode 100644 src/lib/hiro/win/label.hpp delete mode 100644 src/lib/hiro/win/listbox.cpp delete mode 100644 src/lib/hiro/win/listbox.hpp delete mode 100644 src/lib/hiro/win/menucheckitem.cpp delete mode 100644 src/lib/hiro/win/menucheckitem.hpp delete mode 100644 src/lib/hiro/win/menucontrol.cpp delete mode 100644 src/lib/hiro/win/menucontrol.hpp delete mode 100644 src/lib/hiro/win/menugroup.cpp delete mode 100644 src/lib/hiro/win/menugroup.hpp delete mode 100644 src/lib/hiro/win/menuitem.cpp delete mode 100644 src/lib/hiro/win/menuitem.hpp delete mode 100644 src/lib/hiro/win/menuradioitem.cpp delete mode 100644 src/lib/hiro/win/menuradioitem.hpp delete mode 100644 src/lib/hiro/win/menuseparator.cpp delete mode 100644 src/lib/hiro/win/menuseparator.hpp delete mode 100644 src/lib/hiro/win/port.cpp delete mode 100644 src/lib/hiro/win/progressbar.cpp delete mode 100644 src/lib/hiro/win/progressbar.hpp delete mode 100644 src/lib/hiro/win/radiobox.cpp delete mode 100644 src/lib/hiro/win/radiobox.hpp delete mode 100644 src/lib/hiro/win/slider.cpp delete mode 100644 src/lib/hiro/win/slider.hpp delete mode 100644 src/lib/hiro/win/widget.cpp delete mode 100644 src/lib/hiro/win/widget.hpp delete mode 100644 src/lib/hiro/win/window.cpp delete mode 100644 src/lib/hiro/win/window.hpp create mode 100644 src/lib/ruby/input/rawinput.cpp create mode 100644 src/lib/ruby/input/rawinput.hpp delete mode 100644 src/ui_hiro/Makefile delete mode 100644 src/ui_hiro/base/about.cpp delete mode 100644 src/ui_hiro/base/about.hpp delete mode 100644 src/ui_hiro/base/main.cpp delete mode 100644 src/ui_hiro/base/main.hpp delete mode 100644 src/ui_hiro/base/textview.cpp delete mode 100644 src/ui_hiro/base/textview.hpp delete mode 100644 src/ui_hiro/bsnes.rc delete mode 100644 src/ui_hiro/config.cpp delete mode 100644 src/ui_hiro/event/debugger.cpp delete mode 100644 src/ui_hiro/event/debugger.hpp delete mode 100644 src/ui_hiro/event/event.cpp delete mode 100644 src/ui_hiro/event/event.hpp delete mode 100644 src/ui_hiro/inputdevices.cpp delete mode 100644 src/ui_hiro/inputmanager.cpp delete mode 100644 src/ui_hiro/inputui.cpp delete mode 100644 src/ui_hiro/interface.cpp delete mode 100644 src/ui_hiro/license.hpp delete mode 100644 src/ui_hiro/loader/bsxloader.cpp delete mode 100644 src/ui_hiro/loader/bsxloader.hpp delete mode 100644 src/ui_hiro/loader/stloader.cpp delete mode 100644 src/ui_hiro/loader/stloader.hpp delete mode 100644 src/ui_hiro/main.cpp delete mode 100644 src/ui_hiro/main.hpp delete mode 100644 src/ui_hiro/readme.hpp delete mode 100644 src/ui_hiro/resource.cpp delete mode 100644 src/ui_hiro/settings/advanced.cpp delete mode 100644 src/ui_hiro/settings/advanced.hpp delete mode 100644 src/ui_hiro/settings/audiosettings.cpp delete mode 100644 src/ui_hiro/settings/audiosettings.hpp delete mode 100644 src/ui_hiro/settings/cheateditor.cpp delete mode 100644 src/ui_hiro/settings/cheateditor.hpp delete mode 100644 src/ui_hiro/settings/driverselect.cpp delete mode 100644 src/ui_hiro/settings/driverselect.hpp delete mode 100644 src/ui_hiro/settings/inputconfig.cpp delete mode 100644 src/ui_hiro/settings/inputconfig.hpp delete mode 100644 src/ui_hiro/settings/pathsettings.cpp delete mode 100644 src/ui_hiro/settings/pathsettings.hpp delete mode 100644 src/ui_hiro/settings/settings.cpp delete mode 100644 src/ui_hiro/settings/settings.hpp delete mode 100644 src/ui_hiro/settings/videosettings.cpp delete mode 100644 src/ui_hiro/settings/videosettings.hpp delete mode 100644 src/ui_hiro/status.cpp delete mode 100644 src/ui_hiro/status.hpp delete mode 100644 src/ui_hiro/ui.cpp delete mode 100644 src/ui_hiro/ui.hpp diff --git a/src/Makefile b/src/Makefile index 0774319a..a765a589 100644 --- a/src/Makefile +++ b/src/Makefile @@ -17,8 +17,9 @@ ifneq ($(findstring gcc,$(compiler)),) # GCC family link = -s mkbin = -o$1 mkdef = -D$1 - mkinc = -I$1 + mkincpath = -I$1 mklib = -l$1 + mklibpath = -L$1 # profile-guided optimization: # flags += -fprofile-generate @@ -34,8 +35,9 @@ else ifeq ($(compiler),cl) # Visual C++ link = /link mkbin = /Fe$1 mkdef = /D$1 - mkinc = /I$1 + mkincpath = /I$1 mklib = $1.lib + mklibpath = /L$1 else unknown_compiler: help; endif @@ -48,10 +50,13 @@ ifeq ($(platform),x) # X11 ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x delete = rm -f $1 else ifeq ($(platform),win) # Windows - # enable static linking to Qt for Windows build - mingw_link_flags = -mwindows -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc + mingw_link_flags = -mwindows + # mingw_links_flags = -mconsole - ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.directinput + # enable static linking to Qt for Windows build + mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc + + ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1)) link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags)) link += $(call mklib,uuid) @@ -68,6 +73,7 @@ endif ############ rubyflags = $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`) +link += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`) link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9)) link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw)) @@ -80,7 +86,7 @@ link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound)) link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32))) link += $(if $(findstring audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple)) link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid)) -link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`) +link += $(if $(findstring input.rawinput,$(ruby)),$(call mklib,xinput) $(call mklib,dinput8) $(call mklib,dxguid)) #################### ### core objects ### diff --git a/src/base.hpp b/src/base.hpp index da5afb39..ab2d5c31 100644 --- a/src/base.hpp +++ b/src/base.hpp @@ -1,4 +1,4 @@ -#define BSNES_VERSION "0.041" +#define BSNES_VERSION "0.042" #define BSNES_TITLE "bsnes v" BSNES_VERSION #define BUSCORE sBus diff --git a/src/cart/cart_loader.cpp b/src/cart/cart_loader.cpp index 8627221d..283496ee 100644 --- a/src/cart/cart_loader.cpp +++ b/src/cart/cart_loader.cpp @@ -118,7 +118,7 @@ bool Cartridge::load_bsx(const char *base, const char *slot) { delete[] data; } - if(load_image(slot, data, size, patch_applied)) { + if(load_image(slot, data, size, patch_applied) == true) { set(bsx_flash_loaded, true); if(patch_applied) set(patched, true); bs.ram = data; @@ -157,7 +157,7 @@ bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const cha read_header(cartinfo, cart.rom = data, cart.rom_size = size); set_cartinfo(cartinfo); - if(load_image(slotA, data, size, patch_applied)) { + if(load_image(slotA, data, size, patch_applied) == true) { if(patch_applied) set(patched, true); stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000]; memcpy(stA.rom, data, min(size, stA.rom_size)); @@ -166,7 +166,7 @@ bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const cha load_ram(get_filename(slotA, "srm", snes.config.path.save), stA.ram, stA.ram_size = 0x020000, 0xff); } - if(load_image(slotB, data, size, patch_applied)) { + if(load_image(slotB, data, size, patch_applied) == true) { if(patch_applied) set(patched, true); stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000]; memcpy(stB.rom, data, min(size, stB.rom_size)); diff --git a/src/cc.bat b/src/cc.bat index 9e270d97..ecdff182 100644 --- a/src/cc.bat +++ b/src/cc.bat @@ -1,3 +1,3 @@ -@mingw32-make platform=win compiler=mingw32-gcc -::@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true +::@mingw32-make platform=win compiler=mingw32-gcc +@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true @pause diff --git a/src/chip/bsx/bsx.hpp b/src/chip/bsx/bsx.hpp index ebab28a9..484cf421 100644 --- a/src/chip/bsx/bsx.hpp +++ b/src/chip/bsx/bsx.hpp @@ -56,7 +56,7 @@ public: void power(); void reset(); - unsigned size(); + unsigned size() const; uint8 read(unsigned addr); void write(unsigned addr, uint8 data); diff --git a/src/chip/bsx/bsx_base.cpp b/src/chip/bsx/bsx_base.cpp index 3e81ece7..496150a7 100644 --- a/src/chip/bsx/bsx_base.cpp +++ b/src/chip/bsx/bsx_base.cpp @@ -32,9 +32,9 @@ uint8 BSXBase::mmio_read(unsigned addr) { if(regs.r2192_counter >= 18) regs.r2192_counter = 0; if(counter == 0) { - time_t rawtime; + time_t rawtime; time(&rawtime); - tm *t = localtime(&rawtime); + tm *t = localtime(&rawtime); regs.r2192_hour = t->tm_hour; regs.r2192_minute = t->tm_min; @@ -42,11 +42,11 @@ uint8 BSXBase::mmio_read(unsigned addr) { } switch(counter) { - case 0: return 0x00; //??? - case 1: return 0x00; //??? - case 2: return 0x00; //??? - case 3: return 0x00; //??? - case 4: return 0x00; //??? + case 0: return 0x00; //??? + case 1: return 0x00; //??? + case 2: return 0x00; //??? + case 3: return 0x00; //??? + case 4: return 0x00; //??? case 5: return 0x01; case 6: return 0x01; case 7: return 0x00; @@ -55,11 +55,11 @@ uint8 BSXBase::mmio_read(unsigned addr) { case 10: return regs.r2192_second; case 11: return regs.r2192_minute; case 12: return regs.r2192_hour; - case 13: return 0x00; //??? - case 14: return 0x00; //??? - case 15: return 0x00; //??? - case 16: return 0x00; //??? - case 17: return 0x00; //??? + case 13: return 0x00; //??? + case 14: return 0x00; //??? + case 15: return 0x00; //??? + case 16: return 0x00; //??? + case 17: return 0x00; //??? } } break; diff --git a/src/chip/bsx/bsx_cart.cpp b/src/chip/bsx/bsx_cart.cpp index ed875cf8..68a07583 100644 --- a/src/chip/bsx/bsx_cart.cpp +++ b/src/chip/bsx/bsx_cart.cpp @@ -22,10 +22,12 @@ void BSXCart::reset() { void BSXCart::update_memory_map() { Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram; - if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping + if((regs.r[0x02] & 0x80) == 0x00) { + //LoROM mapping bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart); bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart); - } else { //HiROM mapping + } else { + //HiROM mapping bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart); bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart); bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart); @@ -58,12 +60,12 @@ void BSXCart::update_memory_map() { } uint8 BSXCart::mmio_read(unsigned addr) { - if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO + if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO uint8 n = (addr >> 16) & 15; return regs.r[n]; } - if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM + if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff)); } @@ -71,14 +73,14 @@ uint8 BSXCart::mmio_read(unsigned addr) { } void BSXCart::mmio_write(unsigned addr, uint8 data) { - if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO + if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO uint8 n = (addr >> 16) & 15; regs.r[n] = data; if(n == 0x0e && data & 0x80) update_memory_map(); return; } - if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM + if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data); } } diff --git a/src/chip/bsx/bsx_flash.cpp b/src/chip/bsx/bsx_flash.cpp index 781d2ea6..deceb95e 100644 --- a/src/chip/bsx/bsx_flash.cpp +++ b/src/chip/bsx/bsx_flash.cpp @@ -17,7 +17,7 @@ void BSXFlash::reset() { regs.write_enable = false; } -unsigned BSXFlash::size() { +unsigned BSXFlash::size() const { return memory::bscram.size(); } @@ -31,7 +31,7 @@ uint8 BSXFlash::read(unsigned addr) { } if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) { - //read flash cartridge vendor information + //read flash cartridge vendor information switch(addr - 0xff00) { case 0x00: return 0x4d; case 0x01: return 0x00; @@ -39,7 +39,7 @@ uint8 BSXFlash::read(unsigned addr) { case 0x03: return 0x00; case 0x04: return 0x00; case 0x05: return 0x00; - case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID) + case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID) case 0x07: return 0x00; default: return 0x00; } @@ -49,14 +49,14 @@ uint8 BSXFlash::read(unsigned addr) { } void BSXFlash::write(unsigned addr, uint8 data) { -//there exist both read-only and read-write BS-X flash cartridges ... -//unfortunately, the vendor info is not stored inside memory dumps -//of BS-X flashcarts, so it is impossible to determine whether a -//given flashcart is writeable. -//however, it has been observed that LoROM-mapped BS-X carts always -//use read-write flashcarts, and HiROM-mapped BS-X carts always use -//read-only flashcarts. -//below is an unfortunately necessary workaround to this problem. + //there exist both read-only and read-write BS-X flash cartridges ... + //unfortunately, the vendor info is not stored inside memory dumps + //of BS-X flashcarts, so it is impossible to determine whether a + //given flashcart is writeable. + //however, it has been observed that LoROM-mapped BS-X carts always + //use read-write flashcarts, and HiROM-mapped BS-X carts always use + //read-only flashcarts. + //below is an unfortunately necessary workaround to this problem. if(cartridge.mapper() == Cartridge::BSCHiROM) return; if((addr & 0xff0000) == 0) { diff --git a/src/lib/hiro/gtk/button.cpp b/src/lib/hiro/gtk/button.cpp deleted file mode 100644 index bc9c1718..00000000 --- a/src/lib/hiro/gtk/button.cpp +++ /dev/null @@ -1,27 +0,0 @@ -void hiro_pbutton_tick(pButton *p) { - if(p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self)); -} - -void pButton::create(unsigned style, unsigned width, unsigned height, const char *text) { - button = gtk_button_new_with_label(text ? text : ""); - set_default_font(button); - gtk_widget_set_size_request(button, width, height); - gtk_widget_show(button); - g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(hiro_pbutton_tick), (gpointer)this); -} - -void pButton::set_text(const char *text) { - if(!button) return; - gtk_button_set_label(GTK_BUTTON(button), text ? text : ""); - set_default_font(button); -} - -pButton::pButton(Button &self_) : pFormControl(self_), self(self_) { - button = 0; -} - -/* internal */ - -GtkWidget* pButton::gtk_handle() { - return button; -} diff --git a/src/lib/hiro/gtk/button.hpp b/src/lib/hiro/gtk/button.hpp deleted file mode 100644 index 4d9add99..00000000 --- a/src/lib/hiro/gtk/button.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class pButton : public pFormControl { -public: - Button &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - pButton(Button&); - - /* internal */ - GtkWidget *button; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/canvas.cpp b/src/lib/hiro/gtk/canvas.cpp deleted file mode 100644 index 5e571bb7..00000000 --- a/src/lib/hiro/gtk/canvas.cpp +++ /dev/null @@ -1,89 +0,0 @@ -void hiro_pcanvas_expose(pCanvas *p) { - uint32_t *f = p->fbuffer; - uint32_t *r = p->rbuffer; - for(unsigned y = p->canvas->allocation.height; y; y--) { - for(unsigned x = p->canvas->allocation.width; x; x--) { - uint32_t p = *f++; - *r++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff); - } - } - - gdk_draw_rgb_32_image(p->canvas->window, - p->canvas->style->fg_gc[GTK_WIDGET_STATE(p->canvas)], - 0, 0, p->canvas->allocation.width, p->canvas->allocation.height, - GDK_RGB_DITHER_NONE, (guchar*)p->rbuffer, p->bpitch); -} - -gboolean hiro_pcanvas_button_press(GtkWidget *widget, GdkEventButton *event, pCanvas *p) { - if(p->self.on_input && event->button < mouse::buttons) { - p->self.on_input(event_t(event_t::Input, (mouse::button + event->button) + (1 << 16), &p->self)); - } - return false; //do not propogate the event to other handlers -} - -gboolean hiro_pcanvas_button_release(GtkWidget *widget, GdkEventButton *event, pCanvas *p) { - if(p->self.on_input && event->button < mouse::buttons) { - p->self.on_input(event_t(event_t::Input, (mouse::button + event->button) + (0 << 16), &p->self)); - } - return false; //do not propogate the event to other handlers -} - -void pCanvas::create(unsigned style, unsigned width, unsigned height) { - canvas = gtk_drawing_area_new(); - resize(width, height); - GdkColor color; - color.pixel = color.red = color.green = color.blue = 0; - gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &color); - gtk_widget_set_double_buffered(canvas, false); - gtk_widget_add_events(canvas, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - gtk_widget_show(canvas); - g_signal_connect_swapped(G_OBJECT(canvas), "expose_event", G_CALLBACK(hiro_pcanvas_expose), (gpointer)this); - g_signal_connect(G_OBJECT(canvas), "button_press_event", G_CALLBACK(hiro_pcanvas_button_press), (gpointer)this); - g_signal_connect(G_OBJECT(canvas), "button_release_event", G_CALLBACK(hiro_pcanvas_button_release), (gpointer)this); -} - -void pCanvas::redraw() { - if(!canvas || !canvas->window) return; - - GdkRectangle rect; - rect.x = 0; - rect.y = 0; - rect.width = canvas->allocation.width; - rect.height = canvas->allocation.height; - gdk_window_invalidate_rect(canvas->window, &rect, true); -} - -uint32_t* pCanvas::buffer() { - return fbuffer; -} - -pCanvas::pCanvas(Canvas &self_) : pFormControl(self_), self(self_) { - canvas = 0; - fbuffer = 0; - rbuffer = 0; - bpitch = 0; -} - -pCanvas::~pCanvas() { - if(fbuffer) free(fbuffer); - if(rbuffer) free(rbuffer); -} - -/* internal */ - -void pCanvas::resize(unsigned width, unsigned height) { - if(fbuffer) free(fbuffer); - if(rbuffer) free(rbuffer); - - bpitch = width * sizeof(uint32_t); - fbuffer = (uint32_t*)malloc(bpitch * height); - rbuffer = (uint32_t*)malloc(bpitch * height); - memset(fbuffer, 0, bpitch * height); - memset(rbuffer, 0, bpitch * height); - - pFormControl::resize(width, height); -} - -GtkWidget* pCanvas::gtk_handle() { - return canvas; -} diff --git a/src/lib/hiro/gtk/canvas.hpp b/src/lib/hiro/gtk/canvas.hpp deleted file mode 100644 index d924a2c0..00000000 --- a/src/lib/hiro/gtk/canvas.hpp +++ /dev/null @@ -1,19 +0,0 @@ -class pCanvas : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height); - void redraw(); - uint32_t* buffer(); - - Canvas &self; - pCanvas(Canvas&); - ~pCanvas(); - - /* internal */ - GtkWidget *canvas; - //GTK+ RGB drawing function draws in xBGR format, so two buffers are needed ... - uint32_t *fbuffer; //one for the xRGB image - uint32_t *rbuffer; //one for the xBGR image - unsigned bpitch; - void resize(unsigned width, unsigned height); - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/checkbox.cpp b/src/lib/hiro/gtk/checkbox.cpp deleted file mode 100644 index 62aba757..00000000 --- a/src/lib/hiro/gtk/checkbox.cpp +++ /dev/null @@ -1,41 +0,0 @@ -void hiro_pcheckbox_tick(pCheckbox *p) { - if(!p->locked && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, p->checked(), &p->self)); -} - -void pCheckbox::create(unsigned style, unsigned width, unsigned height, const char *text) { - checkbox = gtk_check_button_new_with_label(text ? text : ""); - set_default_font(checkbox); - gtk_widget_set_size_request(checkbox, width, height); - gtk_widget_show(checkbox); - g_signal_connect_swapped(G_OBJECT(checkbox), "toggled", G_CALLBACK(hiro_pcheckbox_tick), (gpointer)this); -} - -void pCheckbox::set_text(const char *text) { - if(!checkbox) return; - gtk_button_set_label(GTK_BUTTON(checkbox), text ? text : ""); -} - -void pCheckbox::check(bool state) { - locked = true; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), state ? TRUE : FALSE); - locked = false; -} - -void pCheckbox::uncheck() { - check(false); -} - -bool pCheckbox::checked() { - return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox)); -} - -pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) { - checkbox = 0; - locked = false; -} - -/* internal */ - -GtkWidget* pCheckbox::gtk_handle() { - return checkbox; -} diff --git a/src/lib/hiro/gtk/checkbox.hpp b/src/lib/hiro/gtk/checkbox.hpp deleted file mode 100644 index 17a5a55c..00000000 --- a/src/lib/hiro/gtk/checkbox.hpp +++ /dev/null @@ -1,16 +0,0 @@ -class pCheckbox : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - void check(bool state = true); - void uncheck(); - bool checked(); - - Checkbox &self; - pCheckbox(Checkbox&); - - /* internal */ - GtkWidget* gtk_handle(); - GtkWidget *checkbox; - bool locked; -}; diff --git a/src/lib/hiro/gtk/combobox.cpp b/src/lib/hiro/gtk/combobox.cpp deleted file mode 100644 index 41d7a436..00000000 --- a/src/lib/hiro/gtk/combobox.cpp +++ /dev/null @@ -1,45 +0,0 @@ -void hiro_pcombobox_change(pCombobox *p) { - if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->get_selection(), &p->self)); -} - -void pCombobox::create(unsigned style, unsigned width, unsigned height, const char *text) { - combobox = gtk_combo_box_new_text(); - set_default_font(combobox); - gtk_widget_set_size_request(combobox, width, height); - gtk_widget_show(combobox); - - g_signal_connect_swapped(G_OBJECT(combobox), "changed", G_CALLBACK(hiro_pcombobox_change), (gpointer)this); -} - -void pCombobox::add_item(const char *text) { - if(!combobox) return; - gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), text ? text : "?"); - if(counter++ == 0) set_selection(0); -} - -int pCombobox::get_selection() { - return gtk_combo_box_get_active(GTK_COMBO_BOX(combobox)); -} - -void pCombobox::set_selection(int index) { - gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index); -} - -void pCombobox::reset() { - if(counter == 0) return; - for(int i = counter - 1; i >= 0; i--) { - gtk_combo_box_remove_text(GTK_COMBO_BOX(combobox), i); - } - counter = 0; -} - -pCombobox::pCombobox(Combobox &self_) : pFormControl(self_), self(self_) { - combobox = 0; - counter = 0; -} - -/* internal */ - -GtkWidget* pCombobox::gtk_handle() { - return combobox; -} diff --git a/src/lib/hiro/gtk/combobox.hpp b/src/lib/hiro/gtk/combobox.hpp deleted file mode 100644 index d3829886..00000000 --- a/src/lib/hiro/gtk/combobox.hpp +++ /dev/null @@ -1,16 +0,0 @@ -class pCombobox : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void add_item(const char *text); - int get_selection(); - void set_selection(int index); - void reset(); - - Combobox &self; - pCombobox(Combobox&); - - /* internal */ - GtkWidget *combobox; - unsigned counter; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/editbox.cpp b/src/lib/hiro/gtk/editbox.cpp deleted file mode 100644 index ff51816b..00000000 --- a/src/lib/hiro/gtk/editbox.cpp +++ /dev/null @@ -1,74 +0,0 @@ -static void hiro_peditbox_change(pEditbox *p) { - if(p->self.on_change) { - p->self.on_change(event_t(event_t::Change, 0, &p->self)); - } -} - -void pEditbox::create(unsigned style, unsigned width, unsigned height, const char *text) { - multiline = bool(style & Editbox::Multiline); - - if(multiline == false) { - editbox = gtk_entry_new(); - if(style & Editbox::Readonly) { gtk_entry_set_editable(GTK_ENTRY(editbox), false); } - gtk_entry_set_text(GTK_ENTRY(editbox), text ? text : ""); - gtk_widget_set_size_request(editbox, width, height); - gtk_widget_show(editbox); - g_signal_connect_swapped(G_OBJECT(editbox), "changed", G_CALLBACK(hiro_peditbox_change), (gpointer)this); - } else { - GtkPolicyType hscroll = (style & Editbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS : - (style & Editbox::HorizontalScrollNever ) ? GTK_POLICY_NEVER : - GTK_POLICY_AUTOMATIC; - GtkPolicyType vscroll = (style & Editbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS : - (style & Editbox::VerticalScrollNever ) ? GTK_POLICY_NEVER : - GTK_POLICY_AUTOMATIC; - scrollbox = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN); - gtk_widget_set_size_request(scrollbox, width, height); - editbox = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(editbox), - (hscroll == GTK_POLICY_NEVER ? GTK_WRAP_WORD_CHAR : GTK_WRAP_NONE)); - gtk_container_add(GTK_CONTAINER(scrollbox), editbox); - buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(editbox)); - if(style & Editbox::Readonly) { gtk_text_view_set_editable(GTK_TEXT_VIEW(editbox), false); } - gtk_text_buffer_set_text(buffer, text ? text : "", -1); - gtk_widget_show(editbox); - gtk_widget_show(scrollbox); - g_signal_connect_swapped(G_OBJECT(buffer), "changed", G_CALLBACK(hiro_peditbox_change), (gpointer)this); - } - - set_default_font(editbox); -} - -void pEditbox::set_text(const char *text) { - if(multiline == false) { - gtk_entry_set_text(GTK_ENTRY(editbox), text); - } else { - gtk_text_buffer_set_text(buffer, text, -1); - } -} - -unsigned pEditbox::get_text(char *text, unsigned length) { - if(multiline == false) { - const char *temp = gtk_entry_get_text(GTK_ENTRY(editbox)); - return strlcpy(text, temp ? temp : "", length); - } else { - GtkTextIter start, end; - gtk_text_buffer_get_start_iter(buffer, &start); - gtk_text_buffer_get_end_iter(buffer, &end); - return strlcpy(text, gtk_text_buffer_get_text(buffer, &start, &end, true), length); - } -} - -pEditbox::pEditbox(Editbox &self_) : pFormControl(self_), self(self_) { - scrollbox = 0; - editbox = 0; - buffer = 0; - multiline = false; -} - -/* internal */ - -GtkWidget* pEditbox::gtk_handle() { - return multiline ? scrollbox : editbox; -} diff --git a/src/lib/hiro/gtk/editbox.hpp b/src/lib/hiro/gtk/editbox.hpp deleted file mode 100644 index 889180b6..00000000 --- a/src/lib/hiro/gtk/editbox.hpp +++ /dev/null @@ -1,16 +0,0 @@ -class pEditbox : public pFormControl { -public: - Editbox &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - unsigned get_text(char *text, unsigned length = -1U); - void set_text(const char *text = ""); - - pEditbox(Editbox&); - - /* internal */ - GtkWidget *scrollbox; - GtkWidget *editbox; - GtkTextBuffer *buffer; - bool multiline; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/formcontrol.cpp b/src/lib/hiro/gtk/formcontrol.cpp deleted file mode 100644 index 276ffc7d..00000000 --- a/src/lib/hiro/gtk/formcontrol.cpp +++ /dev/null @@ -1,32 +0,0 @@ -void pFormControl::resize(unsigned width, unsigned height) { - gtk_widget_set_size_request(gtk_handle(), width, height); -} - -void pFormControl::focus() { - gtk_widget_grab_focus(gtk_handle()); -} - -bool pFormControl::focused() { - return GTK_WIDGET_HAS_FOCUS(gtk_handle()); -} - -void pFormControl::enable(bool state) { - gtk_widget_set_sensitive(gtk_handle(), state); -} - -void pFormControl::disable() { - enable(false); -} - -bool pFormControl::enabled() { - return GTK_WIDGET_SENSITIVE(gtk_handle()); -} - -pFormControl::pFormControl(FormControl &self_) : pWidget(self_), self(self_) { -} - -/* internal */ - -GtkWidget* pFormControl::gtk_handle() { - return 0; -} diff --git a/src/lib/hiro/gtk/formcontrol.hpp b/src/lib/hiro/gtk/formcontrol.hpp deleted file mode 100644 index d05e4dbe..00000000 --- a/src/lib/hiro/gtk/formcontrol.hpp +++ /dev/null @@ -1,15 +0,0 @@ -class pFormControl : public pWidget { -public: - virtual void resize(unsigned width, unsigned height); - void focus(); - bool focused(); - void enable(bool = true); - void disable(); - bool enabled(); - - FormControl &self; - pFormControl(FormControl&); - - /* internal */ - virtual GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/frame.cpp b/src/lib/hiro/gtk/frame.cpp deleted file mode 100644 index f32f38b0..00000000 --- a/src/lib/hiro/gtk/frame.cpp +++ /dev/null @@ -1,20 +0,0 @@ -void pFrame::create(unsigned style, unsigned width, unsigned height, const char *text) { - frame = gtk_frame_new(text ? text : ""); - set_default_font(frame); - gtk_widget_set_size_request(frame, width, height); - gtk_widget_show(frame); -} - -void pFrame::set_text(const char *text) { - gtk_frame_set_label(GTK_FRAME(frame), text ? text : ""); -} - -pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) { - frame = 0; -} - -/* internal */ - -GtkWidget* pFrame::gtk_handle() { - return frame; -} diff --git a/src/lib/hiro/gtk/frame.hpp b/src/lib/hiro/gtk/frame.hpp deleted file mode 100644 index 892a9db1..00000000 --- a/src/lib/hiro/gtk/frame.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class pFrame : public pFormControl { -public: - Frame &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - pFrame(Frame&); - - /* internal */ - GtkWidget *frame; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/hiro.cpp b/src/lib/hiro/gtk/hiro.cpp deleted file mode 100644 index b252cd80..00000000 --- a/src/lib/hiro/gtk/hiro.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#include "hiro.hpp" -#include "port.cpp" - -#include -using nall::min; -using nall::max; - -namespace libhiro { - -static void set_font(GtkWidget *widget, gpointer font) { - gtk_widget_modify_font(widget, (PangoFontDescription*)font); - if(GTK_IS_CONTAINER(widget)) { - gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)set_font, font); - } -} - -static void set_default_font(GtkWidget *widget) { - set_font(widget, phiro().font); -} - -#include "keymap.cpp" -#include "widget.cpp" - #include "window.cpp" - #include "menucontrol.cpp" - #include "menugroup.cpp" - #include "menuitem.cpp" - #include "menucheckitem.cpp" - #include "menuradioitem.cpp" - #include "menuseparator.cpp" - #include "formcontrol.cpp" - #include "frame.cpp" - #include "canvas.cpp" - #include "label.cpp" - #include "button.cpp" - #include "checkbox.cpp" - #include "radiobox.cpp" - #include "editbox.cpp" - #include "listbox.cpp" - #include "combobox.cpp" - #include "progressbar.cpp" - #include "slider.cpp" - -void pHiro::init() { - is_composited = false; - *default_path = 0; - screen = gdk_screen_get_default(); - if(gdk_screen_is_composited(screen)) { - colormap = gdk_screen_get_rgba_colormap(screen); - if(colormap) is_composited = true; - else colormap = gdk_screen_get_rgb_colormap(screen); //fallback - } else { - colormap = gdk_screen_get_rgb_colormap(screen); - } - - font = pango_font_description_new(); - pango_font_description_set_family(font, "Sans"); - pango_font_description_set_absolute_size(font, 11.0 * PANGO_SCALE); - pango_font_description_set_style(font, PANGO_STYLE_NORMAL); - - //apply custom GTK+-2.0 stylesheet. - //it's obviously not ideal to override the global GTK+ theme settings; - //however it is necessary to ensure consistency between ports of hiro. - //without this, it would be impossible to develop a hiro application - //on one platform, and be assured text wouldn't clipped off, etc on - //another platform. - gtk_rc_parse_string( - "style \"ruby-gtk\"\n" - "{\n" - " GtkComboBox::appears-as-list = 1\n" //text tends to get cut off in some themes otherwise - " GtkTreeView::vertical-separator = 0\n" //GTK+ lists tend to have way more space than on Windows - "}\n" - "\n" - "class \"GtkComboBox\" style \"ruby-gtk\"\n" - "class \"GtkTreeView\" style \"ruby-gtk\"\n" - ); -} - -void pHiro::term() { - pango_font_description_free(font); - enable_screensaver(); -} - -bool pHiro::run() { - if(is_screensaver_enabled == false) screensaver_tick(); - gtk_main_iteration_do(false); - return pending(); -} - -bool pHiro::pending() { - return gtk_events_pending(); -} - -bool pHiro::folder_select(Window *focus, char *filename, const char *path) { - if(!filename) return false; - strcpy(filename, ""); - - GtkWidget *dialog = gtk_file_chooser_dialog_new("Select Folder", - focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - (const gchar*)0); - - if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path); - else if(*default_path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), default_path); - - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - strcpy(filename, fn); - set_default_path(fn); - g_free(fn); - } - - gtk_widget_destroy(dialog); - return strcmp(filename, ""); //return true if filename exists -} - -bool pHiro::file_open(Window *focus, char *filename, const char *path, const char *filter) { - if(!filename) return false; - strcpy(filename, ""); - - GtkWidget *dialog = gtk_file_chooser_dialog_new("Open File", - focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - (const gchar*)0); - - if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path); - else if(*default_path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), default_path); - - if(filter && *filter) { - lstring filterlist; - filterlist.split("\n", filter); - for(unsigned i = 0; i < filterlist.size(); i++) { - GtkFileFilter *filter = gtk_file_filter_new(); - lstring filterpart; - filterpart.split("\t", filterlist[i]); - gtk_file_filter_set_name(filter, string() << filterpart[0] << " (" << filterpart[1] << ")"); - lstring patternlist; - patternlist.split(",", filterpart[1]); - for(unsigned l = 0; l < patternlist.size(); l++) { - gtk_file_filter_add_pattern(filter, patternlist[l]); - } - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); - } - } - - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - strcpy(filename, fn); - set_default_path(fn); - g_free(fn); - } - - gtk_widget_destroy(dialog); - return strcmp(filename, ""); //return true if filename exists -} - -bool pHiro::file_save(Window *focus, char *filename, const char *path, const char *filter) { - if(!filename) return false; - strcpy(filename, ""); - - GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File", - focus ? GTK_WINDOW(focus->p.gtk_handle()) : (GtkWindow*)0, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - (const gchar*)0); - - if(path && *path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path); - else if(*default_path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), default_path); - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); - - if(filter && *filter) { - lstring filterlist; - filterlist.split("\n", filter); - for(unsigned i = 0; i < filterlist.size(); i++) { - GtkFileFilter *filter = gtk_file_filter_new(); - lstring filterpart; - filterpart.split("\t", filterlist[i]); - gtk_file_filter_set_name(filter, string() << filterpart[0] << " (" << filterpart[1] << ")"); - lstring patternlist; - patternlist.split(",", filterpart[1]); - for(unsigned l = 0; l < patternlist.size(); l++) { - gtk_file_filter_add_pattern(filter, patternlist[l]); - } - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); - } - } - - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - strcpy(filename, fn); - set_default_path(fn); - g_free(fn); - } - - gtk_widget_destroy(dialog); - return strcmp(filename, ""); //return true if filename exists -} - -unsigned pHiro::screen_width() { - return gdk_screen_width(); -} - -unsigned pHiro::screen_height() { - return gdk_screen_height(); -} - -void pHiro::enable_screensaver() { - if(is_screensaver_enabled == true) return; - is_screensaver_enabled = true; - DPMSDisable(GDK_DISPLAY()); -} - -void pHiro::disable_screensaver() { - if(is_screensaver_enabled == false) return; - is_screensaver_enabled = false; - DPMSEnable(GDK_DISPLAY()); -} - -pHiro& pHiro::handle() { - return hiro().p; -} - -pHiro::pHiro(Hiro &self_) : self(self_) { - is_screensaver_enabled = true; -} - -pHiro& phiro() { - return pHiro::handle(); -} - -/* internal */ - -//GTK+ does not save the most recent path to a file. -//Strip trailing filename / folder to save path for next file dialog request. -//This is only called when file dialog filename / folder is accepted, not when dialog cancelled. -void pHiro::set_default_path(const char *p) { - strcpy(default_path, p); - for(int i = strlen(default_path) - 1; i >= 0; i--) { - if(default_path[i] == '/' || default_path[i] == '\\') { - default_path[i] = 0; - break; - } - } -} - -void pHiro::screensaver_tick() { - static clock_t delta_x = 0, delta_y = 0; - - delta_y = clock(); - if(delta_y - delta_x < CLOCKS_PER_SEC * 20) return; - - //XSetScreenSaver(timeout = 0) does not work - //XResetScreenSaver() does not work - //XScreenSaverSuspend() does not work - //DPMSDisable() does not work - //XSendEvent(KeyPressMask) does not work - //use XTest extension to send fake keypress every ~20 seconds. - //keycode of 255 does not map to any actual key, but it will block screensaver. - delta_x = delta_y; - XTestFakeKeyEvent(GDK_DISPLAY(), 255, True, 0); - XSync(GDK_DISPLAY(), False); - XTestFakeKeyEvent(GDK_DISPLAY(), 255, False, 0); - XSync(GDK_DISPLAY(), False); -} - -} //namespace libhiro diff --git a/src/lib/hiro/gtk/hiro.hpp b/src/lib/hiro/gtk/hiro.hpp deleted file mode 100644 index 0c14c0f9..00000000 --- a/src/lib/hiro/gtk/hiro.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef HIRO_GTK_H -#define HIRO_GTK_H - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -extern int hiromain(int argc, const char *const argv[]); - -namespace libhiro { - -#include "widget.hpp" - #include "window.hpp" - #include "menucontrol.hpp" - #include "menugroup.hpp" - #include "menuitem.hpp" - #include "menucheckitem.hpp" - #include "menuradioitem.hpp" - #include "menuseparator.hpp" - #include "formcontrol.hpp" - #include "frame.hpp" - #include "canvas.hpp" - #include "label.hpp" - #include "button.hpp" - #include "checkbox.hpp" - #include "radiobox.hpp" - #include "editbox.hpp" - #include "listbox.hpp" - #include "combobox.hpp" - #include "progressbar.hpp" - #include "slider.hpp" - -class pHiro { -public: - Hiro &self; - void init(); - void term(); - bool run(); - bool pending(); - - bool folder_select(Window *focus, char *filename, const char *path = ""); - bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = ""); - bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = ""); - - unsigned screen_width(); - unsigned screen_height(); - - void enable_screensaver(); - void disable_screensaver(); - - static pHiro& handle(); - pHiro(Hiro&); - - /* internal */ - GdkScreen *screen; - GdkColormap *colormap; - PangoFontDescription *font; - bool is_composited; - char default_path[PATH_MAX]; - - void set_default_path(const char*); - bool is_screensaver_enabled; - void screensaver_tick(); - uint16_t translate_key(unsigned key); -}; - -pHiro& phiro(); - -} //namespace libhiro - -#endif //ifndef HIRO_GTK_H diff --git a/src/lib/hiro/gtk/keymap.cpp b/src/lib/hiro/gtk/keymap.cpp deleted file mode 100644 index 3a931e46..00000000 --- a/src/lib/hiro/gtk/keymap.cpp +++ /dev/null @@ -1,188 +0,0 @@ -uint16_t pHiro::translate_key(unsigned key) { - switch(key) { - case GDK_Escape: return keyboard::escape; - - case GDK_F1: return keyboard::f1; - case GDK_F2: return keyboard::f2; - case GDK_F3: return keyboard::f3; - case GDK_F4: return keyboard::f4; - case GDK_F5: return keyboard::f5; - case GDK_F6: return keyboard::f6; - case GDK_F7: return keyboard::f7; - case GDK_F8: return keyboard::f8; - case GDK_F9: return keyboard::f9; - case GDK_F10: return keyboard::f10; - case GDK_F11: return keyboard::f11; - case GDK_F12: return keyboard::f12; - - case GDK_Print: return keyboard::print_screen; - case GDK_Sys_Req: return keyboard::print_screen; - case GDK_Scroll_Lock: return keyboard::scroll_lock; - case GDK_Pause: return keyboard::pause; - case GDK_Break: return keyboard::pause; - - case GDK_grave: return keyboard::tilde; - case GDK_asciitilde: return keyboard::tilde; - - case GDK_1: return keyboard::num_1; - case GDK_2: return keyboard::num_2; - case GDK_3: return keyboard::num_3; - case GDK_4: return keyboard::num_4; - case GDK_5: return keyboard::num_5; - case GDK_6: return keyboard::num_6; - case GDK_7: return keyboard::num_7; - case GDK_8: return keyboard::num_8; - case GDK_9: return keyboard::num_9; - case GDK_0: return keyboard::num_0; - - case GDK_exclam: return keyboard::num_1; - case GDK_at: return keyboard::num_2; - case GDK_numbersign: return keyboard::num_3; - case GDK_dollar: return keyboard::num_4; - case GDK_percent: return keyboard::num_5; - case GDK_asciicircum: return keyboard::num_6; - case GDK_ampersand: return keyboard::num_7; - case GDK_asterisk: return keyboard::num_8; - case GDK_parenleft: return keyboard::num_9; - case GDK_parenright: return keyboard::num_0; - - case GDK_minus: return keyboard::dash; - case GDK_underscore: return keyboard::dash; - case GDK_equal: return keyboard::equal; - case GDK_plus: return keyboard::equal; - case GDK_BackSpace: return keyboard::backspace; - - case GDK_Insert: return keyboard::insert; - case GDK_Delete: return keyboard::delete_; - case GDK_Home: return keyboard::home; - case GDK_End: return keyboard::end; - case GDK_Page_Up: return keyboard::page_up; - case GDK_Page_Down: return keyboard::page_down; - - case GDK_a: return keyboard::a; - case GDK_b: return keyboard::b; - case GDK_c: return keyboard::c; - case GDK_d: return keyboard::d; - case GDK_e: return keyboard::e; - case GDK_f: return keyboard::f; - case GDK_g: return keyboard::g; - case GDK_h: return keyboard::h; - case GDK_i: return keyboard::i; - case GDK_j: return keyboard::j; - case GDK_k: return keyboard::k; - case GDK_l: return keyboard::l; - case GDK_m: return keyboard::m; - case GDK_n: return keyboard::n; - case GDK_o: return keyboard::o; - case GDK_p: return keyboard::p; - case GDK_q: return keyboard::q; - case GDK_r: return keyboard::r; - case GDK_s: return keyboard::s; - case GDK_t: return keyboard::t; - case GDK_u: return keyboard::u; - case GDK_v: return keyboard::v; - case GDK_w: return keyboard::w; - case GDK_x: return keyboard::x; - case GDK_y: return keyboard::y; - case GDK_z: return keyboard::z; - - case GDK_A: return keyboard::a; - case GDK_B: return keyboard::b; - case GDK_C: return keyboard::c; - case GDK_D: return keyboard::d; - case GDK_E: return keyboard::e; - case GDK_F: return keyboard::f; - case GDK_G: return keyboard::g; - case GDK_H: return keyboard::h; - case GDK_I: return keyboard::i; - case GDK_J: return keyboard::j; - case GDK_K: return keyboard::k; - case GDK_L: return keyboard::l; - case GDK_M: return keyboard::m; - case GDK_N: return keyboard::n; - case GDK_O: return keyboard::o; - case GDK_P: return keyboard::p; - case GDK_Q: return keyboard::q; - case GDK_R: return keyboard::r; - case GDK_S: return keyboard::s; - case GDK_T: return keyboard::t; - case GDK_U: return keyboard::u; - case GDK_V: return keyboard::v; - case GDK_W: return keyboard::w; - case GDK_X: return keyboard::x; - case GDK_Y: return keyboard::y; - case GDK_Z: return keyboard::z; - - case GDK_bracketleft: return keyboard::lbracket; - case GDK_bracketright: return keyboard::rbracket; - case GDK_backslash: return keyboard::backslash; - case GDK_semicolon: return keyboard::semicolon; - case GDK_apostrophe: return keyboard::apostrophe; - case GDK_comma: return keyboard::comma; - case GDK_period: return keyboard::period; - case GDK_slash: return keyboard::slash; - - case GDK_braceleft: return keyboard::lbracket; - case GDK_braceright: return keyboard::rbracket; - case GDK_bar: return keyboard::backslash; - case GDK_colon: return keyboard::semicolon; - case GDK_quotedbl: return keyboard::apostrophe; - case GDK_less: return keyboard::comma; - case GDK_greater: return keyboard::period; - case GDK_question: return keyboard::slash; - - case GDK_KP_1: return keyboard::pad_1; - case GDK_KP_2: return keyboard::pad_2; - case GDK_KP_3: return keyboard::pad_3; - case GDK_KP_4: return keyboard::pad_4; - case GDK_KP_5: return keyboard::pad_5; - case GDK_KP_6: return keyboard::pad_6; - case GDK_KP_7: return keyboard::pad_7; - case GDK_KP_8: return keyboard::pad_8; - case GDK_KP_9: return keyboard::pad_9; - case GDK_KP_0: return keyboard::pad_0; - case GDK_KP_Decimal: return keyboard::point; - - case GDK_KP_End: return keyboard::pad_1; - case GDK_KP_Down: return keyboard::pad_2; - case GDK_KP_Page_Down: return keyboard::pad_3; - case GDK_KP_Left: return keyboard::pad_4; - case GDK_KP_Begin: return keyboard::pad_5; - case GDK_KP_Right: return keyboard::pad_6; - case GDK_KP_Home: return keyboard::pad_7; - case GDK_KP_Up: return keyboard::pad_8; - case GDK_KP_Page_Up: return keyboard::pad_9; - case GDK_KP_Insert: return keyboard::pad_0; - case GDK_KP_Delete: return keyboard::point; - - case GDK_KP_Add: return keyboard::add; - case GDK_KP_Subtract: return keyboard::subtract; - case GDK_KP_Multiply: return keyboard::multiply; - case GDK_KP_Divide: return keyboard::divide; - case GDK_KP_Enter: return keyboard::enter; - - case GDK_Num_Lock: return keyboard::num_lock; - case GDK_Caps_Lock: return keyboard::caps_lock; - - case GDK_Up: return keyboard::up; - case GDK_Down: return keyboard::down; - case GDK_Left: return keyboard::left; - case GDK_Right: return keyboard::right; - - case GDK_Tab: return keyboard::tab; - case GDK_Return: return keyboard::return_; - case GDK_space: return keyboard::spacebar; - - case GDK_Control_L: return keyboard::lctrl; - case GDK_Control_R: return keyboard::rctrl; - case GDK_Alt_L: return keyboard::lalt; - case GDK_Alt_R: return keyboard::ralt; - case GDK_Shift_L: return keyboard::lshift; - case GDK_Shift_R: return keyboard::rshift; - case GDK_Super_L: return keyboard::lsuper; - case GDK_Super_R: return keyboard::rsuper; - case GDK_Menu: return keyboard::menu; - } - - return keyboard::none; -} diff --git a/src/lib/hiro/gtk/label.cpp b/src/lib/hiro/gtk/label.cpp deleted file mode 100644 index 84a8ebc5..00000000 --- a/src/lib/hiro/gtk/label.cpp +++ /dev/null @@ -1,22 +0,0 @@ -void pLabel::create(unsigned style, unsigned width, unsigned height, const char *text) { - label = gtk_label_new(text ? text : ""); - set_default_font(label); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); - gtk_widget_set_size_request(label, width, height); - gtk_widget_show(label); -} - -void pLabel::set_text(const char *text) { - if(!label) return; - gtk_label_set_label(GTK_LABEL(label), text ? text : ""); -} - -pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) { - label = 0; -} - -/* internal */ - -GtkWidget* pLabel::gtk_handle() { - return label; -} diff --git a/src/lib/hiro/gtk/label.hpp b/src/lib/hiro/gtk/label.hpp deleted file mode 100644 index 00d35728..00000000 --- a/src/lib/hiro/gtk/label.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class pLabel : public pFormControl { -public: - Label &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - pLabel(Label&); - - /* internal */ - GtkWidget *label; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/listbox.cpp b/src/lib/hiro/gtk/listbox.cpp deleted file mode 100644 index ac02b8e7..00000000 --- a/src/lib/hiro/gtk/listbox.cpp +++ /dev/null @@ -1,160 +0,0 @@ -static void hiro_plistbox_change(pListbox *p) { - //only send message when active item changes - if(p->listbox_selection == p->get_selection()) return; - - p->listbox_selection = p->get_selection(); - if(p->self.on_change) { - p->self.on_change(event_t(event_t::Change, p->listbox_selection, &p->self)); - } -} - -static void hiro_plistbox_activate(pListbox *p) { - p->listbox_selection = p->get_selection(); - if(p->self.on_activate) { - p->self.on_activate(event_t(event_t::Activate, p->listbox_selection, &p->self)); - } -} - -void pListbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) { - bool header = style & Listbox::Header; - GtkPolicyType hscroll = (style & Listbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS : - (style & Listbox::HorizontalScrollNever ) ? GTK_POLICY_NEVER : - GTK_POLICY_AUTOMATIC; - GtkPolicyType vscroll = (style & Listbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS : - (style & Listbox::VerticalScrollNever ) ? GTK_POLICY_NEVER : - GTK_POLICY_AUTOMATIC; - - scrollbox = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN); - - lstring list; - list.split("\t", columns); - - GType *v = (GType*)malloc(list.size() * sizeof(GType)); - for(unsigned i = 0; i < list.size(); i++) v[i] = G_TYPE_STRING; - store = gtk_list_store_newv(list.size(), v); - free(v); - - listbox = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_container_add(GTK_CONTAINER(scrollbox), listbox); - g_object_unref(G_OBJECT(store)); - gtk_widget_set_size_request(scrollbox, width, height); - gtk_widget_show(listbox); - gtk_widget_show(scrollbox); - - //alternate colors for each listbox entry if there are multiple columns - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(listbox), list.size() >= 2 ? true : false); - for(unsigned i = 0; i < list.size(); i++) { - unsigned i = column.size(); - column[i].renderer = gtk_cell_renderer_text_new(); - column[i].column = gtk_tree_view_column_new_with_attributes( - list[i], column[i].renderer, "text", i, (void*)0 - ); - //default header widget is GtkLabel with stock font size; - //only way to assign a custom font to header widget is to create custom GtkLabel widget. - column[i].label = gtk_label_new(list[i]); - set_default_font(column[i].label); - gtk_widget_show(column[i].label); - gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(column[i].column), column[i].label); - gtk_tree_view_append_column(GTK_TREE_VIEW(listbox), column[i].column); - } - - if(text && *text) { - list.split("\n", text); - for(unsigned i = 0; i < list.size(); i++) add_item(list[i]); - } - - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(listbox), header); - autosize_columns(); - - g_signal_connect_swapped(G_OBJECT(listbox), "cursor-changed", G_CALLBACK(hiro_plistbox_change), (gpointer)this); - g_signal_connect_swapped(G_OBJECT(listbox), "row-activated", G_CALLBACK(hiro_plistbox_activate), (gpointer)this); - - set_default_font(listbox); -} - -void pListbox::autosize_columns() { - gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listbox)); -} - -void pListbox::set_column_width(unsigned index, unsigned width) { - gtk_tree_view_column_set_min_width(column[index].column, width); - gtk_tree_view_column_set_max_width(column[index].column, width); -} - -void pListbox::add_item(const char *text) { - lstring list; - list.split("\t", text); - gtk_list_store_append(store, &iter); - for(unsigned i = 0; i < list.size(); i++) { - gtk_list_store_set(store, &iter, i, (const char*)list[i], -1); - } -} - -void pListbox::set_item(unsigned index, const char *text) { - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox)); - for(unsigned i = 0; i <= index; i++) { - i == 0 ? - gtk_tree_model_get_iter_first(model, &iter) : - gtk_tree_model_iter_next(model, &iter); - } - - lstring list; - list.split("\t", text); - for(unsigned i = 0; i < list.size(); i++) { - gtk_list_store_set(store, &iter, i, (const char*)list[i], -1); - } -} - -int pListbox::get_selection() { - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox)); - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox)); - if(gtk_tree_model_get_iter_first(model, &iter) == false) return -1; - if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return 0; - for(unsigned i = 1; i < 100000; i++) { - if(gtk_tree_model_iter_next(model, &iter) == false) return -1; - if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return i; - } - return -1; -} - -void pListbox::set_selection(int index) { - int current = get_selection(); - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox)); - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox)); - gtk_tree_selection_unselect_all(selection); - if(index < 0) return; //nothing to select? - - if(gtk_tree_model_get_iter_first(model, &iter)) { - if(index == 0) { - gtk_tree_selection_select_iter(selection, &iter); - } else { - for(unsigned i = 1; i < 100000; i++) { - if(gtk_tree_model_iter_next(model, &iter) == false) break; - if(index == i) { - gtk_tree_selection_select_iter(selection, &iter); - break; - } - } - } - } -} - -void pListbox::reset() { - listbox_selection = -1; - gtk_list_store_clear(GTK_LIST_STORE(store)); - gtk_tree_view_set_model(GTK_TREE_VIEW(listbox), GTK_TREE_MODEL(store)); -} - -pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) { - scrollbox = 0; - listbox = 0; - listbox_selection = -1; -} - -/* internal */ - -GtkWidget* pListbox::gtk_handle() { - return scrollbox; -} diff --git a/src/lib/hiro/gtk/listbox.hpp b/src/lib/hiro/gtk/listbox.hpp deleted file mode 100644 index a56727fa..00000000 --- a/src/lib/hiro/gtk/listbox.hpp +++ /dev/null @@ -1,28 +0,0 @@ -class pListbox : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = ""); - void autosize_columns(); - void set_column_width(unsigned column, unsigned width); - void add_item(const char *text); - void set_item(unsigned index, const char *text); - int get_selection(); - void set_selection(int index); - void reset(); - - Listbox &self; - pListbox(Listbox&); - - /* internal */ - GtkWidget *scrollbox; - GtkWidget *listbox; - GtkListStore *store; - struct GtkColumn { - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkWidget *label; - }; - vector column; - GtkTreeIter iter; - int listbox_selection; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/menucheckitem.cpp b/src/lib/hiro/gtk/menucheckitem.cpp deleted file mode 100644 index 60f9b9cd..00000000 --- a/src/lib/hiro/gtk/menucheckitem.cpp +++ /dev/null @@ -1,35 +0,0 @@ -void hiro_pmenucheckitem_tick(pMenuCheckItem *p) { - if(!p->locked && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, p->checked(), &p->self)); -} - -void pMenuCheckItem::create(const char *text) { - item = gtk_check_menu_item_new_with_label(text ? text : "?"); - set_default_font(item); - gtk_widget_show(item); - g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenucheckitem_tick), (gpointer)this); -} - -void pMenuCheckItem::check(bool state) { - locked = true; - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), state ? TRUE : FALSE); - locked = false; -} - -void pMenuCheckItem::uncheck() { - check(false); -} - -bool pMenuCheckItem::checked() { - return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)); -} - -pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) { - item = 0; - locked = true; -} - -/* internal */ - -GtkWidget* pMenuCheckItem::gtk_handle() { - return item; -} diff --git a/src/lib/hiro/gtk/menucheckitem.hpp b/src/lib/hiro/gtk/menucheckitem.hpp deleted file mode 100644 index 74f262be..00000000 --- a/src/lib/hiro/gtk/menucheckitem.hpp +++ /dev/null @@ -1,15 +0,0 @@ -class pMenuCheckItem : public pMenuControl { -public: - void create(const char *text = ""); - void check(bool state = true); - void uncheck(); - bool checked(); - - MenuCheckItem &self; - pMenuCheckItem(MenuCheckItem&); - - /* internal */ - GtkWidget* gtk_handle(); - GtkWidget *item; - bool locked; -}; diff --git a/src/lib/hiro/gtk/menucontrol.cpp b/src/lib/hiro/gtk/menucontrol.cpp deleted file mode 100644 index de6281bb..00000000 --- a/src/lib/hiro/gtk/menucontrol.cpp +++ /dev/null @@ -1,20 +0,0 @@ -void pMenuControl::enable(bool state) { - gtk_widget_set_sensitive(gtk_handle(), state); -} - -void pMenuControl::disable() { - enable(false); -} - -bool pMenuControl::enabled() { - return GTK_WIDGET_SENSITIVE(gtk_handle()); -} - -pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) { -} - -/* internal */ - -GtkWidget* pMenuControl::gtk_handle() { - return 0; -} diff --git a/src/lib/hiro/gtk/menucontrol.hpp b/src/lib/hiro/gtk/menucontrol.hpp deleted file mode 100644 index e6ec2678..00000000 --- a/src/lib/hiro/gtk/menucontrol.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class pMenuControl : public pWidget { -public: - void enable(bool = true); - void disable(); - bool enabled(); - - MenuControl &self; - pMenuControl(MenuControl&); - - /* internal */ - virtual GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/menugroup.cpp b/src/lib/hiro/gtk/menugroup.cpp deleted file mode 100644 index a05fc5f0..00000000 --- a/src/lib/hiro/gtk/menugroup.cpp +++ /dev/null @@ -1,22 +0,0 @@ -void pMenuGroup::create(const char *text) { - group = gtk_menu_new(); - item = gtk_menu_item_new_with_label(text ? text : ""); - set_default_font(item); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), group); - gtk_widget_show(item); -} - -void pMenuGroup::attach(MenuControl &menucontrol) { - gtk_menu_shell_append(GTK_MENU_SHELL(group), menucontrol.p.gtk_handle()); -} - -pMenuGroup::pMenuGroup(MenuGroup &self_) : pMenuControl(self_), self(self_) { - group = 0; - item = 0; -} - -/* internal */ - -GtkWidget* pMenuGroup::gtk_handle() { - return item; -} diff --git a/src/lib/hiro/gtk/menugroup.hpp b/src/lib/hiro/gtk/menugroup.hpp deleted file mode 100644 index fee411dd..00000000 --- a/src/lib/hiro/gtk/menugroup.hpp +++ /dev/null @@ -1,13 +0,0 @@ -class pMenuGroup : public pMenuControl { -public: - MenuGroup &self; - void create(const char *text); - void attach(MenuControl &menucontrol); - - pMenuGroup(MenuGroup&); - - /* internal */ - GtkWidget *group; - GtkWidget *item; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/menuitem.cpp b/src/lib/hiro/gtk/menuitem.cpp deleted file mode 100644 index c2540d4e..00000000 --- a/src/lib/hiro/gtk/menuitem.cpp +++ /dev/null @@ -1,20 +0,0 @@ -void hiro_pmenuitem_tick(pMenuItem *p) { - if(p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self)); -} - -void pMenuItem::create(const char *text) { - item = gtk_menu_item_new_with_label(text ? text : ""); - set_default_font(item); - g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(hiro_pmenuitem_tick), (gpointer)this); - gtk_widget_show(item); -} - -pMenuItem::pMenuItem(MenuItem &self_) : pMenuControl(self_), self(self_) { - item = 0; -} - -/* internal */ - -GtkWidget* pMenuItem::gtk_handle() { - return item; -} diff --git a/src/lib/hiro/gtk/menuitem.hpp b/src/lib/hiro/gtk/menuitem.hpp deleted file mode 100644 index 57d50126..00000000 --- a/src/lib/hiro/gtk/menuitem.hpp +++ /dev/null @@ -1,11 +0,0 @@ -class pMenuItem : public pMenuControl { -public: - void create(const char *text = ""); - - MenuItem &self; - pMenuItem(MenuItem&); - - /* internal */ - GtkWidget *item; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/menuradioitem.cpp b/src/lib/hiro/gtk/menuradioitem.cpp deleted file mode 100644 index 15f9107f..00000000 --- a/src/lib/hiro/gtk/menuradioitem.cpp +++ /dev/null @@ -1,37 +0,0 @@ -void hiro_pmenuradioitem_tick(pMenuRadioItem *p) { - //GTK+ sends two messages: one for the activated radio item, - //and one for the deactivated radio item. ignore the latter. - if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self)); -} - -void pMenuRadioItem::create(MenuRadioItemGroup &group, const char *text) { - if(group.size() == 0 || group[0] == &self) { - item = gtk_radio_menu_item_new_with_label(0, text ? text : "?"); - } else { - item = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(group[0]->p.gtk_handle()), text ? text : ""); - } - set_default_font(item); - gtk_widget_show(item); - g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenuradioitem_tick), (gpointer)this); -} - -void pMenuRadioItem::check() { - locked = true; - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); - locked = false; -} - -bool pMenuRadioItem::checked() { - return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)); -} - -pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) { - item = 0; - locked = false; -} - -/* internal */ - -GtkWidget* pMenuRadioItem::gtk_handle() { - return item; -} diff --git a/src/lib/hiro/gtk/menuradioitem.hpp b/src/lib/hiro/gtk/menuradioitem.hpp deleted file mode 100644 index 10bbee42..00000000 --- a/src/lib/hiro/gtk/menuradioitem.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class pMenuRadioItem : public pMenuControl { -public: - void create(MenuRadioItemGroup &group, const char *text = ""); - void check(); - bool checked(); - - MenuRadioItem &self; - pMenuRadioItem(MenuRadioItem&); - - /* internal */ - GtkWidget* gtk_handle(); - GtkWidget *item; - bool locked; -}; diff --git a/src/lib/hiro/gtk/menuseparator.cpp b/src/lib/hiro/gtk/menuseparator.cpp deleted file mode 100644 index a03ba421..00000000 --- a/src/lib/hiro/gtk/menuseparator.cpp +++ /dev/null @@ -1,14 +0,0 @@ -void pMenuSeparator::create() { - item = gtk_separator_menu_item_new(); - gtk_widget_show(item); -} - -pMenuSeparator::pMenuSeparator(MenuSeparator &self_) : pMenuControl(self_), self(self_) { - item = 0; -} - -/* internal */ - -GtkWidget* pMenuSeparator::gtk_handle() { - return item; -} diff --git a/src/lib/hiro/gtk/menuseparator.hpp b/src/lib/hiro/gtk/menuseparator.hpp deleted file mode 100644 index 2218a770..00000000 --- a/src/lib/hiro/gtk/menuseparator.hpp +++ /dev/null @@ -1,11 +0,0 @@ -class pMenuSeparator : public pMenuControl { -public: - MenuSeparator &self; - void create(); - - pMenuSeparator(MenuSeparator&); - - /* internal */ - GtkWidget *item; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/port.cpp b/src/lib/hiro/gtk/port.cpp deleted file mode 100644 index 6e3aaa0c..00000000 --- a/src/lib/hiro/gtk/port.cpp +++ /dev/null @@ -1,17 +0,0 @@ -char* userpath(char *output) { - struct passwd *userinfo = getpwuid(getuid()); - if(userinfo) { strcpy(output, userinfo->pw_dir); } - return output; -} - -int mkdir(const char *path) { - return mkdir(path, 0755); -} - -int main(int argc, char *argv[]) { - gtk_init(&argc, &argv); - libhiro::hiro().init(); - int result = hiromain(argc, argv); - libhiro::hiro().term(); - return result; -} diff --git a/src/lib/hiro/gtk/progressbar.cpp b/src/lib/hiro/gtk/progressbar.cpp deleted file mode 100644 index dde99cb4..00000000 --- a/src/lib/hiro/gtk/progressbar.cpp +++ /dev/null @@ -1,25 +0,0 @@ -void pProgressbar::create(unsigned style, unsigned width, unsigned height) { - progressbar = gtk_progress_bar_new(); - gtk_widget_set_size_request(progressbar, width, height); - gtk_widget_show(progressbar); -} - -unsigned pProgressbar::get_progress() { - unsigned progress = (unsigned)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar)) * 100.0); - return max(0U, min(progress, 100U)); -} - -void pProgressbar::set_progress(unsigned progress) { - progress = max(0U, min(progress, 100U)); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), (double)progress / 100.0); -} - -pProgressbar::pProgressbar(Progressbar &self_) : pFormControl(self_), self(self_) { - progressbar = 0; -} - -/* internal */ - -GtkWidget* pProgressbar::gtk_handle() { - return progressbar; -} diff --git a/src/lib/hiro/gtk/progressbar.hpp b/src/lib/hiro/gtk/progressbar.hpp deleted file mode 100644 index 7e5ae36e..00000000 --- a/src/lib/hiro/gtk/progressbar.hpp +++ /dev/null @@ -1,13 +0,0 @@ -class pProgressbar : public pFormControl { -public: - Progressbar &self; - void create(unsigned style, unsigned width, unsigned height); - unsigned get_progress(); - void set_progress(unsigned progress); - - pProgressbar(Progressbar&); - - /* internal */ - GtkWidget *progressbar; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/radiobox.cpp b/src/lib/hiro/gtk/radiobox.cpp deleted file mode 100644 index 6457089a..00000000 --- a/src/lib/hiro/gtk/radiobox.cpp +++ /dev/null @@ -1,43 +0,0 @@ -void hiro_pradiobox_tick(pRadiobox *p) { - //GTK+ sends two messages: one for the activated radiobox, - //and one for the deactivated radiobox. ignore the latter. - if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self)); -} - -void pRadiobox::create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text) { - if(group.size() == 0 || group[0] == &self) { - radiobox = gtk_radio_button_new_with_label(0, text ? text : ""); - } else { - radiobox = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0]->p.gtk_handle()), text ? text : ""); - } - set_default_font(radiobox); - gtk_widget_set_size_request(radiobox, width, height); - gtk_widget_show(radiobox); - g_signal_connect_swapped(G_OBJECT(radiobox), "toggled", G_CALLBACK(hiro_pradiobox_tick), (gpointer)this); -} - -void pRadiobox::set_text(const char *text) { - if(!radiobox) return; - gtk_button_set_label(GTK_BUTTON(radiobox), text ? text : ""); -} - -void pRadiobox::check() { - locked = true; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobox), TRUE); - locked = false; -} - -bool pRadiobox::checked() { - return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radiobox)); -} - -pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self), self(self_) { - radiobox = 0; - locked = false; -} - -/* internal */ - -GtkWidget* pRadiobox::gtk_handle() { - return radiobox; -} diff --git a/src/lib/hiro/gtk/radiobox.hpp b/src/lib/hiro/gtk/radiobox.hpp deleted file mode 100644 index cb25172d..00000000 --- a/src/lib/hiro/gtk/radiobox.hpp +++ /dev/null @@ -1,15 +0,0 @@ -class pRadiobox : public pFormControl { -public: - void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - void check(); - bool checked(); - - Radiobox &self; - pRadiobox(Radiobox&); - - /* internal */ - GtkWidget* gtk_handle(); - GtkWidget *radiobox; - bool locked; -}; diff --git a/src/lib/hiro/gtk/slider.cpp b/src/lib/hiro/gtk/slider.cpp deleted file mode 100644 index e6b02c0c..00000000 --- a/src/lib/hiro/gtk/slider.cpp +++ /dev/null @@ -1,36 +0,0 @@ -void hiro_pslider_change(pSlider *p) { - if(p->slider_position == p->get_position()) return; - if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->slider_position = p->get_position(), &p->self)); -} - -void pSlider::create(unsigned style, unsigned width, unsigned height, unsigned length) { - if(length < 1) length = 1; - if(style & Slider::Vertical) { - slider = gtk_vscale_new_with_range(0, length - 1, 1); - } else { - slider = gtk_hscale_new_with_range(0, length - 1, 1); - } - gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE); - gtk_widget_set_size_request(slider, width, height); - gtk_widget_show(slider); - g_signal_connect_swapped(G_OBJECT(slider), "value-changed", G_CALLBACK(hiro_pslider_change), (gpointer)this); -} - -unsigned pSlider::get_position() { - return (unsigned)gtk_range_get_value(GTK_RANGE(slider)); -} - -void pSlider::set_position(unsigned position) { - gtk_range_set_value(GTK_RANGE(slider), position); -} - -pSlider::pSlider(Slider &self_) : pFormControl(self_), self(self_) { - slider = 0; - slider_position = 0; -} - -/* internal */ - -GtkWidget* pSlider::gtk_handle() { - return slider; -} diff --git a/src/lib/hiro/gtk/slider.hpp b/src/lib/hiro/gtk/slider.hpp deleted file mode 100644 index 768ae821..00000000 --- a/src/lib/hiro/gtk/slider.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class pSlider : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height, unsigned length); - unsigned get_position(); - void set_position(unsigned position); - - Slider &self; - pSlider(Slider&); - - /* internal */ - GtkWidget *slider; - unsigned slider_position; - GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/widget.cpp b/src/lib/hiro/gtk/widget.cpp deleted file mode 100644 index 694f26c8..00000000 --- a/src/lib/hiro/gtk/widget.cpp +++ /dev/null @@ -1,24 +0,0 @@ -void pWidget::show(bool state) { - state ? gtk_widget_show(gtk_handle()) : gtk_widget_hide(gtk_handle()); -} - -void pWidget::hide() { - show(false); -} - -bool pWidget::visible() { - return GTK_WIDGET_VISIBLE(gtk_handle()); -} - -uintptr_t pWidget::handle() { - return GDK_WINDOW_XID(gtk_handle()->window); -} - -pWidget::pWidget(Widget &self_) : self(self_) { -} - -/* internal */ - -GtkWidget* pWidget::gtk_handle() { - return 0; -} diff --git a/src/lib/hiro/gtk/widget.hpp b/src/lib/hiro/gtk/widget.hpp deleted file mode 100644 index f5233a6f..00000000 --- a/src/lib/hiro/gtk/widget.hpp +++ /dev/null @@ -1,13 +0,0 @@ -class pWidget { -public: - void show(bool = true); - void hide(); - bool visible(); - uintptr_t handle(); - - Widget &self; - pWidget(Widget&); - - /* internal */ - virtual GtkWidget* gtk_handle(); -}; diff --git a/src/lib/hiro/gtk/window.cpp b/src/lib/hiro/gtk/window.cpp deleted file mode 100644 index e234027c..00000000 --- a/src/lib/hiro/gtk/window.cpp +++ /dev/null @@ -1,325 +0,0 @@ -static gint hiro_pwindow_close(pWindow *p) { - uintptr_t r = p->self.on_close ? p->self.on_close(event_t(event_t::Close, 0, &p->self)) : true; - return !bool(r); -} - -static gboolean hiro_pwindow_expose(pWindow *p) { - cairo_t *context = gdk_cairo_create(p->window->window); - GtkStyle *style = gtk_widget_get_style(p->window); - - double red = double(style->bg[GTK_STATE_NORMAL].red) / 65536.0; - double green = double(style->bg[GTK_STATE_NORMAL].green) / 65536.0; - double blue = double(style->bg[GTK_STATE_NORMAL].blue) / 65536.0; - double alpha = double(p->state.alpha) / 256.0; - - if(phiro().is_composited == true) { - cairo_set_source_rgba(context, red, green, blue, alpha); - } else { - cairo_set_source_rgb(context, red, green, blue); - } - - cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); - cairo_paint(context); - cairo_destroy(context); - return FALSE; -} - -static gint hiro_pwindow_keydown(GtkWidget *w, GdkEventKey *key, pWindow *p) { - if(p && p->self.on_input) { - p->self.on_input(event_t(event_t::Input, - phiro().translate_key(key->keyval) + (1 << 16), - &p->self)); - } - return FALSE; -} - -static gint hiro_pwindow_keyup(GtkWidget *w, GdkEventKey *key, pWindow *p) { - if(p && p->self.on_input) { - p->self.on_input(event_t(event_t::Input, - phiro().translate_key(key->keyval) + (0 << 16), - &p->self)); - } - return FALSE; -} - -void pWindow::create(unsigned style, unsigned width, unsigned height, const char *text) { - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_set_colormap(window, phiro().colormap); - - gtk_window_set_title(GTK_WINDOW(window), text ? text : ""); - gtk_window_set_resizable(GTK_WINDOW(window), false); - gtk_widget_set_app_paintable(window, true); - if(style & Window::AutoCenter) gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS); - g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(hiro_pwindow_close), (gpointer)this); - g_signal_connect_swapped(G_OBJECT(window), "expose_event", G_CALLBACK(hiro_pwindow_expose), (gpointer)this); - g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(hiro_pwindow_keydown), (gpointer)this); - g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(hiro_pwindow_keyup), (gpointer)this); - - menucontainer = gtk_vbox_new(false, 0); - gtk_container_add(GTK_CONTAINER(window), menucontainer); - gtk_widget_show(menucontainer); - - menubar = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(menucontainer), menubar, false, false, 0); - - formcontainer = gtk_fixed_new(); - gtk_widget_set_size_request(formcontainer, width, height); - gtk_box_pack_start(GTK_BOX(menucontainer), formcontainer, true, true, 0); - gtk_widget_show(formcontainer); - - //GTK+ statusbar background can be transparent, depending upon GTK+ theme - //therefore, pack statusbar inside an event box, which always has a background - //this allows pWindow::set_background_color() to change the window color, - //without affecting the statusbar color - statuscontainer = gtk_event_box_new(); - statusbar = gtk_statusbar_new(); - set_default_font(statusbar); - gtk_container_add(GTK_CONTAINER(statuscontainer), statusbar); - gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), false); - gtk_box_pack_start(GTK_BOX(menucontainer), statuscontainer, false, false, 0); - gtk_widget_show(statuscontainer); - - gtk_widget_realize(window); - state.is_fullscreen = false; - state.width = width; - state.height = height; -} - -void pWindow::close() { - gtk_widget_destroy(window); -} - -void pWindow::move(unsigned x, unsigned y) { - gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE); - gtk_window_move(GTK_WINDOW(window), x, y); -} - -void pWindow::resize(unsigned width, unsigned height) { - gtk_widget_set_size_request(formcontainer, width, height); - state.width = width; - state.height = height; -} - -void pWindow::focus() { - gtk_window_present(GTK_WINDOW(window)); -} - -bool pWindow::focused() { - return gtk_window_is_active(GTK_WINDOW(window)); -} - -//gtk_window_(un/)fullscreen() alone does not work well on certain WMs, such as Openbox. -//sometimes, the window will not resize (but will move to the top left.) -//sometimes, the window decorations will not disappear. -//therefore, to be safe, perform some manual window adjustments as well - -void pWindow::fullscreen() { - if(state.is_fullscreen == true) return; - state.is_fullscreen = true; - - gtk_window_fullscreen(GTK_WINDOW(window)); - gtk_window_set_decorated(GTK_WINDOW(window), false); - gtk_widget_set_size_request(window, gdk_screen_width(), gdk_screen_height()); -} - -//note that the size of the window is bound to be at least the size of the formcontainer. -//this is why the window size is set to -1, -1 below, so that it becomes the minimum -//needed to display all of the formcontainer. - -void pWindow::unfullscreen() { - if(state.is_fullscreen == false) return; - state.is_fullscreen = false; - - gtk_widget_set_size_request(formcontainer, state.width, state.height); - gtk_widget_set_size_request(window, -1, -1); - gtk_window_set_decorated(GTK_WINDOW(window), true); - gtk_window_unfullscreen(GTK_WINDOW(window)); -} - -//gtk_widget_size_request() on a window immediately after gtk_window_(un/)fullscreen() -//is unreliable, as it will usually report the previous window size. -//therefore, calculate it manually by using state information. - -unsigned pWindow::get_width() { - if(state.is_fullscreen == false) return state.width; - return gdk_screen_width(); -} - -unsigned pWindow::get_height() { - if(state.is_fullscreen == false) return state.height; - unsigned height = gdk_screen_height(); - - //do not include menubar height in client area height - if(menu.visible()) { - GtkRequisition req; - gtk_widget_size_request(menubar, &req); - height -= req.height; - } - - //do not include statusbar height in client area height - if(status.visible()) { - GtkRequisition req; - gtk_widget_size_request(statusbar, &req); - height -= req.height; - } - - return height; -} - -void pWindow::set_opacity(uint8_t opacity) { - state.alpha = opacity; - if(window) gtk_widget_queue_draw(window); -} - -void pWindow::set_background_color(uint8_t r, uint8_t g, uint8_t b) { - GdkColor color; - color.pixel = (r << 16) | (g << 8) | b; - color.red = (r << 8) | r; - color.green = (g << 8) | g; - color.blue = (b << 8) | b; - gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); -} - -void pWindow::set_icon(unsigned width, unsigned height, const uint32_t *data) { - uint8_t *temp = (uint8_t*)malloc(width * height * 4); - memcpy(temp, data, width * height * 4); - for(unsigned i = 0; i < width * height; i++) { - //ABGR -> ARGB - uint8_t t = temp[i * 4 + 0]; - temp[i * 4 + 0] = temp[i * 4 + 2]; - temp[i * 4 + 2] = t; - } - - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data( - (const guchar*)temp, GDK_COLORSPACE_RGB, - /* has_alpha = */ TRUE, /* bits_per_sample = */ 8, - width, height, /* rowstride = */ width * 4, - /* destroy_fn = */ NULL, /* destroy_fn_data = */ NULL - ); - gtk_window_set_icon(GTK_WINDOW(window), pixbuf); - - g_object_unref(pixbuf); - free(temp); -} - -void pWindow::set_text(const char *text) { - gtk_window_set_title(GTK_WINDOW(window), text ? text : ""); -} - -void pWindow::attach(Window &window, unsigned x, unsigned y) { - window.p.owner = this; - - //GTK+ does not support attaching a window to another window, - //so instead reparent the container from the child window to - //the parent window, and reposition the child window's container - gtk_widget_hide(window.p.window); - gtk_widget_hide(window.p.formcontainer); - gtk_widget_reparent(window.p.formcontainer, formcontainer); - gtk_fixed_move(GTK_FIXED(formcontainer), window.p.formcontainer, x, y); - gtk_widget_show(window.p.formcontainer); -} - -void pWindow::attach(MenuGroup &menugroup) { - gtk_menu_bar_append(menubar, menugroup.p.item); - gtk_widget_show(menubar); -} - -void pWindow::attach(FormControl &formcontrol, unsigned x, unsigned y) { - gtk_fixed_put(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y); -} - -void pWindow::move(Window &window, unsigned x, unsigned y) { - gtk_fixed_move(GTK_FIXED(formcontainer), window.p.gtk_handle(), x, y); -} - -void pWindow::move(FormControl &formcontrol, unsigned x, unsigned y) { - gtk_fixed_move(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y); -} - -/* pWindow -> Menubar */ - -void pWindow::Menubar::show(bool state) { - p.menu_show(state); -} - -void pWindow::Menubar::hide() { - p.menu_hide(); -} - -bool pWindow::Menubar::visible() { - return p.menu_visible(); -} - -pWindow::Menubar::Menubar(pWindow &p_) : p(p_) { -} - -/* pWindow -> Statusbar */ - -void pWindow::Statusbar::set_text(const char *text) { - p.status_set_text(text); -} - -void pWindow::Statusbar::show(bool state) { - p.status_show(state); -} - -void pWindow::Statusbar::hide() { - p.status_hide(); -} - -bool pWindow::Statusbar::visible() { - return p.status_visible(); -} - -pWindow::Statusbar::Statusbar(pWindow &p_) : p(p_) { -} - -pWindow::pWindow(Window &self_) : pWidget(self_), self(self_), menu(*this), status(*this) { - owner = 0; - window = 0; - menubar = 0; - statusbar = 0; - menucontainer = 0; - formcontainer = 0; - statuscontainer = 0; - - state.is_fullscreen = false; - state.width = 0; - state.height = 0; - state.alpha = 255; -} - -/* internal */ - -GtkWidget* pWindow::gtk_handle() { - return owner ? formcontainer : window; -} - -void pWindow::menu_show(bool state) { - state ? gtk_widget_show(menubar) : gtk_widget_hide(menubar); -} - -void pWindow::menu_hide() { - menu_show(false); -} - -bool pWindow::menu_visible() { - return GTK_WIDGET_VISIBLE(menubar); -} - -void pWindow::status_set_text(const char *text) { - gtk_statusbar_pop(GTK_STATUSBAR(statusbar), 1); - gtk_statusbar_push(GTK_STATUSBAR(statusbar), 1, text ? text : ""); -} - -void pWindow::status_show(bool state) { - state ? gtk_widget_show(statusbar) : gtk_widget_hide(statusbar); -} - -void pWindow::status_hide() { - status_show(false); -} - -bool pWindow::status_visible() { - return GTK_WIDGET_VISIBLE(statusbar); -} diff --git a/src/lib/hiro/gtk/window.hpp b/src/lib/hiro/gtk/window.hpp deleted file mode 100644 index 08880f17..00000000 --- a/src/lib/hiro/gtk/window.hpp +++ /dev/null @@ -1,71 +0,0 @@ -class pWindow : public pWidget { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void close(); - void move(unsigned x, unsigned y); - void resize(unsigned width, unsigned height); - void focus(); - bool focused(); - void fullscreen(); - void unfullscreen(); - unsigned get_width(); - unsigned get_height(); - void set_opacity(uint8_t opacity); - void set_background_color(uint8_t r, uint8_t g, uint8_t b); - void set_icon(unsigned width, unsigned height, const uint32_t *data); - void set_text(const char *text = ""); - void attach(Window &window, unsigned x, unsigned y); - void attach(MenuGroup &menugroup); - void attach(FormControl &formcontrol, unsigned x, unsigned y); - void move(Window &window, unsigned x, unsigned y); - void move(FormControl &formcontrol, unsigned x, unsigned y); - - class Statusbar { - public: - void set_text(const char *text = ""); - void show(bool = true); - void hide(); - bool visible(); - - pWindow &p; - Statusbar(pWindow&); - } status; - - class Menubar { - public: - void show(bool = true); - void hide(); - bool visible(); - - pWindow &p; - Menubar(pWindow&); - } menu; - - Window &self; - pWindow(Window&); - - /* internal */ - pWindow *owner; //0 = no owner (default) - GtkWidget *window; - GtkWidget *menubar; - GtkWidget *statusbar; - GtkWidget *menucontainer; - GtkWidget *formcontainer; - GtkWidget *statuscontainer; - GtkWidget* gtk_handle(); - struct { - bool is_fullscreen; - unsigned width; - unsigned height; - unsigned alpha; - } state; - - void menu_show(bool = true); - void menu_hide(); - bool menu_visible(); - - void status_set_text(const char *text = ""); - void status_show(bool = true); - void status_hide(); - bool status_visible(); -}; diff --git a/src/lib/hiro/hiro.cpp b/src/lib/hiro/hiro.cpp deleted file mode 100644 index 252f4210..00000000 --- a/src/lib/hiro/hiro.cpp +++ /dev/null @@ -1,274 +0,0 @@ -#include "hiro.hpp" -using namespace nall; - -#if defined(_WIN32) - #include "win/hiro.cpp" -#else - #include "gtk/hiro.cpp" -#endif - -namespace libhiro { - -/* Hiro (singleton) */ - -void Hiro::init() { p.init(); } -void Hiro::term() { p.term(); } -bool Hiro::run() { return p.run(); } -bool Hiro::pending() { return p.pending(); } -bool Hiro::folder_select(Window *focus, char *filename, const char *path) { return p.folder_select(focus, filename, path); } -bool Hiro::file_open(Window *focus, char *filename, const char *path, const char *filter) { return p.file_open(focus, filename, path, filter); } -bool Hiro::file_save(Window *focus, char *filename, const char *path, const char *filter) { return p.file_save(focus, filename, path, filter); } -unsigned Hiro::screen_width() { return p.screen_width(); } -unsigned Hiro::screen_height() { return p.screen_height(); } -void Hiro::enable_screensaver() { p.enable_screensaver(); } -void Hiro::disable_screensaver() { p.disable_screensaver(); } -Hiro& Hiro::handle() { static Hiro hiro; return hiro; } -Hiro::Hiro() : p(*new pHiro(*this)) {} -Hiro::~Hiro() { delete &p; } -Hiro& hiro() { return Hiro::handle(); } - -/* Widget */ - -void Widget::show(bool state) { p.show(state); } -void Widget::hide() { p.hide(); } -bool Widget::visible() { return p.visible(); } -uintptr_t Widget::handle() { return p.handle(); } -Widget::Widget() : p(*new pWidget(*this)) { type = WidgetType; } -Widget::Widget(pWidget &p_) : p(p_) { type = WidgetType; } -Widget::~Widget() { delete &p; } - -/* Widget -> Window */ - -void Window::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -void Window::close() { p.close(); } -void Window::move(unsigned x, unsigned y) { p.move(x, y); } -void Window::resize(unsigned width, unsigned height) { p.resize(width, height); } -void Window::focus() { p.focus(); } -bool Window::focused() { return p.focused(); } -void Window::fullscreen() { p.fullscreen(); } -void Window::unfullscreen() { p.unfullscreen(); } -unsigned Window::get_width() { return p.get_width(); } -unsigned Window::get_height() { return p.get_height(); } -void Window::set_opacity(uint8_t opacity) { p.set_opacity(opacity); } -void Window::set_background_color(uint8_t r, uint8_t g, uint8_t b) { p.set_background_color(r, g, b); } -void Window::set_icon(unsigned width, unsigned height, const uint32_t *data) { p.set_icon(width, height, data); } -void Window::set_text(const char *text) { p.set_text(text); } -void Window::attach(Window &window, unsigned x, unsigned y) { p.attach(window, x, y); } -void Window::attach(MenuGroup &menugroup) { p.attach(menugroup); } -void Window::attach(FormControl &formcontrol, unsigned x, unsigned y) { p.attach(formcontrol, x, y); } -void Window::move(Window &window, unsigned x, unsigned y) { p.move(window, x, y); } -void Window::move(FormControl &formcontrol, unsigned x, unsigned y) { p.move(formcontrol, x, y); } - -void Window::Menubar::show(bool state) { p.menu.show(state); } -void Window::Menubar::hide() { p.menu.hide(); } -bool Window::Menubar::visible() { return p.menu.visible(); } -Window::Menubar::Menubar(pWindow &p_) : p(p_) {} - -void Window::Statusbar::set_text(const char *text) { p.status.set_text(text); } -void Window::Statusbar::show(bool state) { p.status.show(state); } -void Window::Statusbar::hide() { p.status.hide(); } -bool Window::Statusbar::visible() { return p.status.visible(); } -Window::Statusbar::Statusbar(pWindow &p_) : p(p_) {} - -Window::Window() : - base_from_member(*new pWindow(*this)), - Widget(base_from_member::value), - p(base_from_member::value), - menu(base_from_member::value), - status(base_from_member::value) { type = WindowType; } - -/* Widget -> MenuControl */ - -void MenuControl::enable(bool state) { p.enable(state); } -void MenuControl::disable() { p.disable(); } -bool MenuControl::enabled() { return p.enabled(); } -MenuControl::MenuControl() : - base_from_member(*new pMenuControl(*this)), - Widget(base_from_member::value), - p(base_from_member::value) { type = MenuControlType; } -MenuControl::MenuControl(pMenuControl &p_) : - base_from_member(p_), - Widget(base_from_member::value), - p(base_from_member::value) { type = MenuControlType; } - -/* Widget -> MenuControl -> MenuGroup */ - -MenuGroup& MenuGroup::create(const char *text) { p.create(text); return *this; } -void MenuGroup::attach(MenuControl &menucontrol) { p.attach(menucontrol); } -MenuGroup::MenuGroup() : - base_from_member(*new pMenuGroup(*this)), - MenuControl(base_from_member::value), - p(base_from_member::value) { type = MenuGroupType; } - -/* Widget -> MenuControl -> MenuItem */ - -MenuItem& MenuItem::create(const char *text) { p.create(text); return *this; } -MenuItem::MenuItem() : - base_from_member(*new pMenuItem(*this)), - MenuControl(base_from_member::value), - p(base_from_member::value) { type = MenuItemType; } - -/* Widget -> MenuControl -> MenuCheckItem */ - -MenuCheckItem& MenuCheckItem::create(const char *text) { p.create(text); return *this; } -void MenuCheckItem::check(bool state) { state ? p.check() : p.uncheck(); } -void MenuCheckItem::uncheck() { p.uncheck(); } -bool MenuCheckItem::checked() { return p.checked(); } -MenuCheckItem::MenuCheckItem() : - base_from_member(*new pMenuCheckItem(*this)), - MenuControl(base_from_member::value), - p(base_from_member::value) { type = MenuCheckItemType; } - -/* Widget -> MenuControl -> MenuRadioItem */ - -MenuRadioItem& MenuRadioItem::create(MenuRadioItemGroup &group, const char *text) { p.create(group, text); return *this; } -void MenuRadioItem::check() { p.check(); } -bool MenuRadioItem::checked() { return p.checked(); } -MenuRadioItem::MenuRadioItem() : - base_from_member(*new pMenuRadioItem(*this)), - MenuControl(base_from_member::value), - p(base_from_member::value) { type = MenuRadioItemType; } - -/* Widget -> MenuControl -> MenuSeparator */ - -MenuSeparator& MenuSeparator::create() { p.create(); return *this; } -MenuSeparator::MenuSeparator() : - base_from_member(*new pMenuSeparator(*this)), - MenuControl(base_from_member::value), - p(base_from_member::value) { type = MenuSeparatorType; } - -/* Widget -> FormControl */ - -void FormControl::resize(unsigned width, unsigned height) { p.resize(width, height); } -void FormControl::focus() { p.focus(); } -bool FormControl::focused() { return p.focused(); } -void FormControl::enable(bool state) { p.enable(state); } -void FormControl::disable() { p.disable(); } -bool FormControl::enabled() { return p.enabled(); } -FormControl::FormControl() : - base_from_member(*new pFormControl(*this)), - Widget(base_from_member::value), - p(base_from_member::value) { type = FormControlType; } -FormControl::FormControl(pFormControl &p_) : - base_from_member(p_), - Widget(base_from_member::value), - p(base_from_member::value) { type = FormControlType; } - -/* Widget -> FormControl -> Frame */ - -void Frame::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -void Frame::set_text(const char *text) { p.set_text(text); } -Frame::Frame() : - base_from_member(*new pFrame(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = FrameType; } - -/* Widget -> FormControl -> Canvas */ - -void Canvas::create(unsigned style, unsigned width, unsigned height) { p.create(style, width, height); } -void Canvas::redraw() { p.redraw(); } -uint32_t* Canvas::buffer() { return p.buffer(); } -Canvas::Canvas() : - base_from_member(*new pCanvas(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = CanvasType; } - -/* Widget -> FormControl -> Label */ - -void Label::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -void Label::set_text(const char *text) { p.set_text(text); } -Label::Label() : - base_from_member(*new pLabel(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = LabelType; } - -/* Widget -> FormControl -> Button */ - -void Button::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -void Button::set_text(const char *text) { p.set_text(text); } -Button::Button() : - base_from_member(*new pButton(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = ButtonType; } - -/* Widget -> FormControl -> Checkbox */ - -void Checkbox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -void Checkbox::set_text(const char *text) { p.set_text(text); } -void Checkbox::check(bool state) { state ? p.check() : p.uncheck(); } -void Checkbox::uncheck() { p.uncheck(); } -bool Checkbox::checked() { return p.checked(); } -Checkbox::Checkbox() : - base_from_member(*new pCheckbox(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = CheckboxType; } - -/* Widget -> FormControl -> Radiobox */ - -void Radiobox::create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text) { p.create(group, style, width, height, text); } -void Radiobox::set_text(const char *text) { p.set_text(text); } -void Radiobox::check() { p.check(); } -bool Radiobox::checked() { return p.checked(); } -Radiobox::Radiobox() : - base_from_member(*new pRadiobox(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = RadioboxType; } - -/* Widget -> FormControl -> Editbox */ - -void Editbox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -unsigned Editbox::get_text(char *text, unsigned length) { return p.get_text(text, length); } -void Editbox::set_text(const char *text) { p.set_text(text); } -Editbox::Editbox() : - base_from_member(*new pEditbox(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = EditboxType; } - -/* Widget -> FormControl -> Listbox */ - -void Listbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) { p.create(style, width, height, columns, text); } -void Listbox::autosize_columns() { p.autosize_columns(); } -void Listbox::set_column_width(unsigned column, unsigned width) { p.set_column_width(column, width); } -void Listbox::add_item(const char *text) { p.add_item(text); } -void Listbox::set_item(unsigned index, const char *text) { p.set_item(index, text); } -int Listbox::get_selection() { return p.get_selection(); } -void Listbox::set_selection(int index) { p.set_selection(index); } -void Listbox::reset() { p.reset(); } -Listbox::Listbox() : - base_from_member(*new pListbox(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = ListboxType; } - -/* Widget -> FormControl -> Combobox */ - -void Combobox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); } -void Combobox::add_item(const char *text) { p.add_item(text); } -int Combobox::get_selection() { return p.get_selection(); } -void Combobox::set_selection(int index) { p.set_selection(index); } -void Combobox::reset() { p.reset(); } -Combobox::Combobox() : - base_from_member(*new pCombobox(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = ComboboxType; } - -/* Widget -> FormControl -> Progressbar */ - -void Progressbar::create(unsigned style, unsigned width, unsigned height) { p.create(style, width, height); } -unsigned Progressbar::get_progress() { return p.get_progress(); } -void Progressbar::set_progress(unsigned progress) { p.set_progress(progress); } -Progressbar::Progressbar() : - base_from_member(*new pProgressbar(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = ProgressbarType; } - -/* Widget -> FormControl -> Slider */ - -void Slider::create(unsigned style, unsigned width, unsigned height, unsigned length) { p.create(style, width, height, length); } -unsigned Slider::get_position() { return p.get_position(); } -void Slider::set_position(unsigned position) { p.set_position(position); } -Slider::Slider() : - base_from_member(*new pSlider(*this)), - FormControl(base_from_member::value), - p(base_from_member::value) { type = SliderType; } - -} //namespace libhiro diff --git a/src/lib/hiro/hiro.hpp b/src/lib/hiro/hiro.hpp deleted file mode 100644 index 1b0576c0..00000000 --- a/src/lib/hiro/hiro.hpp +++ /dev/null @@ -1,538 +0,0 @@ -/* - hiro - version: 0.008.1 (2008-11-02) - author: byuu - license: public domain -*/ - -#ifndef HIRO_H -#define HIRO_H - -#include -#include -#include -#include -#include -#include -#include - -extern char* realpath(const char*, char*); -extern char* userpath(char*); -int mkdir(const char*); - -namespace libhiro { - -class pHiro; -class pWidget; - class pWindow; - class pMenuControl; - class pMenuGroup; - class pMenuItem; - class pMenuCheckItem; - class pMenuRadioItem; - class pMenuSeparator; - class pFormControl; - class pFrame; - class pCanvas; - class pLabel; - class pButton; - class pCheckbox; - class pRadiobox; - class pEditbox; - class pListbox; - class pCombobox; - class pProgressbar; - class pSlider; - -#define pFriends \ - friend class pHiro; \ - friend class pWidget; \ - friend class pWindow; \ - friend class pMenuControl; \ - friend class pMenuGroup; \ - friend class pMenuItem; \ - friend class pMenuCheckItem; \ - friend class pMenuRadioItem; \ - friend class pMenuSeparator; \ - friend class pFormControl; \ - friend class pFrame; \ - friend class pCanvas; \ - friend class pLabel; \ - friend class pButton; \ - friend class pCheckbox; \ - friend class pRadiobox; \ - friend class pEditbox; \ - friend class pListbox; \ - friend class pCombobox; \ - friend class pProgressbar; \ - friend class pSlider - -class Hiro; -class Widget; - class Window; - class MenuControl; - class MenuGroup; - class MenuItem; - class MenuCheckItem; - class MenuRadioItem; - class MenuSeparator; - class FormControl; - class Frame; - class Canvas; - class Label; - class Button; - class Checkbox; - class Radiobox; - class Editbox; - class Listbox; - class Combobox; - class Progressbar; - class Slider; - -typedef nall::array MenuRadioItemGroup; -typedef nall::array RadioboxGroup; - -struct event_t { - enum type_t { - Close, - Block, - Input, - Change, - Tick, - Activate, - } type; - uintptr_t param; - Widget *widget; - - event_t(type_t type_, uintptr_t param_ = 0, Widget *widget_ = 0) : - type(type_), param(param_), widget(widget_) {} -}; - -class Hiro : nall::noncopyable { -public: - void init(); - void term(); - bool run(); - bool pending(); - - bool folder_select(Window *focus, char *filename, const char *path = ""); - bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = ""); - bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = ""); - - unsigned screen_width(); - unsigned screen_height(); - - void enable_screensaver(); - void disable_screensaver(); - - static Hiro& handle(); - Hiro(); - ~Hiro(); - -private: - pFriends; - pHiro &p; -}; - -Hiro& hiro(); - -class Widget : nall::noncopyable { -public: - enum Type { - WidgetType, - WindowType, - MenuControlType, - MenuGroupType, - MenuItemType, - MenuCheckItemType, - MenuRadioItemType, - MenuSeparatorType, - FormControlType, - FrameType, - CanvasType, - LabelType, - ButtonType, - CheckboxType, - RadioboxType, - EditboxType, - ListboxType, - ComboboxType, - ProgressbarType, - SliderType, - } type; - - void show(bool = true); - void hide(); - bool visible(); - - uintptr_t handle(); - - Widget(); - ~Widget(); - -protected: - Widget(pWidget&); - -private: - pFriends; - pWidget &p; -}; - -class Window : private nall::base_from_member, public Widget { -public: - enum Style { - AutoCenter = 1 << 1, - }; - - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void close(); - void move(unsigned x, unsigned y); - void resize(unsigned width, unsigned height); - void focus(); - bool focused(); - void fullscreen(); - void unfullscreen(); - unsigned get_width(); - unsigned get_height(); - void set_opacity(uint8_t opacity); - void set_background_color(uint8_t r, uint8_t g, uint8_t b); - void set_icon(unsigned width, unsigned height, const uint32_t *data); - void set_status_text(const char *text = ""); - void set_text(const char *text = ""); - void attach(Window &window, unsigned x, unsigned y); - void attach(MenuGroup &menugroup); - void attach(FormControl &formcontrol, unsigned x, unsigned y); - void move(Window &window, unsigned x, unsigned y); - void move(FormControl &formcontrol, unsigned x, unsigned y); - - class Menubar { - public: - void show(bool = true); - void hide(); - bool visible(); - - pWindow &p; - Menubar(pWindow&); - } menu; - - class Statusbar { - public: - void set_text(const char *text = ""); - void show(bool = true); - void hide(); - bool visible(); - - pWindow &p; - Statusbar(pWindow&); - } status; - - nall::function on_close; - nall::function on_block; - nall::function on_input; - - Window(); - -private: - pFriends; - pWindow &p; -}; - -class MenuControl : public nall::base_from_member, public Widget { -public: - void enable(bool = true); - void disable(); - bool enabled(); - - MenuControl(); - -protected: - MenuControl(pMenuControl&); - -private: - pFriends; - pMenuControl &p; -}; - -class MenuGroup : public nall::base_from_member, public MenuControl { -public: - MenuGroup& create(const char *text); - void attach(MenuControl &menucontrol); - MenuGroup(); - -private: - pFriends; - pMenuGroup &p; -}; - -class MenuItem : public nall::base_from_member, public MenuControl { -public: - MenuItem& create(const char *text); - MenuItem(); - - nall::function on_tick; - -private: - pFriends; - pMenuItem &p; -}; - -class MenuCheckItem : public nall::base_from_member, public MenuControl { -public: - MenuCheckItem& create(const char *text); - void check(bool = true); - void uncheck(); - bool checked(); - MenuCheckItem(); - - nall::function on_tick; - -private: - pFriends; - pMenuCheckItem &p; -}; - -class MenuRadioItem : public nall::base_from_member, public MenuControl { -public: - MenuRadioItem& create(MenuRadioItemGroup &group, const char *text); - void check(); - bool checked(); - MenuRadioItem(); - - nall::function on_tick; - -private: - pFriends; - pMenuRadioItem &p; -}; - -class MenuSeparator : public nall::base_from_member, public MenuControl { -public: - MenuSeparator& create(); - MenuSeparator(); - -private: - pFriends; - pMenuSeparator &p; -}; - -class FormControl : private nall::base_from_member, public Widget { -public: - void resize(unsigned width, unsigned height); - void focus(); - bool focused(); - void enable(bool = true); - void disable(); - bool enabled(); - - FormControl(); - -protected: - FormControl(pFormControl&); - -private: - pFriends; - pFormControl &p; -}; - -class Frame : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - Frame(); - -private: - pFriends; - pFrame &p; -}; - -class Canvas : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height); - void redraw(); - uint32_t* buffer(); - - Canvas(); - - nall::function on_input; - -private: - pFriends; - pCanvas &p; -}; - -class Label : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - Label(); - -private: - pFriends; - pLabel &p; -}; - -class Button : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - nall::function on_tick; - - Button(); - -private: - pFriends; - pButton &p; -}; - -class Checkbox : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - void check(bool = true); - void uncheck(); - bool checked(); - - nall::function on_tick; - - Checkbox(); - -private: - pFriends; - pCheckbox &p; -}; - -class Radiobox : private nall::base_from_member, public FormControl { -public: - void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - void check(); - bool checked(); - - nall::function on_tick; - - Radiobox(); - -private: - pFriends; - pRadiobox &p; -}; - -class Editbox : private nall::base_from_member, public FormControl { -public: - enum Style { - Multiline = 1 << 1, - Readonly = 1 << 2, - - HorizontalScrollAuto = 0, - HorizontalScrollAlways = 1 << 3, - HorizontalScrollNever = 1 << 4, - - VerticalScrollAuto = 0, - VerticalScrollAlways = 1 << 5, - VerticalScrollNever = 1 << 6, - }; - - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - unsigned get_text(char *text, unsigned length = -1U); - void set_text(const char *text = ""); - - nall::function on_change; - - Editbox(); - -private: - pFriends; - pEditbox &p; -}; - -class Listbox : private nall::base_from_member, public FormControl { -public: - enum Style { - Header = 1 << 1, - - HorizontalScrollAuto = 0, - HorizontalScrollAlways = 1 << 2, - HorizontalScrollNever = 1 << 3, - - VerticalScrollAuto = 0, - VerticalScrollAlways = 1 << 4, - VerticalScrollNever = 1 << 5, - }; - - void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = ""); - void autosize_columns(); - void set_column_width(unsigned column, unsigned width); - void add_item(const char *text); - void set_item(unsigned index, const char *text); - int get_selection(); - void set_selection(int index); - void reset(); - - nall::function on_change; - nall::function on_activate; - - Listbox(); - -private: - pFriends; - pListbox &p; -}; - -class Combobox : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void add_item(const char *text); - int get_selection(); - void set_selection(int index); - void reset(); - - nall::function on_change; - - Combobox(); - -private: - pFriends; - pCombobox &p; -}; - -class Progressbar : private nall::base_from_member, public FormControl { -public: - void create(unsigned style, unsigned width, unsigned height); - unsigned get_progress(); - void set_progress(unsigned progress); - - Progressbar(); - -private: - pFriends; - pProgressbar &p; -}; - -class Slider : private nall::base_from_member, public FormControl { -public: - enum Style { - Horizontal = 0, - Vertical = 1 << 1, - }; - - void create(unsigned style, unsigned width, unsigned height, unsigned length); - unsigned get_position(); - void set_position(unsigned position); - - nall::function on_change; - - Slider(); - -private: - pFriends; - pSlider &p; -}; - -#undef pFriends - -} //namespace libhiro - -#endif //ifndef HIRO_H diff --git a/src/lib/hiro/win/button.cpp b/src/lib/hiro/win/button.cpp deleted file mode 100644 index 6681e3f4..00000000 --- a/src/lib/hiro/win/button.cpp +++ /dev/null @@ -1,14 +0,0 @@ -void pButton::create(unsigned style, unsigned width, unsigned height, const char *text) { - hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE, - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); -} - -void pButton::set_text(const char *text) { - SetWindowText(hwnd, utf16(text)); -} - -pButton::pButton(Button &self_) : pFormControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/button.hpp b/src/lib/hiro/win/button.hpp deleted file mode 100644 index 40723916..00000000 --- a/src/lib/hiro/win/button.hpp +++ /dev/null @@ -1,8 +0,0 @@ -class pButton : public pFormControl { -public: - Button &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - pButton(Button&); -}; diff --git a/src/lib/hiro/win/canvas.cpp b/src/lib/hiro/win/canvas.cpp deleted file mode 100644 index 9446ab2f..00000000 --- a/src/lib/hiro/win/canvas.cpp +++ /dev/null @@ -1,52 +0,0 @@ -void pCanvas::create(unsigned style, unsigned width, unsigned height) { - hwnd = CreateWindow(L"hiro_window", L"", WS_CHILD, - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); - resize(width, height); - ShowWindow(hwnd, SW_NORMAL); -} - -void pCanvas::redraw() { - PAINTSTRUCT ps; - BeginPaint(hwnd, &ps); - SetDIBitsToDevice(ps.hdc, 0, 0, iwidth, iheight, 0, 0, 0, iheight, (void*)ibuffer, &bmi, DIB_RGB_COLORS); - EndPaint(hwnd, &ps); - InvalidateRect(hwnd, 0, FALSE); -} - -uint32_t* pCanvas::buffer() { - return ibuffer; -} - -pCanvas::pCanvas(Canvas &self_) : pFormControl(self_), self(self_) { - ibuffer = 0; - ipitch = 0; - memset(&bmi, 0, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; -} - -pCanvas::~pCanvas() { - if(ibuffer) free(ibuffer); -} - -/* internal */ - -void pCanvas::resize(unsigned width, unsigned height) { - if(ibuffer) free(ibuffer); - - ipitch = width * sizeof(uint32_t); - iwidth = width; - iheight = height; - ibuffer = (uint32_t*)malloc(ipitch * height); - memset(ibuffer, 0, ipitch * height); - - bmi.bmiHeader.biWidth = width; - bmi.bmiHeader.biHeight = -height; //use negative height to tell GDI not to flip bitmap vertically - bmi.bmiHeader.biSizeImage = ipitch * height; - - pFormControl::resize(width, height); -} diff --git a/src/lib/hiro/win/canvas.hpp b/src/lib/hiro/win/canvas.hpp deleted file mode 100644 index b990f050..00000000 --- a/src/lib/hiro/win/canvas.hpp +++ /dev/null @@ -1,16 +0,0 @@ -class pCanvas : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height); - void redraw(); - uint32_t* buffer(); - - Canvas &self; - pCanvas(Canvas&); - ~pCanvas(); - - /* internal */ - BITMAPINFO bmi; - uint32_t *ibuffer; - unsigned ipitch, iwidth, iheight; - void resize(unsigned width, unsigned height); -}; diff --git a/src/lib/hiro/win/checkbox.cpp b/src/lib/hiro/win/checkbox.cpp deleted file mode 100644 index 4b7c9270..00000000 --- a/src/lib/hiro/win/checkbox.cpp +++ /dev/null @@ -1,25 +0,0 @@ -void pCheckbox::create(unsigned style, unsigned width, unsigned height, const char *text) { - hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX, - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); -} - -void pCheckbox::set_text(const char *text) { - SetWindowText(hwnd, utf16(text)); -} - -void pCheckbox::check(bool state) { - SendMessage(hwnd, BM_SETCHECK, (WPARAM)(state ? TRUE : FALSE), 0); -} - -void pCheckbox::uncheck() { - check(false); -} - -bool pCheckbox::checked() { - return SendMessage(hwnd, BM_GETCHECK, 0, 0); -} - -pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/checkbox.hpp b/src/lib/hiro/win/checkbox.hpp deleted file mode 100644 index 5a6902f4..00000000 --- a/src/lib/hiro/win/checkbox.hpp +++ /dev/null @@ -1,11 +0,0 @@ -class pCheckbox : public pFormControl { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - void check(bool state = true); - void uncheck(); - bool checked(); - - Checkbox &self; - pCheckbox(Checkbox&); -}; diff --git a/src/lib/hiro/win/combobox.cpp b/src/lib/hiro/win/combobox.cpp deleted file mode 100644 index 477df9e5..00000000 --- a/src/lib/hiro/win/combobox.cpp +++ /dev/null @@ -1,38 +0,0 @@ -void pCombobox::create(unsigned style, unsigned width, unsigned height, const char *text) { - hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"COMBOBOX", L"", - WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, - 0, 0, width, 200, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); - - //fix combobox height - //CreateWindow height parameter represents dropdown window height; auto-sizes control based on current font setting - //GetWindowRect returns true height (~22px), CB_GETITEMHEIGHT returns text height (~16px) - //difference = WindowHeight - CB_GETITEMHEIGHT - //CB_SETITEMHEIGHT to height - difference, so that height matches requested height perfectly - RECT rc; - GetWindowRect(hwnd, &rc); - unsigned adjusted_height = height - ((rc.bottom - rc.top) - SendMessage(hwnd, CB_GETITEMHEIGHT, (WPARAM)-1, 0)); - SendMessage(hwnd, CB_SETITEMHEIGHT, (WPARAM)-1, adjusted_height); -} - -void pCombobox::add_item(const char *text) { - SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)(wchar_t*)utf16(text)); - if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) set_selection(0); -} - -int pCombobox::get_selection() { - return SendMessage(hwnd, CB_GETCURSEL, 0, 0); -} - -void pCombobox::set_selection(int index) { - SendMessage(hwnd, CB_SETCURSEL, combobox_selection = index, 0); -} - -void pCombobox::reset() { - SendMessage(hwnd, CB_RESETCONTENT, 0, 0); -} - -pCombobox::pCombobox(Combobox &self_) : pFormControl(self_), self(self_) { - combobox_selection = 0; -} diff --git a/src/lib/hiro/win/combobox.hpp b/src/lib/hiro/win/combobox.hpp deleted file mode 100644 index 6404791b..00000000 --- a/src/lib/hiro/win/combobox.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class pCombobox : public pFormControl { -public: - Combobox &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void add_item(const char *text); - int get_selection(); - void set_selection(int index); - void reset(); - - pCombobox(Combobox&); - - /* internal */ - int combobox_selection; -}; diff --git a/src/lib/hiro/win/editbox.cpp b/src/lib/hiro/win/editbox.cpp deleted file mode 100644 index 9f3e2fa7..00000000 --- a/src/lib/hiro/win/editbox.cpp +++ /dev/null @@ -1,84 +0,0 @@ -void pEditbox::create(unsigned style, unsigned width, unsigned height, const char *text) { - bool multiline = style & Editbox::Multiline; - bool readonly = style & Editbox::Readonly; - unsigned vscroll = (style & Editbox::VerticalScrollAlways) ? WS_VSCROLL : - (style & Editbox::VerticalScrollNever ) ? 0 : - ES_AUTOVSCROLL; - unsigned hscroll = (style & Editbox::HorizontalScrollAlways) ? WS_HSCROLL : - (style & Editbox::HorizontalScrollNever ) ? 0 : - ES_AUTOHSCROLL; - - autovscroll = (vscroll == ES_AUTOVSCROLL); - - hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"", - WS_CHILD | WS_VISIBLE | vscroll | hscroll | - (multiline == true ? ES_MULTILINE | ES_WANTRETURN : WS_TABSTOP) | - (readonly == true ? ES_READONLY : 0), - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); - set_text(text); - update(); -} - -void pEditbox::resize(unsigned width, unsigned height) { - pFormControl::resize(width, height); - update(); -} - -void pEditbox::set_text(const char *text) { - string temp = text ? text : ""; - temp.replace("\r", ""); - temp.replace("\n", "\r\n"); - SetWindowText(hwnd, utf16(temp)); - update(); -} - -unsigned pEditbox::get_text(char *text, unsigned length) { - wchar_t *buffer = new wchar_t[length + 1]; - GetWindowText(hwnd, buffer, length); - string temp = (const char*)utf8(buffer); - delete[] buffer; - temp.replace("\r", ""); - strlcpy(text, temp, length); - return strlen(text); -} - -pEditbox::pEditbox(Editbox &self_) : pFormControl(self_), self(self_) { - autovscroll = false; -} - -//======== -//internal -//======== - -//WS_VSCROLL always shows the scrollbar; -//ES_AUTOVSCROLL never shows the scrollbar but allows unlimited text; -//no style disallows more text than what fits in the window. -// -//below routine simulates the effect of allowing unlimited text, but only -//showing the scrollbar when it is needed. not sure how to simulate this effect -//for horizontal scrolling at this time. -// -//below routine should be called whenever the font, text or window size is -//modified. -void pEditbox::update() { - if(autovscroll == true) { - //determine how many lines of text this control allows - RECT rect; - SendMessage(hwnd, EM_GETRECT, 0, (LPARAM)&rect); - unsigned height = rect.bottom - rect.top; - - //determine the height of a single line of text - HDC hdc = GetDC(hwnd); - SelectObject(hdc, phiro().default_font); - DrawText(hdc, L"byuu", -1, &rect, DT_CALCRECT); - ReleaseDC(hwnd, hdc); - unsigned lineheight = rect.bottom - rect.top; - - //only show the scrollbar when there are more lines of text - //than the control can show at once. - unsigned linecount = SendMessage(hwnd, EM_GETLINECOUNT, 0, 0); - ShowScrollBar(hwnd, SB_VERT, linecount > (height / lineheight)); - } -} diff --git a/src/lib/hiro/win/editbox.hpp b/src/lib/hiro/win/editbox.hpp deleted file mode 100644 index 512091fb..00000000 --- a/src/lib/hiro/win/editbox.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class pEditbox : public pFormControl { -public: - Editbox &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void resize(unsigned width, unsigned height); - unsigned get_text(char *text, unsigned length = -1U); - void set_text(const char *text = ""); - - pEditbox(Editbox&); - -//private: - bool autovscroll; - void update(); -}; diff --git a/src/lib/hiro/win/formcontrol.cpp b/src/lib/hiro/win/formcontrol.cpp deleted file mode 100644 index 27950331..00000000 --- a/src/lib/hiro/win/formcontrol.cpp +++ /dev/null @@ -1,45 +0,0 @@ -void pFormControl::resize(unsigned width, unsigned height) { - SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE); -} - -void pFormControl::focus() { - SetFocus(hwnd); -} - -bool pFormControl::focused() { - return true; //fixme -} - -void pFormControl::enable(bool state) { - EnableWindow(hwnd, state); -} - -void pFormControl::disable() { - enable(false); -} - -bool pFormControl::enabled() { - return !(GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED); -} - -uintptr_t pFormControl::handle() { - return (uintptr_t)hwnd; -} - -pFormControl::pFormControl(FormControl &self_) : pWidget(self_), self(self_) { - hwnd = 0; -} - -/* internal */ - -void pFormControl::show(bool state) { - ShowWindow(hwnd, state ? SW_NORMAL : SW_HIDE); -} - -void pFormControl::hide() { - show(false); -} - -bool pFormControl::visible() { - return GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE; -} diff --git a/src/lib/hiro/win/formcontrol.hpp b/src/lib/hiro/win/formcontrol.hpp deleted file mode 100644 index dcafb9f7..00000000 --- a/src/lib/hiro/win/formcontrol.hpp +++ /dev/null @@ -1,20 +0,0 @@ -class pFormControl : public pWidget { -public: - virtual void resize(unsigned width, unsigned height); - void focus(); - bool focused(); - void enable(bool = true); - void disable(); - bool enabled(); - uintptr_t handle(); - - virtual void show(bool = true); - virtual void hide(); - virtual bool visible(); - - FormControl &self; - pFormControl(FormControl&); - - /* internal */ - HWND hwnd; -}; diff --git a/src/lib/hiro/win/frame.cpp b/src/lib/hiro/win/frame.cpp deleted file mode 100644 index 2fbfd587..00000000 --- a/src/lib/hiro/win/frame.cpp +++ /dev/null @@ -1,13 +0,0 @@ -void pFrame::create(unsigned style, unsigned width, unsigned height, const char *text) { - hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_VISIBLE | BS_GROUPBOX, - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); -} - -void pFrame::set_text(const char *text) { - SetWindowText(hwnd, utf16(text)); -} - -pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/frame.hpp b/src/lib/hiro/win/frame.hpp deleted file mode 100644 index d79c43e2..00000000 --- a/src/lib/hiro/win/frame.hpp +++ /dev/null @@ -1,8 +0,0 @@ -class pFrame : public pFormControl { -public: - Frame &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - pFrame(Frame&); -}; diff --git a/src/lib/hiro/win/hiro.cpp b/src/lib/hiro/win/hiro.cpp deleted file mode 100644 index 36f55e27..00000000 --- a/src/lib/hiro/win/hiro.cpp +++ /dev/null @@ -1,444 +0,0 @@ -#include "hiro.hpp" -#include "port.cpp" - -namespace libhiro { - -LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM); - -#include "keymap.cpp" -#include "widget.cpp" - #include "window.cpp" - #include "menucontrol.cpp" - #include "menugroup.cpp" - #include "menuitem.cpp" - #include "menucheckitem.cpp" - #include "menuradioitem.cpp" - #include "menuseparator.cpp" - #include "formcontrol.cpp" - #include "frame.cpp" - #include "canvas.cpp" - #include "label.cpp" - #include "button.cpp" - #include "checkbox.cpp" - #include "radiobox.cpp" - #include "editbox.cpp" - #include "listbox.cpp" - #include "combobox.cpp" - #include "progressbar.cpp" - #include "slider.cpp" - -void pHiro::init() { - memset(&osversioninfo, 0, sizeof(OSVERSIONINFO)); - osversioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osversioninfo); - - WNDCLASS wc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); - wc.hCursor = LoadCursor(0, IDC_ARROW); - wc.hIcon = LoadIcon(0, IDI_APPLICATION); - wc.hInstance = GetModuleHandle(0); - wc.lpfnWndProc = phiro_wndproc; - wc.lpszClassName = L"hiro_window"; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); - - InitCommonControls(); - default_hwnd = CreateWindow(L"hiro_window", L"", WS_POPUP, 0, 0, 640, 480, 0, 0, GetModuleHandle(0), 0); - default_font = create_font("Tahoma", 8); - black_brush = CreateSolidBrush(RGB(0, 0, 0)); -} - -void pHiro::term() { - DeleteObject(black_brush); -} - -bool pHiro::run() { - MSG msg; - if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { - //TODO: IsDialogMessage() does not clear keyboard buffer, but is required for tab key to work ... - #if defined(HIRO_WIN_TABSTOP) - if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) { - #endif - TranslateMessage(&msg); - DispatchMessage(&msg); - #if defined(HIRO_WIN_TABSTOP) - } - #endif - } - return pending(); -} - -bool pHiro::pending() { - MSG msg; - return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); -} - -bool pHiro::folder_select(Window *focus, char *filename, const char *path) { - wchar_t wfilename[_MAX_PATH] = L""; - strcpy(filename, ""); - BROWSEINFO bi; - bi.hwndOwner = focus ? focus->p.hwnd : 0; - bi.pidlRoot = NULL; - bi.pszDisplayName = wfilename; - bi.lpszTitle = L""; - bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS; - bi.lpfn = NULL; - bi.lParam = 0; - bi.iImage = 0; - bool result = false; - LPITEMIDLIST pidl = SHBrowseForFolder(&bi); - if(pidl) { - if(SHGetPathFromIDList(pidl, wfilename)) { - result = true; - IMalloc *imalloc = 0; - if(SUCCEEDED(SHGetMalloc(&imalloc))) { - imalloc->Free(pidl); - imalloc->Release(); - } - } - } - strcpy(filename, utf8(wfilename)); - return result; -} - -bool pHiro::file_open(Window *focus, char *filename, const char *path, const char *filter) { - string dir, f; - dir = path ? path : ""; - dir.replace("/", "\\"); - - lstring type, part; - type.split("\n", filter); - for(int i = 0; i < type.size(); i++) { - part.split("\t", type[i]); - if(part.size() != 2) continue; - - f.append(part[0]); - f.append(" ("); - f.append(part[1]); - f.append(")\t"); - part[1].replace(",", ";"); - f.append(part[1]); - f.append("\t"); - } - - utf16 wfilter(f); - utf16 wdir(dir); - wchar_t wfilename[_MAX_PATH] = L""; - - wchar_t *p = wfilter; - while(*p != L'\0') { - if(*p == L'\t') *p = L'\0'; - p++; - } - - OPENFILENAME ofn; - strcpy(filename, ""); - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = focus ? focus->p.hwnd : 0; - ofn.lpstrFilter = wfilter; - ofn.lpstrInitialDir = wdir; - ofn.lpstrFile = wfilename; - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; - ofn.lpstrDefExt = L""; - - bool result = GetOpenFileName(&ofn); - strcpy(filename, utf8(wfilename)); - return result; -} - -bool pHiro::file_save(Window *focus, char *filename, const char *path, const char *filter) { - string dir, f; - dir = path ? path : ""; - dir.replace("/", "\\"); - - lstring type, part; - type.split("\n", filter); - for(int i = 0; i < type.size(); i++) { - part.split("\t", type[i]); - if(part.size() != 2) continue; - - f.append(part[0]); - f.append(" ("); - f.append(part[1]); - f.append(")\t"); - part[1].replace(",", ";"); - f.append(part[1]); - f.append("\t"); - } - - utf16 wfilter(f); - utf16 wdir(dir); - wchar_t wfilename[_MAX_PATH] = L""; - - wchar_t *p = wfilter; - while(*p != L'\0') { - if(*p == L'\t') *p = L'\0'; - p++; - } - - OPENFILENAME ofn; - strcpy(filename, ""); - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = focus ? focus->p.hwnd : 0; - ofn.lpstrFilter = wfilter; - ofn.lpstrInitialDir = wdir; - ofn.lpstrFile = wfilename; - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; - ofn.lpstrDefExt = L""; - - bool result = GetSaveFileName(&ofn); - strcpy(filename, utf8(wfilename)); - return result; -} - -unsigned pHiro::screen_width() { - return GetSystemMetrics(SM_CXSCREEN); -} - -unsigned pHiro::screen_height() { - return GetSystemMetrics(SM_CYSCREEN); -} - -void pHiro::enable_screensaver() { - is_screensaver_enabled = true; -} - -void pHiro::disable_screensaver() { - is_screensaver_enabled = false; -} - -pHiro& pHiro::handle() { - return hiro().p; -} - -pHiro::pHiro(Hiro &self_) : self(self_) { - is_screensaver_enabled = true; -} - -pHiro& phiro() { - return pHiro::handle(); -} - -/* internal */ - -HFONT pHiro::create_font(const char *name, unsigned size) { - return CreateFont( - -(size * 96.0 / 72.0 + 0.5), //96 = DPI - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - utf16(name) - ); -} - -Widget* pHiro::get_widget(unsigned instance) { - Widget *widget = 0; - for(unsigned i = 0; i < widget_list.size(); i++) { - if(widget_list[i]->p.instance != instance) continue; - widget = widget_list[i]; - break; - } - return widget; -} - -LRESULT CALLBACK phiro_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - return phiro().wndproc(hwnd, msg, wparam, lparam); -} - -LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - pWidget *p = (pWidget*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - switch(msg) { - case WM_SYSCOMMAND: { - switch(wparam) { - case SC_SCREENSAVE: - case SC_MONITORPOWER: { - if(is_screensaver_enabled == false) return FALSE; - //fallthrough to DefWindowProc() - } break; - } - } break; - - case WM_SIZE: { - if(!p || p->self.type != Widget::WindowType) break; - SendMessage(((pWindow*)p)->hstatus, WM_SIZE, 0, 0); //the control itself auto-sizes after receiving WM_SIZE - } break; - - case WM_CLOSE: { - if(!p || p->self.type != Widget::WindowType) break; - Window &w = ((pWindow*)p)->self; - if(w.on_close) return (bool)w.on_close(event_t(event_t::Close, 0, &w)); - return TRUE; //true = destroy window - } break; - - case WM_ENTERMENULOOP: { - if(!p || p->self.type != Widget::WindowType) break; - Window &w = ((pWindow*)p)->self; - if(w.on_block) w.on_block(event_t(event_t::Block, 0, &w)); - } break; - - case WM_KEYDOWN: { - if(!p || p->self.type != Widget::WindowType) break; - Window &w = ((pWindow*)p)->self; - if(w.on_input) w.on_input(event_t(event_t::Input, translate_key(wparam) + (1 << 16), &w)); - } break; - - case WM_KEYUP: { - if(!p || p->self.type != Widget::WindowType) break; - Window &w = ((pWindow*)p)->self; - if(w.on_input) w.on_input(event_t(event_t::Input, translate_key(wparam) + (0 << 16), &w)); - } break; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: { - if(!p || p->self.type != Widget::CanvasType) break; - Canvas &canvas = ((pCanvas*)p)->self; - uintptr_t param = (msg == WM_LBUTTONDOWN ? mouse::button + 0 : mouse::button + 1) + (1 << 16); - if(canvas.on_input) canvas.on_input(event_t(event_t::Input, param, &canvas)); - } break; - - case WM_LBUTTONUP: - case WM_RBUTTONUP: { - if(!p || p->self.type != Widget::CanvasType) break; - Canvas &canvas = ((pCanvas*)p)->self; - uintptr_t param = (msg == WM_LBUTTONUP ? mouse::button + 0 : mouse::button + 1) + (0 << 16); - if(canvas.on_input) canvas.on_input(event_t(event_t::Input, param, &canvas)); - } break; - - case WM_ERASEBKGND: { - if(!p) break; - HBRUSH brush = 0; - if(p->self.type == Widget::WindowType) brush = ((pWindow*)p)->background; - if(p->self.type == Widget::CanvasType) brush = phiro().black_brush; - if(!brush) break; - RECT rc; - GetClientRect(hwnd, &rc); - PAINTSTRUCT ps; - BeginPaint(hwnd, &ps); - FillRect(ps.hdc, &rc, brush); - EndPaint(hwnd, &ps); - return TRUE; - } break; - - case WM_PAINT: { - if(p && p->self.type == Widget::CanvasType) ((pCanvas*)p)->redraw(); - } break; - - case WM_COMMAND: { - Widget *widget = get_widget(LOWORD(wparam)); - if(!widget) break; - - switch(widget->type) { - case Widget::MenuItemType: { - MenuItem &w = (MenuItem&)*widget; - if(w.on_tick) w.on_tick(event_t(event_t::Tick, 0, &w)); - } break; - - case Widget::MenuCheckItemType: { - MenuCheckItem &w = (MenuCheckItem&)*widget; - w.check(!w.checked()); //invert check state - if(w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w)); - } break; - - case Widget::MenuRadioItemType: { - MenuRadioItem &w = (MenuRadioItem&)*widget; - bool checked = w.checked(); - w.check(); - if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w)); - } break; - - case Widget::ButtonType: { - Button &w = (Button&)*widget; - if(w.on_tick) w.on_tick(event_t(event_t::Tick, 0, &w)); - } break; - - case Widget::CheckboxType: { - Checkbox &w = (Checkbox&)*widget; - w.check(!w.checked()); //invert check state - if(w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w)); - } break; - - case Widget::RadioboxType: { - Radiobox &w = (Radiobox&)*widget; - bool checked = w.checked(); - w.check(); - if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w)); - } break; - - case Widget::EditboxType: { - Editbox &editbox = (Editbox&)*widget; - if(HIWORD(wparam) == EN_CHANGE) { - editbox.p.update(); //called to dynamically display vertical scrollbar if needed - if(editbox.on_change) editbox.on_change(event_t(event_t::Change, 0, &editbox)); - } - } break; - - case Widget::ComboboxType: { - Combobox &combobox = (Combobox&)*widget; - if(HIWORD(wparam) == CBN_SELCHANGE) { - if(combobox.p.combobox_selection == combobox.get_selection()) break; - if(combobox.on_change) combobox.on_change(event_t(event_t::Change, combobox.p.combobox_selection = combobox.get_selection(), &combobox)); - } - } break; - } - } break; - - case WM_HSCROLL: - case WM_VSCROLL: { - Widget *widget = get_widget(GetDlgCtrlID((HWND)lparam)); - if(!widget) break; - - switch(widget->type) { - case Widget::SliderType: { - Slider &slider = (Slider&)*widget; - if(slider.p.slider_position == slider.get_position()) break; - if(slider.on_change) slider.on_change(event_t(event_t::Change, slider.p.slider_position = slider.get_position(), &slider)); - } break; - } - } break; - - case WM_NOTIFY: { - Widget *widget = get_widget(LOWORD(wparam)); - if(!widget) break; - - switch(widget->type) { - case Widget::ListboxType: { - Listbox &listbox = (Listbox&)*widget; - LPNMHDR nmhdr = (LPNMHDR)lparam; - LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam; - - if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) { - //LVN_ITEMCHANGED is sent whenever an item gains or loses either focus or selection; - //it does not send a special message to indicate that no items are focused or selected. - //it will send two messages when a different item gains selection -- the first to remove - //focus from the old item, the second to set selection to the new item. - //hiro sends only one message whenever an item changed (eg gained selection), - //including for deselection of all items. below code adapts win32 model to hiro model. - //(focused means an item has a dotted outline box around it, but is not highlighted.) - //(selected means an item is highlighted.) - if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) { - listbox.p.lostfocus = true; - } else { - if((!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED)) - || (listbox.p.lostfocus == false && listbox.get_selection() == -1)) { - if(listbox.on_change) listbox.on_change(event_t(event_t::Change, listbox.get_selection(), &listbox)); - } - listbox.p.lostfocus = false; - } - } else if(nmhdr->code == LVN_ITEMACTIVATE) { - if(listbox.on_activate) listbox.on_activate(event_t(event_t::Activate, listbox.get_selection(), &listbox)); - } - } break; - } - } break; - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -} //namespace libhiro diff --git a/src/lib/hiro/win/hiro.hpp b/src/lib/hiro/win/hiro.hpp deleted file mode 100644 index 4a688050..00000000 --- a/src/lib/hiro/win/hiro.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef HIRO_WIN_H -#define HIRO_WIN_H - -#undef WINVER -#undef _WIN32_WINNT -#undef _WIN32_IE -#undef NOMINMAX -#undef _NO_OLDNAMES - -#define WINVER 0x0501 -#define _WIN32_WINNT 0x0501 -#define _WIN32_IE 0x0600 -#define NOMINMAX -#define _NO_OLDNAMES - -#define mkdir _mkdir -#define UNICODE -#include -#include -#include -#include -#include -#undef mkdir - -#include -using nall::min; -using nall::max; - -#include -#define utf8 nall::utf8_t -#define utf16 nall::utf16_t - -extern int hiromain(int argc, const char *const argv[]); - -namespace libhiro { - -#include "widget.hpp" - #include "window.hpp" - #include "menucontrol.hpp" - #include "menugroup.hpp" - #include "menuitem.hpp" - #include "menucheckitem.hpp" - #include "menuradioitem.hpp" - #include "menuseparator.hpp" - #include "formcontrol.hpp" - #include "frame.hpp" - #include "canvas.hpp" - #include "label.hpp" - #include "button.hpp" - #include "checkbox.hpp" - #include "radiobox.hpp" - #include "editbox.hpp" - #include "listbox.hpp" - #include "combobox.hpp" - #include "progressbar.hpp" - #include "slider.hpp" - -class pHiro { -public: - Hiro &self; - void init(); - void term(); - bool run(); - bool pending(); - - bool folder_select(Window *focus, char *filename, const char *path = ""); - bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = ""); - bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = ""); - - unsigned screen_width(); - unsigned screen_height(); - - void enable_screensaver(); - void disable_screensaver(); - - static pHiro& handle(); - pHiro(Hiro&); - - /* internal */ - OSVERSIONINFO osversioninfo; - bool is_screensaver_enabled; - HWND default_hwnd; //default parent window for all windowless controls - HFONT default_font; //default font for all controls - HBRUSH black_brush; //used for Canvas background - HFONT create_font(const char *name, unsigned size); - - array widget_list; - Widget* get_widget(unsigned instance); - LRESULT wndproc(HWND, UINT, WPARAM, LPARAM); - uint16_t translate_key(unsigned key); -}; - -pHiro& phiro(); - -} //namsepace libhiro - -#endif //ifndef HIRO_WIN_H diff --git a/src/lib/hiro/win/keymap.cpp b/src/lib/hiro/win/keymap.cpp deleted file mode 100644 index 274b5c42..00000000 --- a/src/lib/hiro/win/keymap.cpp +++ /dev/null @@ -1,74 +0,0 @@ -uint16_t pHiro::translate_key(unsigned key) { - switch(key) { - case VK_ESCAPE: return keyboard::escape; - - case VK_F1: return keyboard::f1; - case VK_F2: return keyboard::f2; - case VK_F3: return keyboard::f3; - case VK_F4: return keyboard::f4; - case VK_F5: return keyboard::f5; - case VK_F6: return keyboard::f6; - case VK_F7: return keyboard::f7; - case VK_F8: return keyboard::f8; - case VK_F9: return keyboard::f9; - case VK_F10: return keyboard::f10; - case VK_F11: return keyboard::f11; - case VK_F12: return keyboard::f12; - - case VK_TAB: return keyboard::tab; - case VK_RETURN: return keyboard::return_; - case VK_SPACE: return keyboard::spacebar; - - case '0': return keyboard::num_0; - case '1': return keyboard::num_1; - case '2': return keyboard::num_2; - case '3': return keyboard::num_3; - case '4': return keyboard::num_4; - case '5': return keyboard::num_5; - case '6': return keyboard::num_6; - case '7': return keyboard::num_7; - case '8': return keyboard::num_8; - case '9': return keyboard::num_9; - - case VK_INSERT: return keyboard::insert; - case VK_DELETE: return keyboard::delete_; - case VK_HOME: return keyboard::home; - case VK_END: return keyboard::end; - case VK_PRIOR: return keyboard::page_up; - case VK_NEXT: return keyboard::page_down; - - case 'A': return keyboard::a; - case 'B': return keyboard::b; - case 'C': return keyboard::c; - case 'D': return keyboard::d; - case 'E': return keyboard::e; - case 'F': return keyboard::f; - case 'G': return keyboard::g; - case 'H': return keyboard::h; - case 'I': return keyboard::i; - case 'J': return keyboard::j; - case 'K': return keyboard::k; - case 'L': return keyboard::l; - case 'M': return keyboard::m; - case 'N': return keyboard::n; - case 'O': return keyboard::o; - case 'P': return keyboard::p; - case 'Q': return keyboard::q; - case 'R': return keyboard::r; - case 'S': return keyboard::s; - case 'T': return keyboard::t; - case 'U': return keyboard::u; - case 'V': return keyboard::v; - case 'W': return keyboard::w; - case 'X': return keyboard::x; - case 'Y': return keyboard::y; - case 'Z': return keyboard::z; - - case VK_UP: return keyboard::up; - case VK_DOWN: return keyboard::down; - case VK_LEFT: return keyboard::left; - case VK_RIGHT: return keyboard::right; - } - - return keyboard::none; -} diff --git a/src/lib/hiro/win/label.cpp b/src/lib/hiro/win/label.cpp deleted file mode 100644 index 4c004ff9..00000000 --- a/src/lib/hiro/win/label.cpp +++ /dev/null @@ -1,13 +0,0 @@ -void pLabel::create(unsigned style, unsigned width, unsigned height, const char *text) { - hwnd = CreateWindow(L"STATIC", utf16(text), WS_CHILD | WS_VISIBLE, - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); -} - -void pLabel::set_text(const char *text) { - SetWindowText(hwnd, utf16(text)); -} - -pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/label.hpp b/src/lib/hiro/win/label.hpp deleted file mode 100644 index 0e93e956..00000000 --- a/src/lib/hiro/win/label.hpp +++ /dev/null @@ -1,8 +0,0 @@ -class pLabel : public pFormControl { -public: - Label &self; - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - - pLabel(Label&); -}; diff --git a/src/lib/hiro/win/listbox.cpp b/src/lib/hiro/win/listbox.cpp deleted file mode 100644 index 4d32e6f5..00000000 --- a/src/lib/hiro/win/listbox.cpp +++ /dev/null @@ -1,98 +0,0 @@ -void pListbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) { - bool header = style & Listbox::Header; - unsigned hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL : - (style & Listbox::HorizontalScrollNever) ? 0 : - 0; - unsigned vscroll = (style & Listbox::VerticalScrollAlways) ? WS_VSCROLL : - (style & Listbox::VerticalScrollNever) ? 0 : - 0; - hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"", - WS_CHILD | WS_TABSTOP | WS_VISIBLE | - LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll | - (header ? 0 : LVS_NOCOLUMNHEADER), - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); - ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT); - - lstring list; - list.split("\t", columns ? columns : ""); - column_count = list.size(); - for(unsigned i = 0; i < list.size(); i++) { - LVCOLUMN column; - column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM; - column.fmt = LVCFMT_LEFT; - column.iSubItem = list.size(); - utf16 ulist(list[i]); - column.pszText = ulist; - ListView_InsertColumn(hwnd, i, &column); - } - - if(text && *text) { - list.split("\n", text); - for(unsigned i = 0; i < list.size(); i++) add_item(list[i]); - } - autosize_columns(); -} - -void pListbox::autosize_columns() { - for(unsigned i = 0; i < column_count; i++) { - ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER); - } -} - -void pListbox::set_column_width(unsigned column, unsigned width) { - ListView_SetColumnWidth(hwnd, column, width); -} - -void pListbox::add_item(const char *text) { - lstring list; - list.split("\t", text ? text : ""); - LVITEM item; - unsigned pos = ListView_GetItemCount(hwnd); - item.mask = LVIF_TEXT; - item.iItem = pos; - item.iSubItem = 0; - utf16 wtext(list[0]); - item.pszText = wtext; - ListView_InsertItem(hwnd, &item); - - for(unsigned i = 1; i < list.size(); i++) { - utf16 wtext(list[i]); - ListView_SetItemText(hwnd, pos, i, wtext); - } -} - -void pListbox::set_item(unsigned index, const char *text) { - lstring list; - list.split("\t", text ? text : ""); - for(unsigned i = 0; i < list.size(); i++) { - utf16 wtext(list[i]); - ListView_SetItemText(hwnd, index, i, wtext); - } -} - -int pListbox::get_selection() { - unsigned count = ListView_GetItemCount(hwnd); - for(unsigned i = 0; i < count; i++) { - if(ListView_GetItemState(hwnd, i, LVIS_SELECTED)) return i; - } - return -1; -} - -void pListbox::set_selection(int index) { - unsigned count = ListView_GetItemCount(hwnd); - for(unsigned i = 0; i < count; i++) { - ListView_SetItemState(hwnd, i, LVIS_FOCUSED, (i == index) ? LVIS_FOCUSED : 0); - ListView_SetItemState(hwnd, i, LVIS_SELECTED, (i == index) ? LVIS_SELECTED : 0); - } -} - -void pListbox::reset() { - ListView_DeleteAllItems(hwnd); -} - -pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) { - column_count = 0; - lostfocus = false; //used for message parsing -} diff --git a/src/lib/hiro/win/listbox.hpp b/src/lib/hiro/win/listbox.hpp deleted file mode 100644 index bb00bd1b..00000000 --- a/src/lib/hiro/win/listbox.hpp +++ /dev/null @@ -1,18 +0,0 @@ -class pListbox : public pFormControl { -public: - Listbox &self; - void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = ""); - void autosize_columns(); - void set_column_width(unsigned column, unsigned width); - void add_item(const char *text); - void set_item(unsigned index, const char *text); - int get_selection(); - void set_selection(int index); - void reset(); - - pListbox(Listbox&); - - /* internal */ - unsigned column_count; - bool lostfocus; -}; diff --git a/src/lib/hiro/win/menucheckitem.cpp b/src/lib/hiro/win/menucheckitem.cpp deleted file mode 100644 index bb816a72..00000000 --- a/src/lib/hiro/win/menucheckitem.cpp +++ /dev/null @@ -1,40 +0,0 @@ -void pMenuCheckItem::create(const char *text_) { - text = strdup(text_); -} - -void pMenuCheckItem::check(bool state) { - CheckMenuItem(parent, instance, state ? MF_CHECKED : MF_UNCHECKED); -} - -void pMenuCheckItem::uncheck() { - check(false); -} - -bool pMenuCheckItem::checked() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, instance, false, &info); - return info.fState & MFS_CHECKED; -} - -void pMenuCheckItem::enable(bool state) { - EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED)); -} - -void pMenuCheckItem::disable() { - enable(false); -} - -bool pMenuCheckItem::enabled() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, instance, false, &info); - return info.fState & MFS_ENABLED; -} - -pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/menucheckitem.hpp b/src/lib/hiro/win/menucheckitem.hpp deleted file mode 100644 index bf8a944c..00000000 --- a/src/lib/hiro/win/menucheckitem.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class pMenuCheckItem : public pMenuControl { -public: - void create(const char *text = ""); - void check(bool state = true); - void uncheck(); - bool checked(); - - void enable(bool = true); - void disable(); - bool enabled(); - - MenuCheckItem &self; - pMenuCheckItem(MenuCheckItem&); -}; diff --git a/src/lib/hiro/win/menucontrol.cpp b/src/lib/hiro/win/menucontrol.cpp deleted file mode 100644 index 55d3de55..00000000 --- a/src/lib/hiro/win/menucontrol.cpp +++ /dev/null @@ -1,18 +0,0 @@ -void pMenuControl::enable(bool) { -} - -void pMenuControl::disable() { -} - -bool pMenuControl::enabled() { - return true; -} - -pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) { - parent = 0; - text = 0; -} - -pMenuControl::~pMenuControl() { - if(text) free(text); -} diff --git a/src/lib/hiro/win/menucontrol.hpp b/src/lib/hiro/win/menucontrol.hpp deleted file mode 100644 index bdf5e874..00000000 --- a/src/lib/hiro/win/menucontrol.hpp +++ /dev/null @@ -1,14 +0,0 @@ -class pMenuControl : public pWidget { -public: - virtual void enable(bool = true); - virtual void disable(); - virtual bool enabled(); - - MenuControl &self; - pMenuControl(MenuControl&); - virtual ~pMenuControl(); - - /* internal */ - HMENU parent; - char *text; -}; diff --git a/src/lib/hiro/win/menugroup.cpp b/src/lib/hiro/win/menugroup.cpp deleted file mode 100644 index 7e82ae9f..00000000 --- a/src/lib/hiro/win/menugroup.cpp +++ /dev/null @@ -1,48 +0,0 @@ -void pMenuGroup::create(const char *text_) { - group = CreatePopupMenu(); - text = strdup(text_); -} - -void pMenuGroup::attach(MenuControl &menucontrol) { - switch(menucontrol.type) { - case Widget::MenuGroupType: { - AppendMenu(group, MF_STRING | MF_POPUP, (unsigned)((MenuGroup&)menucontrol).p.group, utf16(menucontrol.p.text)); - } break; - - case Widget::MenuItemType: - case Widget::MenuCheckItemType: - case Widget::MenuRadioItemType: { - AppendMenu(group, MF_STRING, menucontrol.p.instance, utf16(menucontrol.p.text)); - if(menucontrol.type == Widget::MenuRadioItemType && ((MenuRadioItem&)menucontrol).p.create_checked) { - CheckMenuItem(group, menucontrol.p.instance, MF_CHECKED); - } - } break; - - case Widget::MenuSeparatorType: { - AppendMenu(group, MF_SEPARATOR, menucontrol.p.instance, L""); - } break; - } - - menucontrol.p.parent = group; -} - -void pMenuGroup::enable(bool state) { - EnableMenuItem(parent, (unsigned)group, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED)); -} - -void pMenuGroup::disable() { - enable(false); -} - -bool pMenuGroup::enabled() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, (unsigned)group, false, &info); - return info.fState & MFS_ENABLED; -} - -pMenuGroup::pMenuGroup(MenuGroup &self_) : pMenuControl(self_), self(self_) { - group = 0; -} diff --git a/src/lib/hiro/win/menugroup.hpp b/src/lib/hiro/win/menugroup.hpp deleted file mode 100644 index 4a0cfd2a..00000000 --- a/src/lib/hiro/win/menugroup.hpp +++ /dev/null @@ -1,15 +0,0 @@ -class pMenuGroup : public pMenuControl { -public: - MenuGroup &self; - void create(const char *text); - void attach(MenuControl &menucontrol); - - void enable(bool = true); - void disable(); - bool enabled(); - - pMenuGroup(MenuGroup&); - - /* internal */ - HMENU group; -}; diff --git a/src/lib/hiro/win/menuitem.cpp b/src/lib/hiro/win/menuitem.cpp deleted file mode 100644 index 9b90657c..00000000 --- a/src/lib/hiro/win/menuitem.cpp +++ /dev/null @@ -1,23 +0,0 @@ -void pMenuItem::create(const char *text_) { - text = strdup(text_); -} - -void pMenuItem::enable(bool state) { - EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED)); -} - -void pMenuItem::disable() { - enable(false); -} - -bool pMenuItem::enabled() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, instance, false, &info); - return info.fState & MFS_ENABLED; -} - -pMenuItem::pMenuItem(MenuItem &self_) : pMenuControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/menuitem.hpp b/src/lib/hiro/win/menuitem.hpp deleted file mode 100644 index 7166ffbe..00000000 --- a/src/lib/hiro/win/menuitem.hpp +++ /dev/null @@ -1,11 +0,0 @@ -class pMenuItem : public pMenuControl { -public: - void create(const char *text = ""); - - void enable(bool = true); - void disable(); - bool enabled(); - - MenuItem &self; - pMenuItem(MenuItem&); -}; diff --git a/src/lib/hiro/win/menuradioitem.cpp b/src/lib/hiro/win/menuradioitem.cpp deleted file mode 100644 index f379ad7a..00000000 --- a/src/lib/hiro/win/menuradioitem.cpp +++ /dev/null @@ -1,41 +0,0 @@ -void pMenuRadioItem::create(MenuRadioItemGroup &group_, const char *text_) { - group = group_; - text = strdup(text_); - create_checked = (group[0] == &self); -} - -void pMenuRadioItem::check() { - for(unsigned i = 0; i < group.size(); i++) { - CheckMenuItem(parent, group[i]->p.instance, (group[i] == &self) ? MF_CHECKED : MF_UNCHECKED); - } -} - -bool pMenuRadioItem::checked() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, instance, false, &info); - return info.fState & MFS_CHECKED; -} - -void pMenuRadioItem::enable(bool state) { - EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED)); -} - -void pMenuRadioItem::disable() { - enable(false); -} - -bool pMenuRadioItem::enabled() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, instance, false, &info); - return info.fState & MFS_ENABLED; -} - -pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) { - create_checked = false; -} diff --git a/src/lib/hiro/win/menuradioitem.hpp b/src/lib/hiro/win/menuradioitem.hpp deleted file mode 100644 index 58f5b6c5..00000000 --- a/src/lib/hiro/win/menuradioitem.hpp +++ /dev/null @@ -1,17 +0,0 @@ -class pMenuRadioItem : public pMenuControl { -public: - void create(MenuRadioItemGroup &group, const char *text = ""); - void check(); - bool checked(); - - void enable(bool = true); - void disable(); - bool enabled(); - - MenuRadioItem &self; - pMenuRadioItem(MenuRadioItem&); - - /* internal */ - MenuRadioItemGroup group; - bool create_checked; -}; diff --git a/src/lib/hiro/win/menuseparator.cpp b/src/lib/hiro/win/menuseparator.cpp deleted file mode 100644 index eecdb0c1..00000000 --- a/src/lib/hiro/win/menuseparator.cpp +++ /dev/null @@ -1,22 +0,0 @@ -void pMenuSeparator::create() { -} - -void pMenuSeparator::enable(bool state) { - EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED)); -} - -void pMenuSeparator::disable() { - enable(false); -} - -bool pMenuSeparator::enabled() { - MENUITEMINFO info; - memset(&info, 0, sizeof info); - info.cbSize = sizeof info; - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, instance, false, &info); - return info.fState & MFS_ENABLED; -} - -pMenuSeparator::pMenuSeparator(MenuSeparator &self_) : pMenuControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/menuseparator.hpp b/src/lib/hiro/win/menuseparator.hpp deleted file mode 100644 index 2dd883df..00000000 --- a/src/lib/hiro/win/menuseparator.hpp +++ /dev/null @@ -1,11 +0,0 @@ -class pMenuSeparator : public pMenuControl { -public: - MenuSeparator &self; - void create(); - - void enable(bool = true); - void disable(); - bool enabled(); - - pMenuSeparator(MenuSeparator&); -}; diff --git a/src/lib/hiro/win/port.cpp b/src/lib/hiro/win/port.cpp deleted file mode 100644 index deedf6a4..00000000 --- a/src/lib/hiro/win/port.cpp +++ /dev/null @@ -1,40 +0,0 @@ -char* realpath(const char *file_name, char *resolved_name) { - wchar_t filename[_MAX_PATH] = L""; - _wfullpath(filename, utf16(file_name), _MAX_PATH); - strcpy(resolved_name, utf8(filename)); - return resolved_name; -} - -char* userpath(char *output) { - wchar_t path[_MAX_PATH] = L""; - SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path); - strcpy(output, utf8(path)); - return output; -} - -int mkdir(const char *path) { - return _wmkdir(utf16(path)); -} - -int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { - //argv[] is in 7-bit ANSI format; Unicode characters are converted to '?'s. - //this needs to be converted to UTF-8, eg for realpath(argv[0]) to work. - int argc; - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); - char **argv = new char*[argc]; - for(unsigned i = 0; i < argc; i++) { - argv[i] = new char[_MAX_PATH]; - strcpy(argv[i], utf8(wargv[i])); - } - - libhiro::hiro().init(); - int result = hiromain(argc, argv); - libhiro::hiro().term(); - - for(unsigned i = 0; i < argc; i++) { - delete[] argv[i]; - } - delete[] argv; - - return result; -} diff --git a/src/lib/hiro/win/progressbar.cpp b/src/lib/hiro/win/progressbar.cpp deleted file mode 100644 index f4d57d39..00000000 --- a/src/lib/hiro/win/progressbar.cpp +++ /dev/null @@ -1,20 +0,0 @@ -void pProgressbar::create(unsigned style, unsigned width, unsigned height) { - hwnd = CreateWindow(PROGRESS_CLASS, L"", WS_CHILD | WS_VISIBLE | PBS_SMOOTH, - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); - SendMessage(hwnd, PBM_SETSTEP, MAKEWPARAM(1, 0), 0); -} - -unsigned pProgressbar::get_progress() { - unsigned progress = SendMessage(hwnd, PBM_GETPOS, 0, 0); - return max(0U, min(progress, 100U)); -} - -void pProgressbar::set_progress(unsigned progress) { - progress = max(0U, min(progress, 100U)); - SendMessage(hwnd, PBM_SETPOS, (WPARAM)progress, 0); -} - -pProgressbar::pProgressbar(Progressbar &self_) : pFormControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/progressbar.hpp b/src/lib/hiro/win/progressbar.hpp deleted file mode 100644 index 713fdb12..00000000 --- a/src/lib/hiro/win/progressbar.hpp +++ /dev/null @@ -1,9 +0,0 @@ -class pProgressbar : public pFormControl { -public: - Progressbar &self; - void create(unsigned style, unsigned width, unsigned height); - unsigned get_progress(); - void set_progress(unsigned progress); - - pProgressbar(Progressbar&); -}; diff --git a/src/lib/hiro/win/radiobox.cpp b/src/lib/hiro/win/radiobox.cpp deleted file mode 100644 index bef5dd98..00000000 --- a/src/lib/hiro/win/radiobox.cpp +++ /dev/null @@ -1,24 +0,0 @@ -void pRadiobox::create(RadioboxGroup &group_, unsigned style, unsigned width, unsigned height, const char *text) { - group = group_; - hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_RADIOBUTTON, - 0, 0, width, height, phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0); - if(group[0] == &self) check(); -} - -void pRadiobox::set_text(const char *text) { - SetWindowText(hwnd, utf16(text)); -} - -void pRadiobox::check() { - for(unsigned i = 0; i < group.size(); i++) { - SendMessage(group[i]->p.hwnd, BM_SETCHECK, (WPARAM)(group[i] == &self), 0); - } -} - -bool pRadiobox::checked() { - return SendMessage(hwnd, BM_GETCHECK, 0, 0); -} - -pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self_), self(self_) { -} diff --git a/src/lib/hiro/win/radiobox.hpp b/src/lib/hiro/win/radiobox.hpp deleted file mode 100644 index 4350e882..00000000 --- a/src/lib/hiro/win/radiobox.hpp +++ /dev/null @@ -1,13 +0,0 @@ -class pRadiobox : public pFormControl { -public: - void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = ""); - void set_text(const char *text = ""); - void check(); - bool checked(); - - Radiobox &self; - pRadiobox(Radiobox&); - - /* internal */ - RadioboxGroup group; -}; diff --git a/src/lib/hiro/win/slider.cpp b/src/lib/hiro/win/slider.cpp deleted file mode 100644 index dddb63fd..00000000 --- a/src/lib/hiro/win/slider.cpp +++ /dev/null @@ -1,24 +0,0 @@ -void pSlider::create(unsigned style, unsigned width, unsigned height, unsigned length) { - if(length < 1) length = 1; - - hwnd = CreateWindow(TRACKBAR_CLASS, L"", - WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_NOTICKS | TBS_BOTH | - (style & Slider::Vertical ? TBS_VERT : TBS_HORZ), - 0, 0, width, height, - phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); - SendMessage(hwnd, TBM_SETRANGE, (WPARAM)true, (LPARAM)MAKELONG(0, length - 1)); - SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM)(length >> 3)); - SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)0); -} - -unsigned pSlider::get_position() { - return SendMessage(hwnd, TBM_GETPOS, 0, 0); -} - -void pSlider::set_position(unsigned position) { - SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)(slider_position = position)); -} - -pSlider::pSlider(Slider &self_) : pFormControl(self_), self(self_) { - slider_position = 0; -} diff --git a/src/lib/hiro/win/slider.hpp b/src/lib/hiro/win/slider.hpp deleted file mode 100644 index 6e45e61c..00000000 --- a/src/lib/hiro/win/slider.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class pSlider : public pFormControl { -public: - Slider &self; - void create(unsigned style, unsigned width, unsigned height, unsigned length); - unsigned get_position(); - void set_position(unsigned position); - - pSlider(Slider&); - - /* internal */ - unsigned slider_position; -}; diff --git a/src/lib/hiro/win/widget.cpp b/src/lib/hiro/win/widget.cpp deleted file mode 100644 index ebd09d49..00000000 --- a/src/lib/hiro/win/widget.cpp +++ /dev/null @@ -1,27 +0,0 @@ -void pWidget::show(bool state) { -} - -void pWidget::hide() { -} - -bool pWidget::visible() { - return true; -} - -uintptr_t pWidget::handle() { - return 0; -} - -pWidget::pWidget(Widget &self_) : self(self_) { - instance = instance_counter++; - phiro().widget_list.add(&self); -} - -pWidget::~pWidget() { -} - -/* internal */ - -//100 is the standard start index for control IDs in the Windows API -//avoids duplicate IDs when they are not explicitly set (and are thus 0) -unsigned pWidget::instance_counter = 100; diff --git a/src/lib/hiro/win/widget.hpp b/src/lib/hiro/win/widget.hpp deleted file mode 100644 index 966be052..00000000 --- a/src/lib/hiro/win/widget.hpp +++ /dev/null @@ -1,19 +0,0 @@ -class pWidget { -public: - Widget &self; - virtual void show(bool = true); - virtual void hide(); - virtual bool visible(); - virtual uintptr_t handle(); - - pWidget(Widget&); - virtual ~pWidget(); - - /* internal */ - - //Windows API controls often require a unique ID for each control to identify it. - //Simulate this with an instance counter, so that each Widget has a unique ID. - //In each pWidget() constructor, instance = instance_counter++; is called. - static unsigned instance_counter; - unsigned instance; -}; diff --git a/src/lib/hiro/win/window.cpp b/src/lib/hiro/win/window.cpp deleted file mode 100644 index 44006aba..00000000 --- a/src/lib/hiro/win/window.cpp +++ /dev/null @@ -1,334 +0,0 @@ -void pWindow::create(unsigned style, unsigned width_, unsigned height_, const char *text) { - auto_center = style & Window::AutoCenter; - - RECT rc; - SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); - - hwnd = CreateWindowEx(0, L"hiro_window", utf16(text), - WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, - rc.left, rc.top, width_, height_, - 0, 0, GetModuleHandle(0), 0); - hwndr = CreateWindowEx(0, L"hiro_window", utf16(text), - WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, - rc.left, rc.top, width_, height_, - 0, 0, GetModuleHandle(0), 0); - hmenu = CreateMenu(); - hstatus = CreateWindowEx(0, STATUSCLASSNAME, L"", - WS_CHILD, 0, 0, 0, 0, hwnd, 0, GetModuleHandle(0), 0); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); - - resize(width_, height_); -} - -void pWindow::close() { - CloseWindow(hwnd); -} - -void pWindow::move(unsigned x, unsigned y) { - if(is_fullscreen == true) return; - SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); -} - -void pWindow::resize(unsigned width_, unsigned height_) { - int screen_width = GetSystemMetrics(SM_CXSCREEN); - int screen_height = GetSystemMetrics(SM_CYSCREEN); - - if(is_fullscreen == true) { - SetWindowPos(hwnd, 0, 0, 0, screen_width, screen_height, SWP_NOZORDER | SWP_FRAMECHANGED); - return; - } - - width = width_; - height = height_; - - //set requested window size to hidden window, calculate the difference between - //requested and actual client size area, and then adjust width so that new - //width, height values will set requested client area size. - //AdjustWindowRect() does not properly calculate the height of multi-line menus, - //and thusly is not used. - SetWindowPos(hwndr, 0, 0, 0, width_, height_, SWP_NOMOVE | SWP_NOZORDER); - RECT rc; - GetClientRect(hwndr, &rc); - width_ += width_ - (rc.right - rc.left); - height_ += height_ - (rc.bottom - rc.top); - - if(status.visible()) { - //statusbar does not count as part of window client area width, height - GetClientRect(hstatus, &rc); - height_ += rc.bottom - rc.top; - } - - //if window is larger than the screen size, Windows will hide the window entirely. - //therefore, window must be constrained to fit within the current screen size. - - int x, y; - if(width_ <= screen_width) { - x = (screen_width - width_) >> 1; - } else { - x = 0; - width_ = screen_width; - } - - if(height_ <= screen_height) { - y = (screen_height - height_) >> 1; - } else { - y = 0; - height_ = screen_height; - } - - SetWindowPos(hwnd, 0, x, y, width_, height_, (auto_center ? 0 : SWP_NOMOVE) | SWP_NOZORDER | SWP_FRAMECHANGED); -} - -void pWindow::focus() { - if(visible() == false) show(); - SetFocus(hwnd); -} - -bool pWindow::focused() { - return GetForegroundWindow() == hwnd; -} - -void pWindow::show(bool state) { - if(state == true) { - ShowWindow(hwnd, SW_NORMAL); - SetFocus(hwnd); - } else { - ShowWindow(hwnd, SW_HIDE); - } -} - -void pWindow::hide() { - show(false); -} - -bool pWindow::visible() { - return GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE; -} - -void pWindow::fullscreen() { - if(is_fullscreen == true) return; - is_fullscreen = true; - SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); - resize(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); -} - -void pWindow::unfullscreen() { - if(is_fullscreen == false) return; - is_fullscreen = false; - SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE); - resize(width, height); -} - -unsigned pWindow::get_width() { - RECT rc; - GetClientRect(hwnd, &rc); - return rc.right - rc.left; -} - -unsigned pWindow::get_height() { - RECT rc; - GetClientRect(hwnd, &rc); - if(status.visible() == false) return rc.bottom - rc.top; - //do not include statusbar in client area height - RECT src; - GetClientRect(hstatus, &src); - return (rc.bottom - rc.top) - (src.bottom - src.top); -} - -void pWindow::set_opacity(uint8_t opacity_) { - opacity = opacity_; - if(!hwnd) return; - - if(opacity != 255) { - //enable translucency - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); - SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA); - } else { - //disable transluceny - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); - SetLayeredWindowAttributes(hwnd, 0, 0, 0); - } - - InvalidateRect(hwnd, 0, TRUE); -} - -void pWindow::set_background_color(uint8_t r, uint8_t g, uint8_t b) { - if(background) DeleteObject(background); - background = CreateSolidBrush(RGB(r, g, b)); -} - -void pWindow::set_icon(unsigned width, unsigned height, const uint32_t *data) { - if(hicon) DestroyIcon(hicon); - - uint8_t *mask = (uint8_t*)malloc(width * height / 8); - memset(mask, 0, width * height / 8); - uint8_t *icon = (uint8_t*)malloc(width * height * 4); - memcpy(icon, data, width * height * 4); - - if((phiro().osversioninfo.dwMajorVersion < 5) - || (phiro().osversioninfo.dwMajorVersion == 5 && phiro().osversioninfo.dwMinorVersion < 1)) { - //5.1 and above represents Windows XP or later, which supports 32-bit icons. - //5.0 and below represents Windows 2000 or earlier, which does not support 32-bit icons. - //if running Win2k or prior, alpha channel will be ignored; - //so scale color intensity by alpha level, which gives icons a black background. - //this is because an alpha of 0 (fully transparent) results in a color of 0 (black). - //without this step and alpha ignored, icons lose appearance of anti-aliasing. - for(unsigned i = 0; i < width * height; i++) { - uint8_t a = icon[i * 4 + 3]; - uint8_t r = uint8_t(1.0 / 256.0 * a * icon[i * 4 + 2]); - uint8_t g = uint8_t(1.0 / 256.0 * a * icon[i * 4 + 1]); - uint8_t b = uint8_t(1.0 / 256.0 * a * icon[i * 4 + 0]); - icon[i * 4 + 3] = 0xff; //ignored anyway, but just to be safe ... - icon[i * 4 + 2] = max(0, min(255, r)); //clamp 0 <= color <= 255 ... - icon[i * 4 + 1] = max(0, min(255, g)); //not required, but again ... - icon[i * 4 + 0] = max(0, min(255, b)); //it's better to be safe. - } - } - - hicon = CreateIcon(GetModuleHandle(0), width, height, 1, 32, (const BYTE*)mask, (const BYTE*)icon); - SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); - SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); - - free(mask); - free(icon); -} - -void pWindow::set_text(const char *text) { - SetWindowText(hwnd, utf16(text)); -} - -void pWindow::attach(Window &window, unsigned x, unsigned y) { - if(!window.p.hwnd) return; - - //toplevel window size is larger, because it includes window borders - //read size of window without window borders, and resize upon attach - RECT rc; - GetClientRect(window.p.hwnd, &rc); - - ShowWindow(window.p.hwnd, SW_HIDE); - SetWindowLong(window.p.hwnd, GWL_STYLE, WS_CHILD); - SetWindowLong(window.p.hwnd, GWL_EXSTYLE, WS_EX_CONTROLPARENT); - SetParent(window.p.hwnd, hwnd); - SetWindowPos(window.p.hwnd, 0, x, y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_FRAMECHANGED); - ShowWindow(window.p.hwnd, SW_NORMAL); -} - -void pWindow::attach(MenuGroup &menugroup) { - AppendMenu(hmenu, MF_STRING | MF_POPUP, (unsigned)menugroup.p.group, utf16(menugroup.p.text)); - if(menu_visible() == false) menu_show(); -} - -void pWindow::attach(FormControl &formcontrol, unsigned x, unsigned y) { - SetWindowPos(formcontrol.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - SetParent(formcontrol.p.hwnd, hwnd); - //SetParent() sets Z-order to topmost ... - //this causes WS_TABSTOP property to run through controls "backward" - //by inverting this, the later a control is attached, the later the tab key moves to it - SetWindowPos(formcontrol.p.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); -} - -void pWindow::move(Window &window, unsigned x, unsigned y) { - SetWindowPos(window.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); -} - -void pWindow::move(FormControl &formcontrol, unsigned x, unsigned y) { - SetWindowPos(formcontrol.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); -} - -/* pWindow -> Menubar */ - -void pWindow::Menubar::show(bool state) { - p.menu_show(state); -} - -void pWindow::Menubar::hide() { - p.menu_hide(); -} - -bool pWindow::Menubar::visible() { - return p.menu_visible(); -} - -pWindow::Menubar::Menubar(pWindow &p_) : p(p_) { -} - -/* pWindow -> Statusbar */ - -void pWindow::Statusbar::set_text(const char *text) { - p.status_set_text(text); -} - -void pWindow::Statusbar::show(bool state) { - p.status_show(state); -} - -void pWindow::Statusbar::hide() { - p.status_hide(); -} - -bool pWindow::Statusbar::visible() { - return p.status_visible(); -} - -pWindow::Statusbar::Statusbar(pWindow &p_) : p(p_) { -} - -pWindow::pWindow(Window &self_) : pWidget(self_), self(self_), menu(*this), status(*this) { - hwnd = 0; - hwndr = 0; - hicon = 0; - hmenu = 0; - background = 0; - opacity = 255; - is_fullscreen = false; - auto_center = false; - width = 0; - height = 0; -} - -pWindow::~pWindow() { - if(hicon) DestroyIcon(hicon); - if(background) DeleteObject(background); -} - -/* internal */ - -uintptr_t pWindow::handle() { - return (uintptr_t)hwnd; -} - -void pWindow::menu_show(bool state) { - if(state) { - SetMenu(hwnd, hmenu); - SetMenu(hwndr, hmenu); - } else { - SetMenu(hwnd, 0); - SetMenu(hwndr, 0); - } - resize(width, height); -} - -void pWindow::menu_hide() { - menu_show(false); -} - -bool pWindow::menu_visible() { - return GetMenu(hwnd); -} - -void pWindow::status_set_text(const char *text) { - SendMessage(hstatus, SB_SETTEXT, 0, (LPARAM)(wchar_t*)utf16(text)); -} - -void pWindow::status_show(bool state) { - ShowWindow(hstatus, state ? SW_SHOWNORMAL : SW_HIDE); - resize(width, height); -} - -void pWindow::status_hide() { - status_show(false); -} - -bool pWindow::status_visible() { - return GetWindowLong(hstatus, GWL_STYLE) & WS_VISIBLE; -} diff --git a/src/lib/hiro/win/window.hpp b/src/lib/hiro/win/window.hpp deleted file mode 100644 index 218ae800..00000000 --- a/src/lib/hiro/win/window.hpp +++ /dev/null @@ -1,74 +0,0 @@ -class pWindow : public pWidget { -public: - void create(unsigned style, unsigned width, unsigned height, const char *text = ""); - void close(); - void move(unsigned x, unsigned y); - void resize(unsigned width, unsigned height); - void focus(); - bool focused(); - void fullscreen(); - void unfullscreen(); - unsigned get_width(); - unsigned get_height(); - void set_opacity(uint8_t opacity); - void set_background_color(uint8_t r, uint8_t g, uint8_t b); - void set_icon(unsigned width, unsigned height, const uint32_t *data); - void set_text(const char *text = ""); - void attach(Window &window, unsigned x, unsigned y); - void attach(MenuGroup &menugroup); - void attach(FormControl &formcontrol, unsigned x, unsigned y); - void move(Window &window, unsigned x, unsigned y); - void move(FormControl &formcontrol, unsigned x, unsigned y); - - class Statusbar { - public: - void set_text(const char *text = ""); - void show(bool = true); - void hide(); - bool visible(); - - pWindow &p; - Statusbar(pWindow&); - } status; - - class Menubar { - public: - void show(bool = true); - void hide(); - bool visible(); - - pWindow &p; - Menubar(pWindow&); - } menu; - - Window &self; - pWindow(Window&); - ~pWindow(); - - /* internal */ - HWND hwnd; - HWND hwndr; //hidden window, used as resize assistant - HICON hicon; - HMENU hmenu; - HWND hstatus; - HBRUSH background; - uint8_t opacity; - bool is_fullscreen; - bool auto_center; - unsigned width, height; - - uintptr_t handle(); - - void show(bool = true); - void hide(); - bool visible(); - - void menu_show(bool = true); - void menu_hide(); - bool menu_visible(); - - void status_set_text(const char *text = ""); - void status_show(bool = true); - void status_hide(); - bool status_visible(); -}; diff --git a/src/lib/nall/input.hpp b/src/lib/nall/input.hpp index e6dd4741..033c26be 100644 --- a/src/lib/nall/input.hpp +++ b/src/lib/nall/input.hpp @@ -8,9 +8,11 @@ #include namespace nall { - struct keyboard { + enum { input_none = 0 }; + + template struct keyboard { enum { - none, + none = keyboard::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, @@ -29,54 +31,92 @@ namespace nall { }; }; - struct mouse { - enum { buttons = 8 }; - + template<> struct keyboard<-1> { + enum { count = 16 }; enum { - none = keyboard::limit, + 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; + } + }; + + template struct mouse { + enum { buttons = 8 }; + enum { + none = mouse::limit, x, y, z, button, limit = button + buttons, }; }; - template struct joypad { - enum { axes = 8 }; - enum { buttons = 96 }; + 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::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 struct joypad { + enum { hats = 8, axes = 32, buttons = 96 }; enum { none = joypad::limit, - up, down, left, right, - axis, + hat, + axis = hat + hats, button = axis + axes, limit = button + buttons, }; }; template<> struct joypad<-1> { - enum { count = 16 }; - enum { axes = 8 }; - enum { buttons = 96 }; - + 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, - up, down, left, right, - axis, + hat, + axis = hat + hats, button = axis + axes, length = button + buttons - none, //number of syms per joypad - limit = mouse::limit, + limit = mouse::count - 1>::limit, }; static uint16_t index(unsigned joypad_number, unsigned joypad_enum) { - if(joypad_number >= count) return keyboard::none; + if(joypad_number >= count) return input_none; return limit + joypad_number * length + joypad_enum; } }; enum { input_limit = joypad::count - 1>::limit }; - static const char sym_table[][64] = { - //keyboard + 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", @@ -92,24 +132,37 @@ namespace nall { "up", "down", "left", "right", "tab", "return", "spacebar", "lctrl", "rctrl", "lalt", "ralt", "lshift", "rshift", "lsuper", "rsuper", "menu", - "keyboard.limit", - - //mouse - "mouse.x", "mouse.y", "mouse.z", - "mouse.button00", "mouse.button01", "mouse.button02", "mouse.button03", - "mouse.button04", "mouse.button05", "mouse.button06", "mouse.button07", - "mouse.limit", + "limit", }; static const char* input_find(uint16_t key) { - if(key < mouse::limit) return sym_table[key]; - static char buffer[64]; - for(unsigned j = 0; j < 16; j++) { - if(key == joypad<>::index(j, joypad<>::up)) { sprintf(buffer, "joypad%.2d.up", j); return buffer; } - if(key == joypad<>::index(j, joypad<>::down)) { sprintf(buffer, "joypad%.2d.down", j); return buffer; } - if(key == joypad<>::index(j, joypad<>::left)) { sprintf(buffer, "joypad%.2d.left", j); return buffer; } - if(key == joypad<>::index(j, joypad<>::right)) { sprintf(buffer, "joypad%.2d.right", j); return buffer; } + + 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)) { @@ -133,39 +186,77 @@ namespace nall { } static uint16_t input_find(const char *key) { - for(unsigned i = 0; i < mouse::limit; i++) { - if(!strcmp(sym_table[i], key)) return i; + 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; + + if(*key++ != '.') return input_none; + + for(unsigned i = 0; i < keyboard<>::length; i++) { + if(!strcmp(key, keysym[i])) return keyboard<>::index(k, i); + } } - if(memcmp(key, "joypad", 6)) return keyboard::none; - key += 6; - if(!*key || !*(key + 1)) return keyboard::none; - uint8_t j = (*key - '0') * 10 + (*(key + 1) - '0'); - if(j > 15) return keyboard::none; - - key += 2; - if(!strcmp(key, ".up")) return joypad<>::index(j, joypad<>::up); - if(!strcmp(key, ".down")) return joypad<>::index(j, joypad<>::down); - if(!strcmp(key, ".left")) return joypad<>::index(j, joypad<>::left); - if(!strcmp(key, ".right")) return joypad<>::index(j, joypad<>::right); - - if(!memcmp(key, ".axis", 5)) { + if(!memcmp(key, "mouse", 5)) { key += 5; - if(!*key || !*(key + 1)) return keyboard::none; - uint8_t axis = (*key - '0') * 10 + (*(key + 1) - '0'); - if(axis >= joypad<>::axes) return keyboard::none; - return joypad<>::index(j, joypad<>::axis + axis); + 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; + + 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); + + 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, ".button", 7)) { - key += 7; - if(!*key || !*(key + 1)) return keyboard::none; - uint8_t button = (*key - '0') * 10 + (*(key + 1) - '0'); - if(button >= joypad<>::buttons) return keyboard::none; - return joypad<>::index(j, joypad<>::button + button); + 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 keyboard::none; + return input_none; } } diff --git a/src/lib/ruby/input.hpp b/src/lib/ruby/input.hpp index 841f1b39..5387155d 100644 --- a/src/lib/ruby/input.hpp +++ b/src/lib/ruby/input.hpp @@ -5,7 +5,6 @@ public: KeyboardSupport, MouseSupport, JoypadSupport, - AnalogAxisResistance, }; virtual bool cap(Setting) { return false; } diff --git a/src/lib/ruby/input/directinput.cpp b/src/lib/ruby/input/directinput.cpp index ac9777fc..4bdfe23a 100644 --- a/src/lib/ruby/input/directinput.cpp +++ b/src/lib/ruby/input/directinput.cpp @@ -7,22 +7,24 @@ namespace ruby { #include "directinput.hpp" static BOOL CALLBACK DI_EnumJoypadsCallback(const DIDEVICEINSTANCE*, void*); +static BOOL CALLBACK DI_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE*, void*); using namespace nall; class pInputDI { public: InputDI &self; - LPDIRECTINPUT8 context; - LPDIRECTINPUTDEVICE8 keyboard; - LPDIRECTINPUTDEVICE8 mouse; - LPDIRECTINPUTDEVICE8 gamepad[joypad<>::count]; - unsigned gamepad_count; //number of physical gamepads present - bool mouseacquired; + + struct { + LPDIRECTINPUT8 context; + LPDIRECTINPUTDEVICE8 keyboard; + LPDIRECTINPUTDEVICE8 mouse; + LPDIRECTINPUTDEVICE8 gamepad[joypad<>::count]; + bool mouseacquired; + } device; struct { HWND handle; - unsigned analog_axis_resistance; } settings; bool cap(Input::Setting setting) { @@ -30,13 +32,11 @@ public: if(setting == Input::KeyboardSupport) return true; if(setting == Input::MouseSupport) return true; if(setting == Input::JoypadSupport) return true; - if(setting == Input::AnalogAxisResistance) return true; return false; } uintptr_t get(Input::Setting setting) { if(setting == Input::Handle) return (uintptr_t)settings.handle; - if(setting == Input::AnalogAxisResistance) return settings.analog_axis_resistance; return false; } @@ -46,205 +46,210 @@ public: return true; } - if(setting == Input::AnalogAxisResistance) { - settings.analog_axis_resistance = param; - return true; - } - return false; } bool poll(int16_t *table) { - memset(table, 0, input_limit * sizeof(int16_t)); + memset(table, 0, nall::input_limit * sizeof(int16_t)); - if(keyboard) { + //======== + //Keyboard + //======== + + if(device.keyboard) { uint8_t state[256]; - if(FAILED(keyboard->GetDeviceState(sizeof state, state))) { - keyboard->Acquire(); - if(FAILED(keyboard->GetDeviceState(sizeof state, state))) { + if(FAILED(device.keyboard->GetDeviceState(sizeof state, state))) { + device.keyboard->Acquire(); + if(FAILED(device.keyboard->GetDeviceState(sizeof state, state))) { memset(state, 0, sizeof state); } } - table[keyboard::escape] = (bool)(state[0x01] & 0x80); + 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); - table[keyboard::f1 ] = (bool)(state[0x3b] & 0x80); - table[keyboard::f2 ] = (bool)(state[0x3c] & 0x80); - table[keyboard::f3 ] = (bool)(state[0x3d] & 0x80); - table[keyboard::f4 ] = (bool)(state[0x3e] & 0x80); - table[keyboard::f5 ] = (bool)(state[0x3f] & 0x80); - table[keyboard::f6 ] = (bool)(state[0x40] & 0x80); - table[keyboard::f7 ] = (bool)(state[0x41] & 0x80); - table[keyboard::f8 ] = (bool)(state[0x42] & 0x80); - table[keyboard::f9 ] = (bool)(state[0x43] & 0x80); - table[keyboard::f10] = (bool)(state[0x44] & 0x80); - table[keyboard::f11] = (bool)(state[0x57] & 0x80); - table[keyboard::f12] = (bool)(state[0x58] & 0x80); + 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); - table[keyboard::print_screen] = (bool)(state[0xb7] & 0x80); - table[keyboard::scroll_lock ] = (bool)(state[0x46] & 0x80); - table[keyboard::pause ] = (bool)(state[0xc5] & 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); - table[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); - table[keyboard::num_1] = (bool)(state[0x02] & 0x80); - table[keyboard::num_2] = (bool)(state[0x03] & 0x80); - table[keyboard::num_3] = (bool)(state[0x04] & 0x80); - table[keyboard::num_4] = (bool)(state[0x05] & 0x80); - table[keyboard::num_5] = (bool)(state[0x06] & 0x80); - table[keyboard::num_6] = (bool)(state[0x07] & 0x80); - table[keyboard::num_7] = (bool)(state[0x08] & 0x80); - table[keyboard::num_8] = (bool)(state[0x09] & 0x80); - table[keyboard::num_9] = (bool)(state[0x0a] & 0x80); - table[keyboard::num_0] = (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); - table[keyboard::dash ] = (bool)(state[0x0c] & 0x80); - table[keyboard::equal ] = (bool)(state[0x0d] & 0x80); - table[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); - table[keyboard::insert ] = (bool)(state[0xd2] & 0x80); - table[keyboard::delete_ ] = (bool)(state[0xd3] & 0x80); - table[keyboard::home ] = (bool)(state[0xc7] & 0x80); - table[keyboard::end ] = (bool)(state[0xcf] & 0x80); - table[keyboard::page_up ] = (bool)(state[0xc9] & 0x80); - table[keyboard::page_down] = (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); - table[keyboard::a] = (bool)(state[0x1e] & 0x80); - table[keyboard::b] = (bool)(state[0x30] & 0x80); - table[keyboard::c] = (bool)(state[0x2e] & 0x80); - table[keyboard::d] = (bool)(state[0x20] & 0x80); - table[keyboard::e] = (bool)(state[0x12] & 0x80); - table[keyboard::f] = (bool)(state[0x21] & 0x80); - table[keyboard::g] = (bool)(state[0x22] & 0x80); - table[keyboard::h] = (bool)(state[0x23] & 0x80); - table[keyboard::i] = (bool)(state[0x17] & 0x80); - table[keyboard::j] = (bool)(state[0x24] & 0x80); - table[keyboard::k] = (bool)(state[0x25] & 0x80); - table[keyboard::l] = (bool)(state[0x26] & 0x80); - table[keyboard::m] = (bool)(state[0x32] & 0x80); - table[keyboard::n] = (bool)(state[0x31] & 0x80); - table[keyboard::o] = (bool)(state[0x18] & 0x80); - table[keyboard::p] = (bool)(state[0x19] & 0x80); - table[keyboard::q] = (bool)(state[0x10] & 0x80); - table[keyboard::r] = (bool)(state[0x13] & 0x80); - table[keyboard::s] = (bool)(state[0x1f] & 0x80); - table[keyboard::t] = (bool)(state[0x14] & 0x80); - table[keyboard::u] = (bool)(state[0x16] & 0x80); - table[keyboard::v] = (bool)(state[0x2f] & 0x80); - table[keyboard::w] = (bool)(state[0x11] & 0x80); - table[keyboard::x] = (bool)(state[0x2d] & 0x80); - table[keyboard::y] = (bool)(state[0x15] & 0x80); - table[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); - table[keyboard::lbracket ] = (bool)(state[0x1a] & 0x80); - table[keyboard::rbracket ] = (bool)(state[0x1b] & 0x80); - table[keyboard::backslash ] = (bool)(state[0x2b] & 0x80); - table[keyboard::semicolon ] = (bool)(state[0x27] & 0x80); - table[keyboard::apostrophe] = (bool)(state[0x28] & 0x80); - table[keyboard::comma ] = (bool)(state[0x33] & 0x80); - table[keyboard::period ] = (bool)(state[0x34] & 0x80); - table[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); - table[keyboard::pad_0] = (bool)(state[0x4f] & 0x80); - table[keyboard::pad_1] = (bool)(state[0x50] & 0x80); - table[keyboard::pad_2] = (bool)(state[0x51] & 0x80); - table[keyboard::pad_3] = (bool)(state[0x4b] & 0x80); - table[keyboard::pad_4] = (bool)(state[0x4c] & 0x80); - table[keyboard::pad_5] = (bool)(state[0x4d] & 0x80); - table[keyboard::pad_6] = (bool)(state[0x47] & 0x80); - table[keyboard::pad_7] = (bool)(state[0x48] & 0x80); - table[keyboard::pad_8] = (bool)(state[0x49] & 0x80); - table[keyboard::pad_9] = (bool)(state[0x52] & 0x80); - table[keyboard::point] = (bool)(state[0x53] & 0x80); + table[keyboard<0>::num_lock ] = (bool)(state[0x45] & 0x80); + table[keyboard<0>::caps_lock] = (bool)(state[0x3a] & 0x80); - table[keyboard::add] = (bool)(state[0x4e] & 0x80); - table[keyboard::subtract] = (bool)(state[0x4a] & 0x80); - table[keyboard::multiply] = (bool)(state[0x37] & 0x80); - table[keyboard::divide] = (bool)(state[0xb5] & 0x80); - table[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); - table[keyboard::num_lock ] = (bool)(state[0x45] & 0x80); - table[keyboard::caps_lock] = (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); - table[keyboard::up ] = (bool)(state[0xc8] & 0x80); - table[keyboard::down ] = (bool)(state[0xd0] & 0x80); - table[keyboard::left ] = (bool)(state[0xcb] & 0x80); - table[keyboard::right] = (bool)(state[0xcd] & 0x80); - - table[keyboard::tab ] = (bool)(state[0x0f] & 0x80); - table[keyboard::return_ ] = (bool)(state[0x1c] & 0x80); - table[keyboard::spacebar] = (bool)(state[0x39] & 0x80); - - table[keyboard::lctrl ] = (bool)(state[0x1d] & 0x80); - table[keyboard::rctrl ] = (bool)(state[0x9d] & 0x80); - table[keyboard::lalt ] = (bool)(state[0x38] & 0x80); - table[keyboard::ralt ] = (bool)(state[0xb8] & 0x80); - table[keyboard::lshift] = (bool)(state[0x2a] & 0x80); - table[keyboard::rshift] = (bool)(state[0x36] & 0x80); - table[keyboard::lsuper] = (bool)(state[0xdb] & 0x80); - table[keyboard::rsuper] = (bool)(state[0xdc] & 0x80); - table[keyboard::menu ] = (bool)(state[0xdd] & 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); } - if(mouse) { + //===== + //Mouse + //===== + + if(device.mouse) { DIMOUSESTATE2 state; - if(FAILED(mouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void*)&state))) { - mouse->Acquire(); - if(FAILED(mouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void*)&state))) { + if(FAILED(device.mouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void*)&state))) { + device.mouse->Acquire(); + if(FAILED(device.mouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void*)&state))) { memset(&state, 0, sizeof(DIMOUSESTATE2)); } } - table[mouse::x] = state.lX; - table[mouse::y] = state.lY; - table[mouse::z] = state.lZ / WHEEL_DELTA; - for(unsigned n = 0; n < mouse::buttons; n++) { - table[mouse::button + n] = (bool)state.rgbButtons[n]; + 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]; } //on Windows, 0 = left, 1 = right, 2 = middle //swap middle and right buttons for consistency with Linux - int16_t temp = table[mouse::button + 1]; - table[mouse::button + 1] = table[mouse::button + 2]; - table[mouse::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; } - for(unsigned i = 0; i < gamepad_count; i++) { - if(!gamepad[i]) continue; + //========= + //Joypad(s) + //========= + + 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(); + continue; + } DIJOYSTATE2 state; - if(FAILED(gamepad[i]->Poll())) { - gamepad[i]->Acquire(); - if(FAILED(gamepad[i]->Poll())) { - continue; + device.gamepad[i]->GetDeviceState(sizeof(DIJOYSTATE2), &state); + + //POV hats + 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; } } - gamepad[i]->GetDeviceState(sizeof(DIJOYSTATE2), &state); + //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; - unsigned index = joypad<>::index(i, joypad<>::none); - - int resistance = settings.analog_axis_resistance; - resistance = max(1, min(99, resistance)); - resistance = (int)((double)resistance * 32768.0 / 100.0); - int resistance_lo = 0x7fff - resistance; - int resistance_hi = 0x8000 + resistance; - - table[index + joypad<>::up ] = (state.lY <= resistance_lo); - table[index + joypad<>::down ] = (state.lY >= resistance_hi); - table[index + joypad<>::left ] = (state.lX <= resistance_lo); - table[index + joypad<>::right] = (state.lX >= resistance_hi); - - unsigned pov = state.rgdwPOV[0]; - table[index + joypad<>::up ] |= (pov == 0 || pov == 31500 || pov == 4500); - table[index + joypad<>::down ] |= (pov == 18000 || pov == 13500 || pov == 22500); - table[index + joypad<>::left ] |= (pov == 27000 || pov == 22500 || pov == 31500); - table[index + joypad<>::right] |= (pov == 9000 || pov == 4500 || pov == 13500); - - table[index + joypad<>::axis + 0] = (int16_t)(state.lX - 32768); - table[index + joypad<>::axis + 1] = (int16_t)(state.lY - 32768); - - for(unsigned n = 0; n < joypad<>::buttons; n++) { + //buttons + for(unsigned n = 0; n < min((unsigned)joypad<>::buttons, 128); n++) { table[index + joypad<>::button + n] = (bool)state.rgbButtons[n]; } } @@ -252,114 +257,135 @@ public: return true; } - bool enum_joypads(const DIDEVICEINSTANCE *instance) { - if(FAILED(context->CreateDevice(instance->guidInstance, &gamepad[gamepad_count], 0))) { - return DIENUM_CONTINUE; //continue and try next gamepad + 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; + + if(FAILED(device.context->CreateDevice(instance->guidInstance, &device.gamepad[n], 0))) { + return DIENUM_CONTINUE; //continue and try next gamepad } - gamepad[gamepad_count]->SetDataFormat(&c_dfDIJoystick2); - gamepad[gamepad_count]->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + device.gamepad[n]->SetDataFormat(&c_dfDIJoystick2); + device.gamepad[n]->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + device.gamepad[n]->EnumObjects(DI_EnumJoypadAxesCallback, (void*)this, DIDFT_ABSAXIS); - if(++gamepad_count >= joypad<>::count) return DIENUM_STOP; + return DIENUM_CONTINUE; + } + + bool init_axis(const DIDEVICEOBJECTINSTANCE *instance) { + signed n; + for(n = joypad<>::count - 1; n >= 0; n--) { if(device.gamepad[n]) break; } + if(n < 0) return DIENUM_STOP; + + DIPROPRANGE range; + range.diph.dwSize = sizeof(DIPROPRANGE); + range.diph.dwHeaderSize = sizeof(DIPROPHEADER); + range.diph.dwHow = DIPH_BYID; + range.diph.dwObj = instance->dwType; + range.lMin = -32768; + range.lMax = +32767; + device.gamepad[n]->SetProperty(DIPROP_RANGE, &range.diph); + return DIENUM_CONTINUE; } bool init() { - context = 0; - keyboard = 0; - mouse = 0; - for(unsigned i = 0; i < joypad<>::count; i++) gamepad[i] = 0; - gamepad_count = 0; - mouseacquired = false; + device.context = 0; + device.keyboard = 0; + device.mouse = 0; + for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0; + device.mouseacquired = false; - DirectInput8Create(GetModuleHandle(0), 0x0800, IID_IDirectInput8, (void**)&context, 0); + DirectInput8Create(GetModuleHandle(0), 0x0800, IID_IDirectInput8, (void**)&device.context, 0); - context->CreateDevice(GUID_SysKeyboard, &keyboard, 0); - keyboard->SetDataFormat(&c_dfDIKeyboard); - keyboard->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - keyboard->Acquire(); + device.context->CreateDevice(GUID_SysKeyboard, &device.keyboard, 0); + device.keyboard->SetDataFormat(&c_dfDIKeyboard); + device.keyboard->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + device.keyboard->Acquire(); - context->CreateDevice(GUID_SysMouse, &mouse, 0); - mouse->SetDataFormat(&c_dfDIMouse2); - HRESULT hr = mouse->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - mouse->Acquire(); + device.context->CreateDevice(GUID_SysMouse, &device.mouse, 0); + device.mouse->SetDataFormat(&c_dfDIMouse2); + HRESULT hr = device.mouse->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + device.mouse->Acquire(); - context->EnumDevices(DI8DEVCLASS_GAMECTRL, DI_EnumJoypadsCallback, (void*)this, DIEDFL_ATTACHEDONLY); + device.context->EnumDevices(DI8DEVCLASS_GAMECTRL, DI_EnumJoypadsCallback, (void*)this, DIEDFL_ATTACHEDONLY); return true; } void term() { - if(keyboard) { - keyboard->Unacquire(); - keyboard->Release(); - keyboard = 0; + if(device.keyboard) { + device.keyboard->Unacquire(); + device.keyboard->Release(); + device.keyboard = 0; } - if(mouse) { - mouse->Unacquire(); - mouse->Release(); - mouse = 0; + if(device.mouse) { + device.mouse->Unacquire(); + device.mouse->Release(); + device.mouse = 0; } for(unsigned i = 0; i < joypad<>::count; i++) { - if(gamepad[i]) { - gamepad[i]->Unacquire(); - gamepad[i]->Release(); - gamepad[i] = 0; + if(device.gamepad[i]) { + device.gamepad[i]->Unacquire(); + device.gamepad[i]->Release(); + device.gamepad[i] = 0; } } - gamepad_count = 0; - if(context) { - context->Release(); - context = 0; + if(device.context) { + device.context->Release(); + device.context = 0; } } bool acquire() { - if(!mouse) return false; + if(!device.mouse) return false; if(acquired() == false) { - mouse->Unacquire(); - mouse->SetCooperativeLevel(settings.handle, DISCL_EXCLUSIVE | DISCL_FOREGROUND); - mouse->Acquire(); - mouseacquired = true; + device.mouse->Unacquire(); + device.mouse->SetCooperativeLevel(settings.handle, DISCL_EXCLUSIVE | DISCL_FOREGROUND); + device.mouse->Acquire(); + device.mouseacquired = true; } return true; } bool unacquire() { - if(!mouse) return false; + if(!device.mouse) return false; if(acquired() == true) { - mouse->Unacquire(); - mouse->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - mouse->Acquire(); - mouseacquired = false; + device.mouse->Unacquire(); + device.mouse->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + device.mouse->Acquire(); + device.mouseacquired = false; } return true; } bool acquired() { - return mouseacquired; + return device.mouseacquired; } pInputDI(InputDI &self_) : self(self_) { - context = 0; - keyboard = 0; - mouse = 0; - for(unsigned i = 0; i < joypad<>::count; i++) gamepad[i] = 0; - gamepad_count = 0; - mouseacquired = false; + device.context = 0; + device.keyboard = 0; + device.mouse = 0; + for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0; + device.mouseacquired = false; settings.handle = 0; - settings.analog_axis_resistance = 75; } ~pInputDI() { term(); } }; BOOL CALLBACK DI_EnumJoypadsCallback(const DIDEVICEINSTANCE *instance, void *p) { - return ((pInputDI*)p)->enum_joypads(instance); + return ((pInputDI*)p)->init_joypad(instance); +} + +BOOL CALLBACK DI_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE *instance, void *p) { + return ((pInputDI*)p)->init_axis(instance); } bool InputDI::cap(Setting setting) { return p.cap(setting); } diff --git a/src/lib/ruby/input/rawinput.cpp b/src/lib/ruby/input/rawinput.cpp new file mode 100644 index 00000000..a576c7ca --- /dev/null +++ b/src/lib/ruby/input/rawinput.cpp @@ -0,0 +1,781 @@ +//RawInput driver +//author: byuu + +//this driver utilizes RawInput (WM_INPUT) to capture keyboard and mouse input. +//although this requires WinXP or newer, it is the only way to uniquely identify +//and independently map multiple keyboards and mice. DirectInput merges all +//keyboards and mice into one device per. +// +//as WM_INPUT lacks specific RAWINPUT structures for gamepads, giving only raw +//data, and because DirectInput supports up to 16 joypads, DirectInput is used +//for joypad mapping. +// +//further, Xbox 360 controllers are explicitly detected and supported through +//XInput. this is because under DirectInput, the LT / RT (trigger) buttons are +//merged into a single Z-axis -- making it impossible to detect both buttons +//being pressed at the same time. with XInput, the state of both trigger +//buttons can be read independently. +// +//so in essence, this is actually more of a hybrid driver. + +#define DIRECTINPUT_VERSION 0x0800 +#include +#include + +namespace ruby { + +#include "rawinput.hpp" + +DWORD WINAPI RawInputThreadProc(void*); +LRESULT CALLBACK RawInputWindowProc(HWND, UINT, WPARAM, LPARAM); + +class RawInput { +public: + HANDLE mutex; + HWND hwnd; + bool initialized; + bool ready; + + struct Device { + HANDLE handle; + }; + + struct Keyboard : Device { + bool state[keyboard<>::length]; + + 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(0x0037, 2, keyboard<>::print_screen) + map(0x0046, 0, keyboard<>::scroll_lock) + map(0x001d, 4, keyboard<>::pause) + map(0x0029, 0, 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(0x000c, 0, keyboard<>::dash) + map(0x000d, 0, keyboard<>::equal) + map(0x000e, 0, 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(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(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(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(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(0x0045, 0, keyboard<>::num_lock) + map(0x003a, 0, keyboard<>::caps_lock) + + //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; + + map(0x0048, 2, keyboard<>::up) + map(0x0050, 2, keyboard<>::down) + map(0x004b, 2, keyboard<>::left) + map(0x004d, 2, keyboard<>::right) + + map(0x000f, 0, keyboard<>::tab) + map(0x001c, 0, keyboard<>::return_) + map(0x0039, 0, keyboard<>::spacebar) + + 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) + #undef map + } + + Keyboard() { + for(unsigned i = 0; i < keyboard<>::length; i++) state[i] = false; + } + }; + + struct Mouse : Device { + signed xDistance; + signed yDistance; + signed zDistance; + unsigned buttonState; + + void sync() { + xDistance = 0; + yDistance = 0; + zDistance = 0; + } + + void update(RAWINPUT *input) { + if((input->data.mouse.usFlags & 1) == MOUSE_MOVE_RELATIVE) { + xDistance += input->data.mouse.lLastX; + yDistance += input->data.mouse.lLastY; + } + + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) buttonState |= 1 << 0; + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP ) buttonState &=~ 1 << 0; + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) buttonState |= 1 << 2; //swap middle and right buttons, + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP ) buttonState &=~ 1 << 2; //for consistency with Linux: + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) buttonState |= 1 << 1; //left = 0, middle = 1, right = 2 + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP ) buttonState &=~ 1 << 1; + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) buttonState |= 1 << 3; + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP ) buttonState &=~ 1 << 3; + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) buttonState |= 1 << 4; + if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP ) buttonState &=~ 1 << 4; + + if(input->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { + zDistance += (int16_t)input->data.mouse.usButtonData; + } + } + + Mouse() { + xDistance = yDistance = zDistance = 0; + buttonState = 0; + } + }; + + //keep track of gamepads for the sole purpose of distinguishing XInput devices + //from all other devices. this is necessary, as DirectInput does not provide + //a way to retrieve the necessary RIDI_DEVICENAME string. + struct Gamepad : Device { + bool isXInputDevice; + uint16_t vendorId; + uint16_t productId; + }; + + vector lkeyboard; + vector lmouse; + vector lgamepad; + + LRESULT window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + if(msg == WM_INPUT) { + unsigned size = 0; + GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + RAWINPUT *input = new RAWINPUT[size]; + GetRawInputData((HRAWINPUT)lparam, RID_INPUT, input, &size, sizeof(RAWINPUTHEADER)); + WaitForSingleObject(mutex, INFINITE); + + if(input->header.dwType == RIM_TYPEKEYBOARD) { + for(unsigned i = 0; i < lkeyboard.size(); i++) { + if(input->header.hDevice == lkeyboard[i].handle) { + lkeyboard[i].update(input); + break; + } + } + } else if(input->header.dwType == RIM_TYPEMOUSE) { + for(unsigned i = 0; i < lmouse.size(); i++) { + if(input->header.hDevice == lmouse[i].handle) { + lmouse[i].update(input); + break; + } + } + } + + ReleaseMutex(mutex); + //allow propogation of WM_INPUT message + LRESULT result = DefRawInputProc(&input, size, sizeof(RAWINPUTHEADER)); + delete[] input; + return result; + } + + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + //this is used to sort device IDs + struct DevicePool { + HANDLE handle; + char name[4096]; + bool operator<(const DevicePool &pool) const { return strcmp(name, pool.name) < 0; } + }; + + int main() { + //create an invisible window to act as a sink, capturing all WM_INPUT messages + WNDCLASS wc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hbrBackground = (HBRUSH)COLOR_WINDOW; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = RawInputWindowProc; + wc.lpszClassName = "RawInputClass"; + wc.lpszMenuName = 0; + wc.style = CS_VREDRAW | CS_HREDRAW; + RegisterClass(&wc); + + hwnd = CreateWindow("RawInputClass", "RawInputClass", WS_POPUP, + 0, 0, 64, 64, 0, 0, GetModuleHandle(0), 0); + + //enumerate all HID devices + unsigned devices = 0; + GetRawInputDeviceList(NULL, &devices, sizeof(RAWINPUTDEVICELIST)); + RAWINPUTDEVICELIST *list = new RAWINPUTDEVICELIST[devices]; + GetRawInputDeviceList(list, &devices, sizeof(RAWINPUTDEVICELIST)); + + //sort all devices by name. this has two important properties: + //1) it consistently orders peripherals, so mapped IDs remain constant + //2) it sorts the virtual keyboard and mouse to the bottom of the list + // (real devices start with \\?\HID#, virtual with \\?\Root#) + DevicePool pool[devices]; + for(unsigned i = 0; i < devices; i++) { + pool[i].handle = list[i].hDevice; + unsigned size = sizeof(pool[i].name) - 1; + GetRawInputDeviceInfo(list[i].hDevice, RIDI_DEVICENAME, &pool[i].name, &size); + } + nall::sort(pool, devices); + delete[] list; + + for(unsigned i = 0; i < devices; i++) { + RID_DEVICE_INFO info; + info.cbSize = sizeof(RID_DEVICE_INFO); + + unsigned size = info.cbSize; + GetRawInputDeviceInfo(pool[i].handle, RIDI_DEVICEINFO, &info, &size); + + if(info.dwType == RIM_TYPEKEYBOARD) { + unsigned n = lkeyboard.size(); + lkeyboard[n].handle = pool[i].handle; + } else if(info.dwType == RIM_TYPEMOUSE) { + unsigned n = lmouse.size(); + lmouse[n].handle = pool[i].handle; + } else if(info.dwType == RIM_TYPEHID) { + //if this is a gamepad or joystick device ... + if(info.hid.usUsagePage == 1 && (info.hid.usUsage == 4 || info.hid.usUsage == 5)) { + //... then cache device information for later use + unsigned n = lgamepad.size(); + lgamepad[n].handle = pool[i].handle; + lgamepad[n].vendorId = (uint16_t)info.hid.dwVendorId; + lgamepad[n].productId = (uint16_t)info.hid.dwProductId; + + //per MSDN: XInput devices have "IG_" in their device strings, + //which is how they should be identified. + const char *p = strstr(pool[i].name, "IG_"); + lgamepad[n].isXInputDevice = (bool)p; + } + } + } + + RAWINPUTDEVICE device[2]; + //capture all keyboard input + device[0].usUsagePage = 1; + device[0].usUsage = 6; + device[0].dwFlags = RIDEV_INPUTSINK; + device[0].hwndTarget = hwnd; + //capture all mouse input + device[1].usUsagePage = 1; + device[1].usUsage = 2; + device[1].dwFlags = RIDEV_INPUTSINK; + device[1].hwndTarget = hwnd; + RegisterRawInputDevices(device, 2, sizeof(RAWINPUTDEVICE)); + + WaitForSingleObject(mutex, INFINITE); + ready = true; + ReleaseMutex(mutex); + + while(true) { + MSG msg; + GetMessage(&msg, hwnd, 0, 0); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return 0; + } + + RawInput() : initialized(false), ready(false) { + } +}; + +static RawInput rawinput; + +DWORD WINAPI RawInputThreadProc(void*) { + return rawinput.main(); +} + +LRESULT CALLBACK RawInputWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + return rawinput.window_proc(hwnd, msg, wparam, lparam); +} + +class XInput { +public: + struct Gamepad { + unsigned id; + + int16_t hat; + int16_t axis[6]; + 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; + + axis[0] = (int16_t)state.Gamepad.sThumbLX; + axis[1] = (int16_t)state.Gamepad.sThumbLY; + axis[2] = (int16_t)state.Gamepad.sThumbRX; + axis[3] = (int16_t)state.Gamepad.sThumbRY; + + //transform left and right trigger ranges: + //from: 0 (low, eg released) to 255 (high, eg pressed all the way down) + //to: +32767 (low) to -32768 (high) + uint16_t triggerX = state.Gamepad.bLeftTrigger; + uint16_t triggerY = state.Gamepad.bRightTrigger; + + triggerX = (triggerX << 8) | triggerX; + triggerY = (triggerY << 8) | triggerY; + + axis[4] = (~triggerX) - 32768; + axis[5] = (~triggerY) - 32768; + + button[0] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_A); + button[1] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_B); + button[2] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_X); + button[3] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y); + button[4] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK); + button[5] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_START); + button[6] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER); + button[7] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER); + button[8] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB); + button[9] = (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB); + } + + Gamepad() { + hat = joypad<>::hat_center; + for(unsigned n = 0; n < 6; n++) axis[n] = 0; + for(unsigned n = 0; n < 10; n++) button[n] = false; + } + }; + + vector lgamepad; + + void poll() { + for(unsigned i = 0; i < lgamepad.size(); i++) { + XINPUT_STATE state; + DWORD result = XInputGetState(lgamepad[i].id, &state); + if(result == ERROR_SUCCESS) lgamepad[i].poll(state); + } + } + + void init() { + //XInput only supports up to four controllers + for(unsigned i = 0; i <= 3; i++) { + XINPUT_STATE state; + DWORD result = XInputGetState(i, &state); + if(result == ERROR_SUCCESS) { + //valid controller detected, add to gamepad list + unsigned n = lgamepad.size(); + lgamepad[n].id = i; + } + } + } +}; + +static BOOL CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE*, void*); +static BOOL CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE*, void*); + +class DirectInput { +public: + HWND handle; + LPDIRECTINPUT8 context; + struct Gamepad { + LPDIRECTINPUTDEVICE8 handle; + + int16_t hat[4]; + int16_t axis[6]; + bool button[128]; + + void poll(DIJOYSTATE2 &state) { + //POV hats + for(unsigned n = 0; n < 4; n++) { + hat[n] = joypad<>::hat_center; + + //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) 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; + } + + //axes + axis[0] = state.lX; + axis[1] = state.lY; + axis[2] = state.lZ; + axis[3] = state.lRx; + axis[4] = state.lRy; + axis[5] = state.lRz; + + //buttons + for(unsigned n = 0; n < 128; n++) { + button[n] = (bool)state.rgbButtons[n]; + } + } + + Gamepad() { + handle = 0; + for(unsigned n = 0; n < 4; n++) hat[n] = joypad<>::hat_center; + for(unsigned n = 0; n < 6; n++) axis[n] = 0; + for(unsigned n = 0; n < 128; n++) button[n] = false; + } + }; + vector lgamepad; + + void poll() { + for(unsigned i = 0; i < lgamepad.size(); i++) { + if(FAILED(lgamepad[i].handle->Poll())) { + lgamepad[i].handle->Acquire(); + continue; + } + + DIJOYSTATE2 state; + lgamepad[i].handle->GetDeviceState(sizeof(DIJOYSTATE2), &state); + lgamepad[i].poll(state); + } + } + + bool init_joypad(const DIDEVICEINSTANCE *instance) { + //if this is an XInput device, do not acquire it via DirectInput ... + //the XInput driver above will handle said device. + for(unsigned i = 0; i < rawinput.lgamepad.size(); i++) { + uint32_t guid = MAKELONG(rawinput.lgamepad[i].vendorId, rawinput.lgamepad[i].productId); + if(guid == instance->guidProduct.Data1) { + if(rawinput.lgamepad[i].isXInputDevice == true) { + return DIENUM_CONTINUE; + } + } + } + + if(FAILED(context->CreateDevice(instance->guidInstance, &device, 0))) { + return DIENUM_CONTINUE; + } + + device->SetDataFormat(&c_dfDIJoystick2); + device->SetCooperativeLevel(handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + device->EnumObjects(DirectInput_EnumJoypadAxesCallback, (void*)this, DIDFT_ABSAXIS); + unsigned n = lgamepad.size(); + lgamepad[n].handle = device; + return DIENUM_CONTINUE; + } + + bool init_axis(const DIDEVICEOBJECTINSTANCE *instance) { + DIPROPRANGE range; + range.diph.dwSize = sizeof(DIPROPRANGE); + range.diph.dwHeaderSize = sizeof(DIPROPHEADER); + range.diph.dwHow = DIPH_BYID; + range.diph.dwObj = instance->dwType; + range.lMin = -32768; + range.lMax = +32767; + device->SetProperty(DIPROP_RANGE, &range.diph); + return DIENUM_CONTINUE; + } + + void init(HWND handle_) { + handle = handle_; + DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&context, 0); + context->EnumDevices(DI8DEVCLASS_GAMECTRL, DirectInput_EnumJoypadsCallback, (void*)this, DIEDFL_ATTACHEDONLY); + } + + void term() { + for(unsigned i = 0; i < lgamepad.size(); i++) { + lgamepad[i].handle->Unacquire(); + lgamepad[i].handle->Release(); + } + lgamepad.reset(); + + if(context) { + context->Release(); + context = 0; + } + } + +private: + LPDIRECTINPUTDEVICE8 device; +}; + +BOOL CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE *instance, void *p) { + return ((DirectInput*)p)->init_joypad(instance); +} + +BOOL CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE *instance, void *p) { + return ((DirectInput*)p)->init_axis(instance); +} + +class pInputRaw { +public: + InputRaw &self; + XInput xinput; + DirectInput dinput; + + bool acquire_mouse; + bool cursor_visible; + + struct { + HWND handle; + } settings; + + bool cap(Input::Setting setting) { + if(setting == Input::Handle) return true; + if(setting == Input::KeyboardSupport) return true; + if(setting == Input::MouseSupport) return true; + if(setting == Input::JoypadSupport) return true; + return false; + } + + uintptr_t get(Input::Setting setting) { + if(setting == Input::Handle) return (uintptr_t)settings.handle; + return false; + } + + bool set(Input::Setting setting, uintptr_t param) { + if(setting == Input::Handle) { + settings.handle = (HWND)param; + return true; + } + return false; + } + + bool acquire() { + acquire_mouse = true; + if(cursor_visible == true) { + ShowCursor(cursor_visible = false); + } + return acquired(); + } + + bool unacquire() { + acquire_mouse = false; + ReleaseCapture(); + ClipCursor(NULL); + if(cursor_visible == false) { + ShowCursor(cursor_visible = true); + } + return true; + } + + bool acquired() { + if(acquire_mouse == true) { + SetFocus(settings.handle); + SetCapture(settings.handle); + RECT rc; + GetWindowRect(settings.handle, &rc); + ClipCursor(&rc); + } + return GetCapture() == settings.handle; + } + + bool poll(int16_t *table) { + memset(table, 0, nall::input_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]; + } + } + + //==== + //Mice + //==== + for(unsigned i = 0; i < min(rawinput.lmouse.size(), (unsigned)mouse<>::count); i++) { + unsigned index = mouse<>::index(i, mouse<>::none); + + 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)); + } + + rawinput.lmouse[i].sync(); + } + + ReleaseMutex(rawinput.mutex); + + unsigned joy = 0; + + //================== + //XInput controllers + //================== + xinput.poll(); + for(unsigned i = 0; i < xinput.lgamepad.size(); i++) { + if(joy >= joypad<>::count) break; + unsigned index = joypad<>::index(joy++, joypad<>::none); + + table[index + joypad<>::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 button = 0; button < min(10U, (unsigned)joypad<>::buttons); button++) { + table[index + joypad<>::button + button] = xinput.lgamepad[i].button[button]; + } + } + + //======================= + //DirectInput controllers + //======================= + dinput.poll(); + for(unsigned i = 0; i < dinput.lgamepad.size(); i++) { + if(joy >= joypad<>::count) break; + unsigned index = joypad<>::index(joy++, joypad<>::none); + + for(unsigned hat = 0; hat < min(4U, (unsigned)joypad<>::hats); hat++) { + table[index + joypad<>::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 button = 0; button < min(128U, (unsigned)joypad<>::buttons); button++) { + table[index + joypad<>::button + button] = dinput.lgamepad[i].button[button]; + } + } + } + + bool init() { + //only spawn RawInput processing thread one time + if(rawinput.initialized == false) { + rawinput.initialized = true; + rawinput.mutex = CreateMutex(NULL, FALSE, NULL); + CreateThread(NULL, 0, RawInputThreadProc, 0, 0, NULL); + + //RawInput device calibration needs to finish before initializing DirectInput; + //as it needs device GUIDs to distinguish XInput devices from ordinary joypads. + bool ready = false; + do { + Sleep(10); + WaitForSingleObject(rawinput.mutex, INFINITE); + ready = rawinput.ready; + ReleaseMutex(rawinput.mutex); + } while(ready == false); + } + + xinput.init(); + dinput.init(settings.handle); + + acquire_mouse = false; + cursor_visible = true; + return true; + } + + void term() { + unacquire(); + dinput.term(); + } + + pInputRaw(InputRaw &self_) : self(self_) { + } +}; + +bool InputRaw::cap(Setting setting) { return p.cap(setting); } +uintptr_t InputRaw::get(Setting setting) { return p.get(setting); } +bool InputRaw::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool InputRaw::acquire() { return p.acquire(); } +bool InputRaw::unacquire() { return p.unacquire(); } +bool InputRaw::acquired() { return p.acquired(); } +bool InputRaw::poll(int16_t *table) { return p.poll(table); } +bool InputRaw::init() { return p.init(); } +void InputRaw::term() { p.term(); } +InputRaw::InputRaw() : p(*new pInputRaw(*this)) {} +InputRaw::~InputRaw() { delete &p; } + +} diff --git a/src/lib/ruby/input/rawinput.hpp b/src/lib/ruby/input/rawinput.hpp new file mode 100644 index 00000000..02b7d2d1 --- /dev/null +++ b/src/lib/ruby/input/rawinput.hpp @@ -0,0 +1,22 @@ +class pInputRaw; + +class InputRaw : public Input { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + bool acquire(); + bool unacquire(); + bool acquired(); + + bool poll(int16_t *table); + bool init(); + void term(); + + InputRaw(); + ~InputRaw(); + +private: + pInputRaw &p; +}; diff --git a/src/lib/ruby/input/sdl.cpp b/src/lib/ruby/input/sdl.cpp index fa094f9f..f5c46071 100644 --- a/src/lib/ruby/input/sdl.cpp +++ b/src/lib/ruby/input/sdl.cpp @@ -38,7 +38,6 @@ struct pInputSDL { struct { uintptr_t handle; - unsigned analog_axis_resistance; } settings; bool cap(Input::Setting setting) { @@ -46,13 +45,11 @@ struct pInputSDL { if(setting == Input::KeyboardSupport) return true; if(setting == Input::MouseSupport) return true; if(setting == Input::JoypadSupport) return true; - if(setting == Input::AnalogAxisResistance) return true; return false; } uintptr_t get(Input::Setting setting) { if(setting == Input::Handle) return settings.handle; - if(setting == Input::AnalogAxisResistance) return settings.analog_axis_resistance; return false; } @@ -62,11 +59,6 @@ struct pInputSDL { return true; } - if(setting == Input::AnalogAxisResistance) { - settings.analog_axis_resistance = param; - return true; - } - return false; } @@ -105,7 +97,7 @@ struct pInputSDL { } bool poll(int16_t *table) { - memset(table, 0, input_limit * sizeof(int16_t)); + memset(table, 0, nall::input_limit * sizeof(int16_t)); //======== //Keyboard @@ -114,7 +106,7 @@ struct pInputSDL { char state[32]; XQueryKeymap(device.display, state); - for(unsigned i = 0; i < keyboard::limit; i++) { + 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))); @@ -137,27 +129,27 @@ struct pInputSDL { XGetWindowAttributes(device.display, settings.handle, &attributes); //absolute -> relative conversion - table[mouse::x] = (int16_t)(root_x_return - device.screenwidth / 2); - table[mouse::y] = (int16_t)(root_y_return - device.screenheight / 2); + table[mouse<0>::x] = (int16_t)(root_x_return - device.screenwidth / 2); + table[mouse<0>::y] = (int16_t)(root_y_return - device.screenheight / 2); - if(table[mouse::x] != 0 || table[mouse::y] != 0) { + if(table[mouse<0>::x] != 0 || table[mouse<0>::y] != 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::x] = (int16_t)(root_x_return - device.relativex); - table[mouse::y] = (int16_t)(root_y_return - device.relativey); + table[mouse<0>::x] = (int16_t)(root_x_return - device.relativex); + table[mouse<0>::y] = (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::button + 0] = (bool)(mask_return & Button1Mask); - table[mouse::button + 1] = (bool)(mask_return & Button2Mask); - table[mouse::button + 2] = (bool)(mask_return & Button3Mask); - table[mouse::button + 3] = (bool)(mask_return & Button4Mask); - table[mouse::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) @@ -166,43 +158,27 @@ struct pInputSDL { SDL_JoystickUpdate(); for(unsigned i = 0; i < joypad<>::count; i++) { if(!device.gamepad[i]) continue; - unsigned index = joypad<>::index(i, joypad<>::none); - table[index + joypad<>::up ] = false; - table[index + joypad<>::down ] = false; - table[index + joypad<>::left ] = false; - table[index + joypad<>::right] = false; - int resistance = settings.analog_axis_resistance; - resistance = max(1, min(99, resistance)); - resistance = (int)((double)resistance * 32768.0 / 100.0); + //POV hats + 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; + } //axes unsigned axes = min((unsigned)joypad<>::axes, SDL_JoystickNumAxes(device.gamepad[i])); for(unsigned axis = 0; axis < axes; axis++) { - int16_t value = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis); - table[index + joypad<>::axis + axis] = value; - if(axis == 0) { //X-axis - table[index + joypad<>::left ] |= value < -resistance; - table[index + joypad<>::right] |= value > +resistance; - } else if(axis == 1) { //Y-axis - table[index + joypad<>::up ] |= value < -resistance; - table[index + joypad<>::down ] |= value > +resistance; - } - } - - //POV hats - if(SDL_JoystickNumHats(device.gamepad[i]) >= 1) { - uint8_t state = SDL_JoystickGetHat(device.gamepad[i], 0); - table[index + joypad<>::up ] |= state & SDL_HAT_UP; - table[index + joypad<>::down ] |= state & SDL_HAT_DOWN; - table[index + joypad<>::left ] |= state & SDL_HAT_LEFT; - table[index + joypad<>::right] |= state & SDL_HAT_RIGHT; + table[index + joypad<>::axis + axis] = (int16_t)SDL_JoystickGetAxis(device.gamepad[i], axis); } //buttons for(unsigned button = 0; button < joypad<>::buttons; button++) { - table[index + joypad<>::button + button] = SDL_JoystickGetButton(device.gamepad[i], button); + table[index + joypad<>::button + button] = (bool)SDL_JoystickGetButton(device.gamepad[i], button); } } @@ -238,9 +214,8 @@ struct pInputSDL { device.relativex = 0; device.relativey = 0; - for(unsigned i = 0; i < joypad<>::count && i < SDL_NumJoysticks(); i++) { - device.gamepad[i] = SDL_JoystickOpen(i); - } + unsigned joypads = min((unsigned)joypad<>::count, SDL_NumJoysticks()); + for(unsigned i = 0; i < joypads; i++) device.gamepad[i] = SDL_JoystickOpen(i); return true; } @@ -259,7 +234,7 @@ struct pInputSDL { pInputSDL(InputSDL &self_) : self(self_) { for(unsigned i = 0; i < joypad<>::count; i++) device.gamepad[i] = 0; - settings.analog_axis_resistance = 75; + settings.handle = 0; } }; diff --git a/src/lib/ruby/input/x.cpp b/src/lib/ruby/input/x.cpp index 0555465d..db1b38fc 100644 --- a/src/lib/ruby/input/x.cpp +++ b/src/lib/ruby/input/x.cpp @@ -33,7 +33,7 @@ public: char state[32]; XQueryKeymap(display, state); - for(unsigned i = 0; i < keyboard::limit; i++) { + 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))); diff --git a/src/lib/ruby/input/xlibkeys.hpp b/src/lib/ruby/input/xlibkeys.hpp index 45813b49..bbce472a 100644 --- a/src/lib/ruby/input/xlibkeys.hpp +++ b/src/lib/ruby/input/xlibkeys.hpp @@ -15,123 +15,123 @@ bool init_keycodes() { memset(&keycode, 0, sizeof keycode); #define assign(x, y) keycode[x] = XKeysymToKeycode(display, y) - assign(keyboard::escape, XK_Escape); + assign(keyboard<0>::escape, XK_Escape); - assign(keyboard::f1, XK_F1); - assign(keyboard::f2, XK_F2); - assign(keyboard::f3, XK_F3); - assign(keyboard::f4, XK_F4); - assign(keyboard::f5, XK_F5); - assign(keyboard::f6, XK_F6); - assign(keyboard::f7, XK_F7); - assign(keyboard::f8, XK_F8); - assign(keyboard::f9, XK_F9); - assign(keyboard::f10, XK_F10); - assign(keyboard::f11, XK_F11); - assign(keyboard::f12, XK_F12); + 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); - //assign(keyboard::print_screen, XK_???); - assign(keyboard::scroll_lock, XK_Scroll_Lock); - assign(keyboard::pause, XK_Pause); + //assign(keyboard<0>::print_screen, XK_???); + assign(keyboard<0>::scroll_lock, XK_Scroll_Lock); + assign(keyboard<0>::pause, XK_Pause); - assign(keyboard::tilde, XK_asciitilde); + assign(keyboard<0>::tilde, XK_asciitilde); - assign(keyboard::num_0, XK_0); - assign(keyboard::num_1, XK_1); - assign(keyboard::num_2, XK_2); - assign(keyboard::num_3, XK_3); - assign(keyboard::num_4, XK_4); - assign(keyboard::num_5, XK_5); - assign(keyboard::num_6, XK_6); - assign(keyboard::num_7, XK_7); - assign(keyboard::num_8, XK_8); - assign(keyboard::num_9, XK_9); + 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); - assign(keyboard::dash, XK_minus); - assign(keyboard::equal, XK_equal); - assign(keyboard::backspace, XK_BackSpace); + assign(keyboard<0>::dash, XK_minus); + assign(keyboard<0>::equal, XK_equal); + assign(keyboard<0>::backspace, XK_BackSpace); - assign(keyboard::insert, XK_Insert); - assign(keyboard::delete_, XK_Delete); - assign(keyboard::home, XK_Home); - assign(keyboard::end, XK_End); - assign(keyboard::page_up, XK_Prior); - assign(keyboard::page_down, XK_Next); + 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); - assign(keyboard::a, XK_A); - assign(keyboard::b, XK_B); - assign(keyboard::c, XK_C); - assign(keyboard::d, XK_D); - assign(keyboard::e, XK_E); - assign(keyboard::f, XK_F); - assign(keyboard::g, XK_G); - assign(keyboard::h, XK_H); - assign(keyboard::i, XK_I); - assign(keyboard::j, XK_J); - assign(keyboard::k, XK_K); - assign(keyboard::l, XK_L); - assign(keyboard::m, XK_M); - assign(keyboard::n, XK_N); - assign(keyboard::o, XK_O); - assign(keyboard::p, XK_P); - assign(keyboard::q, XK_Q); - assign(keyboard::r, XK_R); - assign(keyboard::s, XK_S); - assign(keyboard::t, XK_T); - assign(keyboard::u, XK_U); - assign(keyboard::v, XK_V); - assign(keyboard::w, XK_W); - assign(keyboard::x, XK_X); - assign(keyboard::y, XK_Y); - assign(keyboard::z, XK_Z); + 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); - assign(keyboard::lbracket, XK_bracketleft); - assign(keyboard::rbracket, XK_bracketright); - assign(keyboard::backslash, XK_backslash); - assign(keyboard::semicolon, XK_semicolon); - assign(keyboard::apostrophe, XK_apostrophe); - assign(keyboard::comma, XK_comma); - assign(keyboard::period, XK_period); - assign(keyboard::slash, XK_slash); + 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); - assign(keyboard::pad_0, XK_KP_0); - assign(keyboard::pad_1, XK_KP_1); - assign(keyboard::pad_2, XK_KP_2); - assign(keyboard::pad_3, XK_KP_3); - assign(keyboard::pad_4, XK_KP_4); - assign(keyboard::pad_5, XK_KP_5); - assign(keyboard::pad_6, XK_KP_6); - assign(keyboard::pad_7, XK_KP_7); - assign(keyboard::pad_8, XK_KP_8); - assign(keyboard::pad_9, XK_KP_9); + 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); - assign(keyboard::add, XK_KP_Add); - assign(keyboard::subtract, XK_KP_Subtract); - assign(keyboard::multiply, XK_KP_Multiply); - assign(keyboard::divide, XK_KP_Divide); - assign(keyboard::enter, XK_KP_Enter); + 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); - //assign(keyboard::num_lock, XK_???); - //assign(keyboard::caps_lock, XK_???); + //assign(keyboard<0>::num_lock, XK_???); + //assign(keyboard<0>::caps_lock, XK_???); - assign(keyboard::up, XK_Up); - assign(keyboard::down, XK_Down); - assign(keyboard::left, XK_Left); - assign(keyboard::right, XK_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); - assign(keyboard::tab, XK_Tab); - assign(keyboard::return_, XK_Return); - assign(keyboard::spacebar, XK_space); + assign(keyboard<0>::tab, XK_Tab); + assign(keyboard<0>::return_, XK_Return); + assign(keyboard<0>::spacebar, XK_space); - assign(keyboard::lctrl, XK_Control_L); - assign(keyboard::rctrl, XK_Control_R); - assign(keyboard::lalt, XK_Alt_L); - assign(keyboard::ralt, XK_Alt_R); - assign(keyboard::lshift, XK_Shift_L); - assign(keyboard::rshift, XK_Shift_R); - assign(keyboard::lsuper, XK_Super_L); - assign(keyboard::rsuper, XK_Super_R); - assign(keyboard::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); diff --git a/src/lib/ruby/ruby.cpp b/src/lib/ruby/ruby.cpp index 2a8bd1b9..ee844a54 100644 --- a/src/lib/ruby/ruby.cpp +++ b/src/lib/ruby/ruby.cpp @@ -236,6 +236,10 @@ void InputInterface::driver(const char *driver) { else if(!strcmp(driver, "DirectInput")) p = new InputDI(); #endif + #ifdef INPUT_RAWINPUT + else if(!strcmp(driver, "RawInput")) p = new InputRaw(); + #endif + #ifdef INPUT_SDL else if(!strcmp(driver, "SDL")) p = new InputSDL(); #endif @@ -249,7 +253,9 @@ void InputInterface::driver(const char *driver) { //select the *safest* available driver, not the fastest const char* InputInterface::default_driver() { - #if defined(INPUT_DIRECTINPUT) + #if defined(INPUT_RAWINPUT) + return "RawInput"; + #elif defined(INPUT_DIRECTINPUT) return "DirectInput"; #elif defined(INPUT_SDL) return "SDL"; @@ -265,6 +271,10 @@ const char* InputInterface::driver_list() { //Windows + #if defined(INPUT_RAWINPUT) + "RawInput;" + #endif + #if defined(INPUT_DIRECTINPUT) "DirectInput;" #endif diff --git a/src/lib/ruby/ruby.hpp b/src/lib/ruby/ruby.hpp index 0ac6d269..1f0cbc47 100644 --- a/src/lib/ruby/ruby.hpp +++ b/src/lib/ruby/ruby.hpp @@ -1,6 +1,6 @@ /* ruby - version: 0.04 (2008-08-20) + version: 0.05 (2009-03-21) license: public domain */ @@ -8,10 +8,13 @@ #define RUBY_H #include +#include #include #include #include +#include #include +#include namespace ruby { diff --git a/src/lib/ruby/ruby_impl.cpp b/src/lib/ruby/ruby_impl.cpp index f1f52a62..86d8fe48 100644 --- a/src/lib/ruby/ruby_impl.cpp +++ b/src/lib/ruby/ruby_impl.cpp @@ -1,5 +1,10 @@ /* Video */ +#ifdef _WIN32 + #define _WIN32_WINNT 0x0501 + #include +#endif + #ifdef VIDEO_DIRECT3D #include #endif @@ -60,6 +65,10 @@ #include #endif +#ifdef INPUT_RAWINPUT + #include +#endif + #ifdef INPUT_SDL #include #endif diff --git a/src/lib/sync.bat b/src/lib/sync.bat index 47175d6e..f886b633 100644 --- a/src/lib/sync.bat +++ b/src/lib/sync.bat @@ -1,16 +1,9 @@ -rmdir /Q /S nall -rmdir /Q /S hiro +rmdir /Q /S nall rmdir /Q /S ruby - -mkdir nall -mkdir hiro -mkdir ruby - -xcopy /E ..\..\..\nall nall -xcopy /E ..\..\..\hiro hiro -xcopy /E ..\..\..\ruby ruby - -del hiro\test* -del hiro\cc.* -del ruby\test* -del ruby\cc.* + +mkdir nall +mkdir ruby +xcopy /E ..\..\..\nall nall +xcopy /E ..\..\..\ruby ruby +del ruby\test* +del ruby\cc.* diff --git a/src/lib/sync.sh b/src/lib/sync.sh index 918683dc..81a89702 100644 --- a/src/lib/sync.sh +++ b/src/lib/sync.sh @@ -1,12 +1,6 @@ rm -r nall -rm -r hiro rm -r ruby - cp -r ../../../nall ./nall -cp -r ../../../hiro ./hiro cp -r ../../../ruby ./ruby - -rm hiro/test* -rm hiro/cc.* rm ruby/test* rm ruby/cc.* diff --git a/src/ppu/bppu/bppu_render_bg.cpp b/src/ppu/bppu/bppu_render_bg.cpp index 0bf63d7a..ec1cdb05 100644 --- a/src/ppu/bppu/bppu_render_bg.cpp +++ b/src/ppu/bppu/bppu_render_bg.cpp @@ -1,217 +1,211 @@ #ifdef BPPU_CPP //called once at the start of every rendered scanline -void bPPU::update_bg_info() { - unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6); - unsigned width = (!hires) ? 256 : 512; - - for(int bg = 0; bg < 4; bg++) { - bg_info[bg].th = (regs.bg_tilesize[bg]) ? 4 : 3; - bg_info[bg].tw = (hires) ? 4 : bg_info[bg].th; - - bg_info[bg].mx = (bg_info[bg].th == 4) ? (width << 1) : width; - bg_info[bg].my = bg_info[bg].mx; - if(regs.bg_scsize[bg] & 0x01) bg_info[bg].mx <<= 1; - if(regs.bg_scsize[bg] & 0x02) bg_info[bg].my <<= 1; - bg_info[bg].mx--; - bg_info[bg].my--; - - bg_info[bg].scy = (regs.bg_scsize[bg] & 0x02) ? (32 << 5) : 0; - bg_info[bg].scx = (regs.bg_scsize[bg] & 0x01) ? (32 << 5) : 0; - if(regs.bg_scsize[bg] == 3) bg_info[bg].scy <<= 1; - } -} - -uint16 bPPU::bg_get_tile(uint8 bg, uint16 x, uint16 y) { - x = (x & bg_info[bg].mx) >> bg_info[bg].tw; - y = (y & bg_info[bg].my) >> bg_info[bg].th; - - uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f); - if(y & 0x20) pos += bg_info[bg].scy; - if(x & 0x20) pos += bg_info[bg].scx; - - uint16 addr = regs.bg_scaddr[bg] + (pos << 1); - return memory::vram[addr] + (memory::vram[addr + 1] << 8); -} - -#define setpixel_main(x) \ - if(pixel_cache[x].pri_main < tile_pri) { \ - pixel_cache[x].pri_main = tile_pri; \ - pixel_cache[x].bg_main = bg; \ - pixel_cache[x].src_main = col; \ - pixel_cache[x].ce_main = false; \ - } - -#define setpixel_sub(x) \ - if(pixel_cache[x].pri_sub < tile_pri) { \ - pixel_cache[x].pri_sub = tile_pri; \ - pixel_cache[x].bg_sub = bg; \ - pixel_cache[x].src_sub = col; \ - pixel_cache[x].ce_sub = false; \ - } - -void bPPU::render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos) { - if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) { - return; - } - - //are layers disabled by user? - if(render_enabled(bg, 0) == false)pri0_pos = 0; - if(render_enabled(bg, 1) == false)pri1_pos = 0; - //nothing to render? - if(!pri0_pos && !pri1_pos)return; - - bool bg_enabled = regs.bg_enabled[bg]; - bool bgsub_enabled = regs.bgsub_enabled[bg]; - - uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : (bg == BG2) ? 0x4000 : 0x0000; - uint8 bgpal_index = (regs.bg_mode == 0) ? (bg << 5) : 0; - - uint8 pal_size = 2 << color_depth; //<<2 (*4), <<4 (*16), <<8 (*256) - uint16 tile_mask = 0x0fff >> color_depth; //0x0fff, 0x07ff, 0x03ff - //4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile - //index is a tile number count to add to base tile number - unsigned tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth); - - uint8 *bg_td = bg_tiledata[color_depth]; - uint8 *bg_td_state = bg_tiledata_state[color_depth]; - - uint8 tile_width = bg_info[bg].tw; - uint8 tile_height = bg_info[bg].th; - uint16 mask_x = bg_info[bg].mx; //screen width mask - uint16 mask_y = bg_info[bg].my; //screen height mask - - uint16 y = regs.bg_y[bg]; - uint16 hscroll = regs.bg_hofs[bg]; - uint16 vscroll = regs.bg_vofs[bg]; - - unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6); - unsigned width = (!hires) ? 256 : 512; - - if(hires) { - hscroll <<= 1; - if(regs.interlace) y = (y << 1) + ifield(); - } - - uint16 *mtable = mosaic_table[(regs.mosaic_enabled[bg]) ? regs.mosaic_size : 0]; - - uint16 hval, vval; - uint16 t, tile_pri, tile_num; - uint8 pal_index, pal_num; - uint8 *tile_ptr; - unsigned xpos, ypos; - uint16 hoffset, voffset, opt_x, col; - bool mirror_x, mirror_y; - const bool is_opt_mode = (regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6); - - build_window_tables(bg); - uint8 *wt_main = window[bg].main; - uint8 *wt_sub = window[bg].sub; - - uint16 prev_x = 0xffff, prev_y = 0xffff, prev_optx = 0xffff; - for(uint16 x = 0; x < width; x++) { - hoffset = mtable[x] + hscroll; - voffset = y + vscroll; - - if(is_opt_mode) { - opt_x = (x + (hscroll & 7)); - - //tile 0 is unaffected by OPT mode... +void bPPU::update_bg_info() { + const unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6); + const unsigned width = (!hires ? 256 : 512); + + for(unsigned bg = 0; bg < 4; bg++) { + bg_info[bg].th = (regs.bg_tilesize[bg] ? 4 : 3); + bg_info[bg].tw = (hires ? 4 : bg_info[bg].th); + + bg_info[bg].mx = (bg_info[bg].th == 4 ? (width << 1) : width); + bg_info[bg].my = bg_info[bg].mx; + if(regs.bg_scsize[bg] & 0x01) bg_info[bg].mx <<= 1; + if(regs.bg_scsize[bg] & 0x02) bg_info[bg].my <<= 1; + bg_info[bg].mx--; + bg_info[bg].my--; + + bg_info[bg].scy = (regs.bg_scsize[bg] & 0x02) ? (32 << 5) : 0; + bg_info[bg].scx = (regs.bg_scsize[bg] & 0x01) ? (32 << 5) : 0; + if(regs.bg_scsize[bg] == 3) bg_info[bg].scy <<= 1; + } +} + +uint16 bPPU::bg_get_tile(uint8 bg, uint16 x, uint16 y) { + x = (x & bg_info[bg].mx) >> bg_info[bg].tw; + y = (y & bg_info[bg].my) >> bg_info[bg].th; + + uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f); + if(y & 0x20) pos += bg_info[bg].scy; + if(x & 0x20) pos += bg_info[bg].scx; + + const uint16 addr = regs.bg_scaddr[bg] + (pos << 1); + return memory::vram[addr] + (memory::vram[addr + 1] << 8); +} + +#define setpixel_main(x) \ + if(pixel_cache[x].pri_main < tile_pri) { \ + pixel_cache[x].pri_main = tile_pri; \ + pixel_cache[x].bg_main = bg; \ + pixel_cache[x].src_main = col; \ + pixel_cache[x].ce_main = false; \ + } + +#define setpixel_sub(x) \ + if(pixel_cache[x].pri_sub < tile_pri) { \ + pixel_cache[x].pri_sub = tile_pri; \ + pixel_cache[x].bg_sub = bg; \ + pixel_cache[x].src_sub = col; \ + pixel_cache[x].ce_sub = false; \ + } + +void bPPU::render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos) { + if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) { + return; + } + + //are layers disabled by user? + if(render_enabled(bg, 0) == false) pri0_pos = 0; + if(render_enabled(bg, 1) == false) pri1_pos = 0; + //nothing to render? + if(!pri0_pos && !pri1_pos) return; + + const bool bg_enabled = regs.bg_enabled[bg]; + const bool bgsub_enabled = regs.bgsub_enabled[bg]; + + const uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : (bg == BG2) ? 0x4000 : 0x0000; + const uint8 bgpal_index = (regs.bg_mode == 0 ? (bg << 5) : 0); + + const uint8 pal_size = 2 << color_depth; //<<2 (*4), <<4 (*16), <<8 (*256) + const uint16 tile_mask = 0x0fff >> color_depth; //0x0fff, 0x07ff, 0x03ff + //4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile + //index is a tile number count to add to base tile number + const unsigned tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth); + + const uint8 *bg_td = bg_tiledata[color_depth]; + const uint8 *bg_td_state = bg_tiledata_state[color_depth]; + + const uint8 tile_width = bg_info[bg].tw; + const uint8 tile_height = bg_info[bg].th; + const uint16 mask_x = bg_info[bg].mx; //screen width mask + const uint16 mask_y = bg_info[bg].my; //screen height mask + + uint16 y = regs.bg_y[bg]; + uint16 hscroll = regs.bg_hofs[bg]; + uint16 vscroll = regs.bg_vofs[bg]; + + const unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6); + const unsigned width = (!hires ? 256 : 512); + + if(hires) { + hscroll <<= 1; + if(regs.interlace) y = (y << 1) + ifield(); + } + + uint16 hval, vval; + uint16 tile_pri, tile_num; + uint8 pal_index, pal_num; + uint16 hoffset, voffset, opt_x, col; + bool mirror_x, mirror_y; + + const uint8 *tile_ptr; + const uint16 *mtable = mosaic_table[regs.mosaic_enabled[bg] ? regs.mosaic_size : 0]; + const bool is_opt_mode = (regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6); + const bool is_direct_color_mode = (regs.direct_color == true && bg == BG1 && (regs.bg_mode == 3 || regs.bg_mode == 4)); + + build_window_tables(bg); + const uint8 *wt_main = window[bg].main; + const uint8 *wt_sub = window[bg].sub; + + uint16 prev_x = 0xffff, prev_y = 0xffff, prev_optx = 0xffff; + for(uint16 x = 0; x < width; x++) { + hoffset = mtable[x] + hscroll; + voffset = y + vscroll; + + if(is_opt_mode) { + opt_x = (x + (hscroll & 7)); + + //tile 0 is unaffected by OPT mode... if(opt_x >= 8) { //cache tile data in hval, vval if possible - if((opt_x >> 3) != (prev_optx >> 3)) { + if((opt_x >> 3) != (prev_optx >> 3)) { + prev_optx = opt_x; + hval = bg_get_tile(BG3, (opt_x - 8) + (regs.bg_hofs[BG3] & ~7), regs.bg_vofs[BG3]); - if(regs.bg_mode != 4) { + if(regs.bg_mode != 4) { vval = bg_get_tile(BG3, (opt_x - 8) + (regs.bg_hofs[BG3] & ~7), regs.bg_vofs[BG3] + 8); } - prev_optx = opt_x; - } - - if(regs.bg_mode == 4) { - if(hval & opt_valid_bit) { - if(!(hval & 0x8000)) { - hoffset = opt_x + (hval & ~7); - } else { - voffset = y + hval; - } - } - } else { - if(hval & opt_valid_bit) { - hoffset = opt_x + (hval & ~7); - } - if(vval & opt_valid_bit) { - voffset = y + vval; - } - } - } - } - - hoffset &= mask_x; - voffset &= mask_y; - - if((hoffset >> 3) != prev_x || (voffset >> 3) != prev_y) { - prev_x = (hoffset >> 3); - prev_y = (voffset >> 3); - - t = bg_get_tile(bg, hoffset, voffset); - - mirror_y = !!(t & 0x8000); - mirror_x = !!(t & 0x4000); - - tile_pri = (t & 0x2000) ? pri1_pos : pri0_pos; - tile_num = t; - - if(tile_width == 4) { //16x16 horizontal tile mirroring - if(!!(hoffset & 8) != mirror_x)tile_num++; - } - - if(tile_height == 4) { //16x16 vertical tile mirroring - if(!!(voffset & 8) != mirror_y)tile_num += 16; - } - - tile_num &= 0x03ff; - tile_num += tiledata_index; - tile_num &= tile_mask; - - if(bg_td_state[tile_num] == 1) { - render_bg_tile(color_depth, tile_num); - } - - pal_num = ((t >> 10) & 7); - pal_index = bgpal_index + (pal_num << pal_size); - - ypos = voffset & 7; - if(mirror_y)ypos ^= 7; //invert y tile pos - - tile_ptr = bg_td + (tile_num * 64) + (ypos * 8); - } - - xpos = hoffset & 7; - if(mirror_x)xpos ^= 7; //invert x tile pos - col = *(tile_ptr + xpos); - if(col) { - if(regs.direct_color == true && bg == BG1 && (regs.bg_mode == 3 || regs.bg_mode == 4)) { - col = get_direct_color(pal_num, col); - } else { - col = get_palette(col + pal_index); - } - - if(!hires) { - if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); } - if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); } - } else { - int hx = x >> 1; - if(x & 1) { - if(bg_enabled == true && !wt_main[hx]) { setpixel_main(hx); } - } else { - if(bgsub_enabled == true && !wt_sub[hx]) { setpixel_sub(hx); } - } - } - } - } -} - -#undef setpixel_main -#undef setpixel_sub + } + + if(regs.bg_mode == 4) { + if(hval & opt_valid_bit) { + if(!(hval & 0x8000)) { + hoffset = opt_x + (hval & ~7); + } else { + voffset = y + hval; + } + } + } else { + if(hval & opt_valid_bit) { + hoffset = opt_x + (hval & ~7); + } + if(vval & opt_valid_bit) { + voffset = y + vval; + } + } + } + } + + hoffset &= mask_x; + voffset &= mask_y; + + if((hoffset >> 3) != prev_x || (voffset >> 3) != prev_y) { + prev_x = (hoffset >> 3); + prev_y = (voffset >> 3); + + tile_num = bg_get_tile(bg, hoffset, voffset); //format = vhopppcc cccccccc + mirror_y = (tile_num & 0x8000); + mirror_x = (tile_num & 0x4000); + tile_pri = (tile_num & 0x2000) ? pri1_pos : pri0_pos; + pal_num = ((tile_num >> 10) & 7); + pal_index = bgpal_index + (pal_num << pal_size); + + if(tile_width == 4) { //16x16 horizontal tile mirroring + if((bool)(hoffset & 8) != mirror_x) tile_num++; + } + + if(tile_height == 4) { //16x16 vertical tile mirroring + if((bool)(voffset & 8) != mirror_y) tile_num += 16; + } + + tile_num &= 0x03ff; + tile_num += tiledata_index; + tile_num &= tile_mask; + + if(bg_td_state[tile_num] == 1) { + render_bg_tile(color_depth, tile_num); + } + + if(mirror_y) voffset ^= 7; //invert y tile pos + tile_ptr = bg_td + (tile_num * 64) + ((voffset & 7) * 8); + } + + if(mirror_x) hoffset ^= 7; //invert x tile pos + col = *(tile_ptr + (hoffset & 7)); + if(col) { + if(is_direct_color_mode) { + col = get_direct_color(pal_num, col); + } else { + col = get_palette(col + pal_index); + } + + if(!hires) { + if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); } + if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); } + } else { + int hx = x >> 1; + if(x & 1) { + if(bg_enabled == true && !wt_main[hx]) { setpixel_main(hx); } + } else { + if(bgsub_enabled == true && !wt_sub[hx]) { setpixel_sub(hx); } + } + } + } + } +} + +#undef setpixel_main +#undef setpixel_sub #endif //ifdef BPPU_CPP diff --git a/src/snes/snes.cpp b/src/snes/snes.cpp index 52880043..84b706fd 100644 --- a/src/snes/snes.cpp +++ b/src/snes/snes.cpp @@ -68,7 +68,7 @@ void SNES::power() { snes_expansion = max(0, min(1, snes.config.expansion_port)); if(snes_region == Autodetect) { - snes_region = cartridge.region() == Cartridge::NTSC ? NTSC : PAL; + snes_region = (cartridge.region() == Cartridge::NTSC ? NTSC : PAL); } scheduler.init(); diff --git a/src/ui_hiro/Makefile b/src/ui_hiro/Makefile deleted file mode 100644 index 2bddc60c..00000000 --- a/src/ui_hiro/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -############################## -### platform configuration ### -############################## - -objects := main hiro $(if $(call streq,$(platform),win),resource) $(objects) - -ifeq ($(platform),x) - link += `pkg-config --libs gtk+-2.0` - link += $(call mklib,Xtst) - hiroflags = `pkg-config --cflags gtk+-2.0` -else ifeq ($(platform),win) - link += $(call mklib,comctl32) - link += $(call mklib,comdlg32) - hiroflags = -endif - -############# -### rules ### -############# - -obj/main.$(obj): $(ui)/main.cpp $(ui)/* $(ui)/base/* $(ui)/loader/* $(ui)/settings/* $(ui)/event/* -obj/hiro.$(obj): lib/hiro/hiro.cpp lib/hiro/* - $(call compile,$(hiroflags)) -obj/resource.$(obj): $(ui)/bsnes.rc; windres $(ui)/bsnes.rc obj/resource.$(obj) - -############### -### targets ### -############### - -ui_build:; -ui_clean:; diff --git a/src/ui_hiro/base/about.cpp b/src/ui_hiro/base/about.cpp deleted file mode 100644 index 2347ab3a..00000000 --- a/src/ui_hiro/base/about.cpp +++ /dev/null @@ -1,34 +0,0 @@ -uintptr_t AboutWindow::close(event_t) { - hide(); - return false; -} - -void AboutWindow::setup() { - create(Window::AutoCenter, 283, 76, translate["About bsnes ..."]); - set_icon(48, 48, (uint32_t*)resource::icon48); - - icon.create(0, 48, 48); - about.create(0, 225, 48, string() - << "bsnes -- " << translate["Version"] << " " << BSNES_VERSION "\n" - << translate["Author"] << ": byuu\n" - << translate["Project began: October 14th, 2004"] - ); - localization.create(0, 273, 18, translate["Localization by: byuu"]); - - attach(icon, 5, 5); - attach(about, 58, 5); - attach(localization, 5, 58); - - on_close = bind(&AboutWindow::close, this); - - uint8_t *buffer = new uint8_t[48 * 48 * 4]; - memcpy(buffer, resource::icon48, 48 * 48 * 4); - for(unsigned i = 0; i < 48 * 48; i++) { - uint8_t alpha = buffer[i * 4 + 3]; - buffer[i * 4 + 2] = uint8_t(1.0 / 256.0 * alpha * buffer[i * 4 + 2]); - buffer[i * 4 + 1] = uint8_t(1.0 / 256.0 * alpha * buffer[i * 4 + 1]); - buffer[i * 4 + 0] = uint8_t(1.0 / 256.0 * alpha * buffer[i * 4 + 0]); - } - memcpy(icon.buffer(), buffer, 48 * 48 * 4); - delete[] buffer; -} diff --git a/src/ui_hiro/base/about.hpp b/src/ui_hiro/base/about.hpp deleted file mode 100644 index aa6d9cc1..00000000 --- a/src/ui_hiro/base/about.hpp +++ /dev/null @@ -1,9 +0,0 @@ -class AboutWindow : public Window { -public: - Canvas icon; - Label about; - Label localization; - - void setup(); - uintptr_t close(event_t); -} window_about; diff --git a/src/ui_hiro/base/main.cpp b/src/ui_hiro/base/main.cpp deleted file mode 100644 index 0f58b0e2..00000000 --- a/src/ui_hiro/base/main.cpp +++ /dev/null @@ -1,499 +0,0 @@ -bool MainWindow::input_ready() { - //allow input if main window has focus - if(focused() == true) return true; - //allow input if config set to never block input - if(config.input.capture_mode == 0) return true; - //block input - return false; -} - -uintptr_t MainWindow::close(event_t) { - event::quit(); - return false; -} - -uintptr_t MainWindow::event(event_t e) { - if(e.type == event_t::Tick) { - if(e.widget == &menu_system_load) { - event::load_cart(); - } - - if(e.widget == &menu_system_power_on) { event::modify_system_state(event::PowerOn); } - if(e.widget == &menu_system_power_off) { event::modify_system_state(event::PowerOff); } - if(e.widget == &menu_system_reset) { event::modify_system_state(event::Reset); } - - if(e.widget == &menu_system_controller_port1_none) { event::update_controller_port1(SNES::Input::DeviceNone); } - if(e.widget == &menu_system_controller_port1_joypad) { event::update_controller_port1(SNES::Input::DeviceJoypad); } - if(e.widget == &menu_system_controller_port1_multitap) { event::update_controller_port1(SNES::Input::DeviceMultitap); } - if(e.widget == &menu_system_controller_port1_mouse) { event::update_controller_port1(SNES::Input::DeviceMouse); } - - if(e.widget == &menu_system_controller_port2_none) { event::update_controller_port2(SNES::Input::DeviceNone); } - if(e.widget == &menu_system_controller_port2_joypad) { event::update_controller_port2(SNES::Input::DeviceJoypad); } - if(e.widget == &menu_system_controller_port2_multitap) { event::update_controller_port2(SNES::Input::DeviceMultitap); } - if(e.widget == &menu_system_controller_port2_mouse) { event::update_controller_port2(SNES::Input::DeviceMouse); } - if(e.widget == &menu_system_controller_port2_superscope) { event::update_controller_port2(SNES::Input::DeviceSuperScope); } - if(e.widget == &menu_system_controller_port2_justifier) { event::update_controller_port2(SNES::Input::DeviceJustifier); } - if(e.widget == &menu_system_controller_port2_justifiers) { event::update_controller_port2(SNES::Input::DeviceJustifiers); } - - if(e.widget == &menu_system_expansion_port_none) { snes.config.expansion_port = SNES::ExpansionNone; } - if(e.widget == &menu_system_expansion_port_bsx) { snes.config.expansion_port = SNES::ExpansionBSX; } - - if(e.widget == &menu_system_region_auto) { snes.config.region = SNES::Autodetect; } - if(e.widget == &menu_system_region_ntsc) { snes.config.region = SNES::NTSC; } - if(e.widget == &menu_system_region_pal) { snes.config.region = SNES::PAL; } - - if(e.widget == &menu_system_exit) { event::quit(); } - - if(e.widget == &menu_settings_videomode_1x) { event::update_multiplier(1); } - if(e.widget == &menu_settings_videomode_2x) { event::update_multiplier(2); } - if(e.widget == &menu_settings_videomode_3x) { event::update_multiplier(3); } - if(e.widget == &menu_settings_videomode_4x) { event::update_multiplier(4); } - if(e.widget == &menu_settings_videomode_5x) { event::update_multiplier(5); } - - if(e.widget == &menu_settings_videomode_aspect_correction) { - event::update_aspect_correction(menu_settings_videomode_aspect_correction.checked()); - } - - if(e.widget == &menu_settings_videomode_fullscreen) { event::toggle_fullscreen(); } - - if(e.widget == &menu_settings_videomode_ntsc) { event::update_region(0); } - if(e.widget == &menu_settings_videomode_pal) { event::update_region(1); } - - if(e.widget == &menu_settings_videofilter_hwpoint) { event::update_hardware_filter(0); } - if(e.widget == &menu_settings_videofilter_hwlinear) { event::update_hardware_filter(1); } - - if(e.widget == &menu_settings_videofilter_swnone) { event::update_software_filter(0); } - if(e.widget == &menu_settings_videofilter_swscanline) { event::update_software_filter(1); } - if(e.widget == &menu_settings_videofilter_swscale2x) { event::update_software_filter(2); } - if(e.widget == &menu_settings_videofilter_swhq2x) { event::update_software_filter(3); } - if(e.widget == &menu_settings_videofilter_swntsc) { event::update_software_filter(4); } - - if(e.widget == &menu_settings_videoframeskip_0) { event::update_frameskip(0); } - if(e.widget == &menu_settings_videoframeskip_1) { event::update_frameskip(1); } - if(e.widget == &menu_settings_videoframeskip_2) { event::update_frameskip(2); } - if(e.widget == &menu_settings_videoframeskip_3) { event::update_frameskip(3); } - if(e.widget == &menu_settings_videoframeskip_4) { event::update_frameskip(4); } - if(e.widget == &menu_settings_videoframeskip_5) { event::update_frameskip(5); } - if(e.widget == &menu_settings_videoframeskip_6) { event::update_frameskip(6); } - if(e.widget == &menu_settings_videoframeskip_7) { event::update_frameskip(7); } - if(e.widget == &menu_settings_videoframeskip_8) { event::update_frameskip(8); } - if(e.widget == &menu_settings_videoframeskip_9) { event::update_frameskip(9); } - - if(e.widget == &menu_settings_mute) { - config.audio.mute = menu_settings_mute.checked(); - } - - if(e.widget == &menu_settings_emuspeed_slowest) { event::update_emulation_speed(0); } - if(e.widget == &menu_settings_emuspeed_slow) { event::update_emulation_speed(1); } - if(e.widget == &menu_settings_emuspeed_normal) { event::update_emulation_speed(2); } - if(e.widget == &menu_settings_emuspeed_fast) { event::update_emulation_speed(3); } - if(e.widget == &menu_settings_emuspeed_fastest) { event::update_emulation_speed(4); } - - if(e.widget == &menu_settings_emuspeed_videosync) { - config.video.synchronize = menu_settings_emuspeed_videosync.checked(); - video.set(Video::Synchronize, config.video.synchronize); - } - - if(e.widget == &menu_settings_emuspeed_audiosync) { - config.audio.synchronize = menu_settings_emuspeed_audiosync.checked(); - audio.set(Audio::Synchronize, config.audio.synchronize); - } - - if(e.widget == &menu_settings_config) { window_settings.show(); } - - if(e.widget == &menu_help_readme) { - window_textview.set_text(translate["bsnes Readme"]); - window_textview.text.set_text(text_readme); - window_textview.focus(); - window_textview.ok.focus(); - } - if(e.widget == &menu_help_license) { - window_textview.set_text(translate["bsnes License"]); - window_textview.text.set_text(text_license); - window_textview.focus(); - window_textview.ok.focus(); - } - if(e.widget == &menu_help_about) { window_about.focus(); } - } - - return true; -} - -uintptr_t MainWindow::input(event_t e) { - uint16_t code = e.param; - int16_t state = e.param >> 16; - - if(state == 0 && code >= mouse::button && code < mouse::button + mouse::buttons) { - event::acquire(); - } - - return true; -} - -uintptr_t MainWindow::block(event_t) { - audio.clear(); - return true; -} - -void MainWindow::setup() { - create(Window::AutoCenter, 256, 224, BSNES_TITLE); - set_background_color(0, 0, 0); - set_icon(48, 48, (uint32_t*)resource::icon48); - - MenuRadioItemGroup group; - attach(menu_system.create(translate["{{menu}}System"])); - menu_system.attach(menu_system_load.create(string() << translate["{{system}}Load Cartridge"] << " ...")); - - menu_system.attach(menu_system_sep1.create()); - menu_system.attach(menu_system_power.create(translate["{{system}}Power"])); - group.add(&menu_system_power_on); - group.add(&menu_system_power_off); - menu_system_power.attach(menu_system_power_on.create(group, translate["{{power}}On"])); - menu_system_power.attach(menu_system_power_off.create(group, translate["{{power}}Off"])); - group.reset(); - menu_system.attach(menu_system_reset.create(translate["{{system}}Reset"])); - - menu_system.attach(menu_system_sep2.create()); - menu_system.attach(menu_system_controller_port1.create(translate["{{system}}Controller Port 1"])); - group.add(&menu_system_controller_port1_none); - group.add(&menu_system_controller_port1_joypad); - group.add(&menu_system_controller_port1_multitap); - group.add(&menu_system_controller_port1_mouse); - menu_system_controller_port1.attach(menu_system_controller_port1_none.create (group, translate["{{controllerport}}None"])); - menu_system_controller_port1.attach(menu_system_controller_port1_joypad.create (group, translate["{{controllerport}}Joypad"])); - menu_system_controller_port1.attach(menu_system_controller_port1_multitap.create(group, translate["{{controllerport}}Multitap"])); - menu_system_controller_port1.attach(menu_system_controller_port1_mouse.create (group, translate["{{controllerport}}Mouse"])); - group.reset(); - menu_system.attach(menu_system_controller_port2.create(translate["{{system}}Controller Port 2"])); - group.add(&menu_system_controller_port2_none); - group.add(&menu_system_controller_port2_joypad); - group.add(&menu_system_controller_port2_multitap); - group.add(&menu_system_controller_port2_mouse); - group.add(&menu_system_controller_port2_superscope); - group.add(&menu_system_controller_port2_justifier); - group.add(&menu_system_controller_port2_justifiers); - menu_system_controller_port2.attach(menu_system_controller_port2_none.create (group, translate["{{controllerport}}None"])); - menu_system_controller_port2.attach(menu_system_controller_port2_joypad.create (group, translate["{{controllerport}}Joypad"])); - menu_system_controller_port2.attach(menu_system_controller_port2_multitap.create (group, translate["{{controllerport}}Multitap"])); - menu_system_controller_port2.attach(menu_system_controller_port2_mouse.create (group, translate["{{controllerport}}Mouse"])); - menu_system_controller_port2.attach(menu_system_controller_port2_superscope.create(group, translate["{{controllerport}}Super Scope"])); - menu_system_controller_port2.attach(menu_system_controller_port2_justifier.create (group, translate["{{controllerport}}Justifier"])); - menu_system_controller_port2.attach(menu_system_controller_port2_justifiers.create(group, translate["{{controllerport}}Two Justifiers"])); - group.reset(); - - menu_system_sep3.create(); - menu_system_expansion_port.create(translate["{{system}}Expansion Port"]); - group.add(&menu_system_expansion_port_none); - group.add(&menu_system_expansion_port_bsx); - menu_system_expansion_port.attach(menu_system_expansion_port_none.create(group, translate["{{expansionport}}None"])); - menu_system_expansion_port.attach(menu_system_expansion_port_bsx.create (group, translate["{{expansionport}}Satellaview"])); - group.reset(); - menu_system_region.create(translate["{{system}}Region"]); - group.add(&menu_system_region_auto); - group.add(&menu_system_region_ntsc); - group.add(&menu_system_region_pal); - menu_system_region.attach(menu_system_region_auto.create(group, translate["{{region}}Auto-detect"])); - menu_system_region.attach(menu_system_region_ntsc.create(group, translate["{{region}}NTSC"])); - menu_system_region.attach(menu_system_region_pal.create (group, translate["{{region}}PAL"])); - group.reset(); - - if(config.misc.show_advanced_options == true) { - menu_system.attach(menu_system_sep3); - menu_system.attach(menu_system_expansion_port); - menu_system.attach(menu_system_region); - } - - menu_system_sep4.create(); - menu_system_exit.create(translate["{{system}}Exit"]); - menu_system.attach(menu_system_sep4); - menu_system.attach(menu_system_exit); - - attach(menu_settings.create(translate["{{menu}}Settings"])); - menu_settings.attach(menu_settings_videomode.create(translate["Video Mode"])); - group.add(&menu_settings_videomode_1x); - group.add(&menu_settings_videomode_2x); - group.add(&menu_settings_videomode_3x); - group.add(&menu_settings_videomode_4x); - group.add(&menu_settings_videomode_5x); - menu_settings_videomode.attach(menu_settings_videomode_1x.create(group, translate["Scale 1x"])); - menu_settings_videomode.attach(menu_settings_videomode_2x.create(group, translate["Scale 2x"])); - menu_settings_videomode.attach(menu_settings_videomode_3x.create(group, translate["Scale 3x"])); - menu_settings_videomode.attach(menu_settings_videomode_4x.create(group, translate["Scale 4x"])); - menu_settings_videomode.attach(menu_settings_videomode_5x.create(group, translate["Scale 5x"])); - group.reset(); - menu_settings_videomode.attach(menu_settings_videomode_sep1.create()); - menu_settings_videomode.attach(menu_settings_videomode_aspect_correction.create(translate["Correct Aspect Ratio"])); - menu_settings_videomode.attach(menu_settings_videomode_fullscreen.create(translate["Fullscreen"])); - menu_settings_videomode.attach(menu_settings_videomode_sep2.create()); - group.add(&menu_settings_videomode_ntsc); - group.add(&menu_settings_videomode_pal); - menu_settings_videomode.attach(menu_settings_videomode_ntsc.create(group, translate["NTSC"])); - menu_settings_videomode.attach(menu_settings_videomode_pal.create(group, translate["PAL"])); - group.reset(); - - menu_settings.attach(menu_settings_videofilter.create(translate["Video Filter"])); - group.add(&menu_settings_videofilter_hwpoint); - group.add(&menu_settings_videofilter_hwlinear); - menu_settings_videofilter_hwpoint.create(group, translate["Point"]); - menu_settings_videofilter_hwlinear.create(group, translate["Linear"]); - group.reset(); - menu_settings_videofilter_sep1.create(); - if(video.cap(Video::Filter)) { - menu_settings_videofilter.attach(menu_settings_videofilter_hwpoint); - menu_settings_videofilter.attach(menu_settings_videofilter_hwlinear); - menu_settings_videofilter.attach(menu_settings_videofilter_sep1); - } - group.add(&menu_settings_videofilter_swnone); - group.add(&menu_settings_videofilter_swscanline); - group.add(&menu_settings_videofilter_swscale2x); - group.add(&menu_settings_videofilter_swhq2x); - group.add(&menu_settings_videofilter_swntsc); - menu_settings_videofilter.attach(menu_settings_videofilter_swnone.create(group, translate["None"])); - menu_settings_videofilter.attach(menu_settings_videofilter_swscanline.create(group, translate["Scanline"])); - menu_settings_videofilter.attach(menu_settings_videofilter_swscale2x.create(group, translate["Scale2x"])); - menu_settings_videofilter.attach(menu_settings_videofilter_swhq2x.create(group, translate["HQ2x"])); - menu_settings_videofilter.attach(menu_settings_videofilter_swntsc.create(group, translate["{{filter}}NTSC"])); - group.reset(); - - menu_settings.attach(menu_settings_videoframeskip.create(translate["Video Frameskip"])); - group.add(&menu_settings_videoframeskip_0); - group.add(&menu_settings_videoframeskip_1); - group.add(&menu_settings_videoframeskip_2); - group.add(&menu_settings_videoframeskip_3); - group.add(&menu_settings_videoframeskip_4); - group.add(&menu_settings_videoframeskip_5); - group.add(&menu_settings_videoframeskip_6); - group.add(&menu_settings_videoframeskip_7); - group.add(&menu_settings_videoframeskip_8); - group.add(&menu_settings_videoframeskip_9); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_0.create(group, translate["0"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_1.create(group, translate["1"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_2.create(group, translate["2"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_3.create(group, translate["3"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_4.create(group, translate["4"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_5.create(group, translate["5"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_6.create(group, translate["6"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_7.create(group, translate["7"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_8.create(group, translate["8"])); - menu_settings_videoframeskip.attach(menu_settings_videoframeskip_9.create(group, translate["9"])); - group.reset(); - - menu_settings.attach(menu_settings_sep1.create()); - menu_settings.attach(menu_settings_mute.create(translate["Mute Audio Output"])); - - menu_settings.attach(menu_settings_sep2.create()); - menu_settings_emuspeed.create(translate["Emulation Speed"]); - group.add(&menu_settings_emuspeed_slowest); - group.add(&menu_settings_emuspeed_slow); - group.add(&menu_settings_emuspeed_normal); - group.add(&menu_settings_emuspeed_fast); - group.add(&menu_settings_emuspeed_fastest); - menu_settings_emuspeed_slowest.create(group, translate["50%"]); - menu_settings_emuspeed_slow.create(group, translate["75%"]); - menu_settings_emuspeed_normal.create(group, translate["100%"]); - menu_settings_emuspeed_fast.create(group, translate["150%"]); - menu_settings_emuspeed_fastest.create(group, translate["200%"]); - group.reset(); - menu_settings_emuspeed_sep1.create(); - menu_settings_emuspeed_videosync.create(translate["Sync Video"]); - menu_settings_emuspeed_audiosync.create(translate["Sync Audio"]); - - if(audio.cap(Audio::Frequency)) { - //only audio can sync to specific frequency rates; video syncs only to monitor refresh rate - menu_settings_emuspeed.attach(menu_settings_emuspeed_slowest); - menu_settings_emuspeed.attach(menu_settings_emuspeed_slow); - menu_settings_emuspeed.attach(menu_settings_emuspeed_normal); - menu_settings_emuspeed.attach(menu_settings_emuspeed_fast); - menu_settings_emuspeed.attach(menu_settings_emuspeed_fastest); - menu_settings_emuspeed.attach(menu_settings_emuspeed_sep1); - } - - if(video.cap(Video::Synchronize)) { - menu_settings_emuspeed.attach(menu_settings_emuspeed_videosync); - } - if(audio.cap(Audio::Synchronize)) { - menu_settings_emuspeed.attach(menu_settings_emuspeed_audiosync); - } - - if(video.cap(Video::Synchronize) || audio.cap(Audio::Synchronize)) { - menu_settings.attach(menu_settings_emuspeed); - } - menu_settings.attach(menu_settings_config.create(string() << translate["Configuration"] << " ...")); - - attach(menu_help.create(translate["{{menu}}Help"])); - menu_help.attach(menu_help_readme.create(string() << translate["{{help}}Readme"] << " ...")); - menu_help.attach(menu_help_license.create(string() << translate["{{help}}License"] << " ...")); - menu_help.attach(menu_help_sep1.create()); - menu_help.attach(menu_help_about.create(string() << translate["{{help}}About"] << " ...")); - - menu_system_power.disable(); - menu_system_reset.disable(); - - view.create(0, 256, 224); - view.on_input = bind(&MainWindow::input, this); - attach(view, 0, 0); - - on_close = bind(&MainWindow::close, this); - on_block = bind(&MainWindow::block, this); - - menu_system_load.on_tick = - menu_system_power_on.on_tick = - menu_system_power_off.on_tick = - menu_system_reset.on_tick = - - menu_system_controller_port1_none.on_tick = - menu_system_controller_port1_joypad.on_tick = - menu_system_controller_port1_multitap.on_tick = - menu_system_controller_port1_mouse.on_tick = - - menu_system_controller_port2_none.on_tick = - menu_system_controller_port2_joypad.on_tick = - menu_system_controller_port2_multitap.on_tick = - menu_system_controller_port2_mouse.on_tick = - menu_system_controller_port2_superscope.on_tick = - menu_system_controller_port2_justifier.on_tick = - menu_system_controller_port2_justifiers.on_tick = - - menu_system_expansion_port_none.on_tick = - menu_system_expansion_port_bsx.on_tick = - - menu_system_region_auto.on_tick = - menu_system_region_ntsc.on_tick = - menu_system_region_pal.on_tick = - - menu_system_exit.on_tick = - - menu_settings_videomode_1x.on_tick = - menu_settings_videomode_2x.on_tick = - menu_settings_videomode_3x.on_tick = - menu_settings_videomode_4x.on_tick = - menu_settings_videomode_5x.on_tick = - menu_settings_videomode_aspect_correction.on_tick = - menu_settings_videomode_fullscreen.on_tick = - menu_settings_videomode_ntsc.on_tick = - menu_settings_videomode_pal.on_tick = - - menu_settings_videofilter_hwpoint.on_tick = - menu_settings_videofilter_hwlinear.on_tick = - menu_settings_videofilter_swnone.on_tick = - menu_settings_videofilter_swscanline.on_tick = - menu_settings_videofilter_swscale2x.on_tick = - menu_settings_videofilter_swhq2x.on_tick = - menu_settings_videofilter_swntsc.on_tick = - - menu_settings_videoframeskip_0.on_tick = - menu_settings_videoframeskip_1.on_tick = - menu_settings_videoframeskip_2.on_tick = - menu_settings_videoframeskip_3.on_tick = - menu_settings_videoframeskip_4.on_tick = - menu_settings_videoframeskip_5.on_tick = - menu_settings_videoframeskip_6.on_tick = - menu_settings_videoframeskip_7.on_tick = - menu_settings_videoframeskip_8.on_tick = - menu_settings_videoframeskip_9.on_tick = - - menu_settings_mute.on_tick = - menu_settings_emuspeed_slowest.on_tick = - menu_settings_emuspeed_slow.on_tick = - menu_settings_emuspeed_normal.on_tick = - menu_settings_emuspeed_fast.on_tick = - menu_settings_emuspeed_fastest.on_tick = - menu_settings_emuspeed_videosync.on_tick = - menu_settings_emuspeed_audiosync.on_tick = - menu_settings_config.on_tick = - - menu_help_readme.on_tick = - menu_help_license.on_tick = - menu_help_about.on_tick = - - bind(&MainWindow::event, this); - - status.show(); -} - -void MainWindow::sync() { - event::load_video_settings(); - - switch(snes.config.controller_port1) { default: - case SNES::Input::DeviceNone: menu_system_controller_port1_none.check(); break; - case SNES::Input::DeviceJoypad: menu_system_controller_port1_joypad.check(); break; - case SNES::Input::DeviceMultitap: menu_system_controller_port1_multitap.check(); break; - case SNES::Input::DeviceMouse: menu_system_controller_port1_mouse.check(); break; - } - - switch(snes.config.controller_port2) { default: - case SNES::Input::DeviceNone: menu_system_controller_port2_none.check(); break; - case SNES::Input::DeviceJoypad: menu_system_controller_port2_joypad.check(); break; - case SNES::Input::DeviceMultitap: menu_system_controller_port2_multitap.check(); break; - case SNES::Input::DeviceMouse: menu_system_controller_port2_mouse.check(); break; - case SNES::Input::DeviceSuperScope: menu_system_controller_port2_superscope.check(); break; - case SNES::Input::DeviceJustifier: menu_system_controller_port2_justifier.check(); break; - case SNES::Input::DeviceJustifiers: menu_system_controller_port2_justifiers.check(); break; - } - - switch(snes.config.expansion_port) { default: - case SNES::ExpansionNone: menu_system_expansion_port_none.check(); break; - case SNES::ExpansionBSX: menu_system_expansion_port_bsx.check(); break; - } - - switch(snes.config.region) { default: - case SNES::Autodetect: menu_system_region_auto.check(); break; - case SNES::NTSC: menu_system_region_ntsc.check(); break; - case SNES::PAL: menu_system_region_pal.check(); break; - } - - switch(event::video_settings.multiplier) { default: - case 1: menu_settings_videomode_1x.check(); break; - case 2: menu_settings_videomode_2x.check(); break; - case 3: menu_settings_videomode_3x.check(); break; - case 4: menu_settings_videomode_4x.check(); break; - case 5: menu_settings_videomode_5x.check(); break; - } - - menu_settings_videomode_aspect_correction.check(event::video_settings.aspect_correction); - menu_settings_videomode_fullscreen.check(event::video_settings.mode == 1); - - switch(event::video_settings.region) { default: - case 0: menu_settings_videomode_ntsc.check(); break; - case 1: menu_settings_videomode_pal.check(); break; - } - - switch(event::video_settings.hardware_filter) { default: - case 0: menu_settings_videofilter_hwpoint.check(); break; - case 1: menu_settings_videofilter_hwlinear.check(); break; - } - - switch(event::video_settings.software_filter) { default: - case 0: menu_settings_videofilter_swnone.check(); break; - case 1: menu_settings_videofilter_swscanline.check(); break; - case 2: menu_settings_videofilter_swscale2x.check(); break; - case 3: menu_settings_videofilter_swhq2x.check(); break; - case 4: menu_settings_videofilter_swntsc.check(); break; - } - - menu_settings_mute.check(config.audio.mute); - - switch(config.video.frameskip) { - case 0: menu_settings_videoframeskip_0.check(); break; - case 1: menu_settings_videoframeskip_1.check(); break; - case 2: menu_settings_videoframeskip_2.check(); break; - case 3: menu_settings_videoframeskip_3.check(); break; - case 4: menu_settings_videoframeskip_4.check(); break; - case 5: menu_settings_videoframeskip_5.check(); break; - case 6: menu_settings_videoframeskip_6.check(); break; - case 7: menu_settings_videoframeskip_7.check(); break; - case 8: menu_settings_videoframeskip_8.check(); break; - case 9: menu_settings_videoframeskip_9.check(); break; - } - - switch(config.system.emulation_speed) { - case 0: menu_settings_emuspeed_slowest.check(); break; - case 1: menu_settings_emuspeed_slow.check(); break; - case 2: menu_settings_emuspeed_normal.check(); break; - case 3: menu_settings_emuspeed_fast.check(); break; - case 4: menu_settings_emuspeed_fastest.check(); break; - } - - menu_settings_emuspeed_videosync.check(config.video.synchronize); - menu_settings_emuspeed_audiosync.check(config.audio.synchronize); -} diff --git a/src/ui_hiro/base/main.hpp b/src/ui_hiro/base/main.hpp deleted file mode 100644 index 40a98a5d..00000000 --- a/src/ui_hiro/base/main.hpp +++ /dev/null @@ -1,98 +0,0 @@ -class MainWindow : public Window { -public: - MenuGroup menu_system; - MenuItem menu_system_load; - MenuSeparator menu_system_sep1; - MenuGroup menu_system_power; - MenuRadioItem menu_system_power_on; - MenuRadioItem menu_system_power_off; - MenuItem menu_system_reset; - MenuSeparator menu_system_sep2; - MenuGroup menu_system_controller_port1; - MenuRadioItem menu_system_controller_port1_none; - MenuRadioItem menu_system_controller_port1_joypad; - MenuRadioItem menu_system_controller_port1_multitap; - MenuRadioItem menu_system_controller_port1_mouse; - MenuGroup menu_system_controller_port2; - MenuRadioItem menu_system_controller_port2_none; - MenuRadioItem menu_system_controller_port2_joypad; - MenuRadioItem menu_system_controller_port2_multitap; - MenuRadioItem menu_system_controller_port2_mouse; - MenuRadioItem menu_system_controller_port2_superscope; - MenuRadioItem menu_system_controller_port2_justifier; - MenuRadioItem menu_system_controller_port2_justifiers; - MenuSeparator menu_system_sep3; - MenuGroup menu_system_expansion_port; - MenuRadioItem menu_system_expansion_port_none; - MenuRadioItem menu_system_expansion_port_bsx; - MenuGroup menu_system_region; - MenuRadioItem menu_system_region_auto; - MenuRadioItem menu_system_region_ntsc; - MenuRadioItem menu_system_region_pal; - MenuSeparator menu_system_sep4; - MenuItem menu_system_exit; - - MenuGroup menu_settings; - MenuGroup menu_settings_videomode; - MenuRadioItem menu_settings_videomode_1x; - MenuRadioItem menu_settings_videomode_2x; - MenuRadioItem menu_settings_videomode_3x; - MenuRadioItem menu_settings_videomode_4x; - MenuRadioItem menu_settings_videomode_5x; - MenuSeparator menu_settings_videomode_sep1; - MenuCheckItem menu_settings_videomode_aspect_correction; - MenuCheckItem menu_settings_videomode_fullscreen; - MenuSeparator menu_settings_videomode_sep2; - MenuRadioItem menu_settings_videomode_ntsc; - MenuRadioItem menu_settings_videomode_pal; - MenuGroup menu_settings_videofilter; - MenuRadioItem menu_settings_videofilter_hwpoint; - MenuRadioItem menu_settings_videofilter_hwlinear; - MenuSeparator menu_settings_videofilter_sep1; - MenuRadioItem menu_settings_videofilter_swnone; - MenuRadioItem menu_settings_videofilter_swscanline; - MenuRadioItem menu_settings_videofilter_swscale2x; - MenuRadioItem menu_settings_videofilter_swhq2x; - MenuRadioItem menu_settings_videofilter_swntsc; - MenuGroup menu_settings_videoframeskip; - MenuRadioItem menu_settings_videoframeskip_0; - MenuRadioItem menu_settings_videoframeskip_1; - MenuRadioItem menu_settings_videoframeskip_2; - MenuRadioItem menu_settings_videoframeskip_3; - MenuRadioItem menu_settings_videoframeskip_4; - MenuRadioItem menu_settings_videoframeskip_5; - MenuRadioItem menu_settings_videoframeskip_6; - MenuRadioItem menu_settings_videoframeskip_7; - MenuRadioItem menu_settings_videoframeskip_8; - MenuRadioItem menu_settings_videoframeskip_9; - MenuSeparator menu_settings_sep1; - MenuCheckItem menu_settings_mute; - MenuSeparator menu_settings_sep2; - MenuGroup menu_settings_emuspeed; - MenuRadioItem menu_settings_emuspeed_slowest; - MenuRadioItem menu_settings_emuspeed_slow; - MenuRadioItem menu_settings_emuspeed_normal; - MenuRadioItem menu_settings_emuspeed_fast; - MenuRadioItem menu_settings_emuspeed_fastest; - MenuSeparator menu_settings_emuspeed_sep1; - MenuCheckItem menu_settings_emuspeed_videosync; - MenuCheckItem menu_settings_emuspeed_audiosync; - MenuItem menu_settings_config; - - MenuGroup menu_help; - MenuItem menu_help_readme; - MenuItem menu_help_license; - MenuSeparator menu_help_sep1; - MenuItem menu_help_about; - - Canvas view; - - bool input_ready(); - void setup(); - void sync(); - - uintptr_t close(event_t); - uintptr_t event(event_t); - uintptr_t input(event_t); - uintptr_t block(event_t); -} window_main; diff --git a/src/ui_hiro/base/textview.cpp b/src/ui_hiro/base/textview.cpp deleted file mode 100644 index b3b84d92..00000000 --- a/src/ui_hiro/base/textview.cpp +++ /dev/null @@ -1,17 +0,0 @@ -uintptr_t TextViewWindow::close(event_t) { - hide(); - return false; -} - -void TextViewWindow::setup() { - create(Window::AutoCenter, 415, 450); - set_icon(48, 48, (uint32_t*)resource::icon48); - - text.create(Editbox::Multiline | Editbox::Readonly | Editbox::HorizontalScrollNever | Editbox::VerticalScrollAuto, 405, 410); - ok.create(0, 100, 25, translate["{{textview}}Ok"]); - - attach(text, 5, 5); - attach(ok, 310, 420); - - on_close = ok.on_tick = bind(&TextViewWindow::close, this); -} diff --git a/src/ui_hiro/base/textview.hpp b/src/ui_hiro/base/textview.hpp deleted file mode 100644 index 6db0ed86..00000000 --- a/src/ui_hiro/base/textview.hpp +++ /dev/null @@ -1,8 +0,0 @@ -class TextViewWindow : public Window { -public: - Editbox text; - Button ok; - - void setup(); - uintptr_t close(event_t); -} window_textview; diff --git a/src/ui_hiro/bsnes.rc b/src/ui_hiro/bsnes.rc deleted file mode 100644 index 83058c63..00000000 --- a/src/ui_hiro/bsnes.rc +++ /dev/null @@ -1,4 +0,0 @@ -#define IDI_APP_ICON 100 - -1 24 "data/bsnes.Manifest" -IDI_APP_ICON ICON DISCARDABLE "data/bsnes.ico" diff --git a/src/ui_hiro/config.cpp b/src/ui_hiro/config.cpp deleted file mode 100644 index ccd258bd..00000000 --- a/src/ui_hiro/config.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include - -class bsnes_configuration : public configuration { -public: - char bsnes_cfg[PATH_MAX], locale_cfg[PATH_MAX]; - - struct System { - string video, audio, input; - bool invoke_crash_handler; - unsigned emulation_speed; - } system; - - struct Video { - unsigned mode; - bool synchronize; - - struct Windowed { - bool aspect_correction; - unsigned region, multiplier, hardware_filter, software_filter; - } windowed; - - struct Fullscreen { - bool aspect_correction; - unsigned region, multiplier, hardware_filter, software_filter; - } fullscreen; - - unsigned aspect_ntsc_x, aspect_ntsc_y, aspect_pal_x, aspect_pal_y; - unsigned frameskip; - - unsigned contrast, brightness, gamma; - bool gamma_ramp, sepia, grayscale, invert; - bool ntsc_filter_merge_fields; - } video; - - struct Audio { - unsigned output_frequency, input_frequency; - unsigned latency; - unsigned volume, mute; - bool synchronize; - } audio; - - struct Input { - unsigned capture_mode; - bool allow_invalid_input; - unsigned analog_axis_resistance; - - 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, l, r; - } mouse1, mouse2; - - struct SuperScope { - string x, y, trigger, turbo, cursor, pause; - } superscope; - - struct Justifier { - string x, y, trigger, start; - } justifier1, justifier2; - - struct GUI { - string load, pause, reset, power, quit; - string speed_decrease, speed_increase; - string frameskip_decrease, frameskip_increase; - string toggle_fullscreen, toggle_menubar, toggle_statusbar; - } gui; - - struct Debugger { - string export_memory; - string toggle_cputrace, toggle_cputracemask; - string toggle_smptrace, toggle_smptracemask; - } debugger; - } input; - - struct Misc { - bool start_in_fullscreen_mode; - unsigned window_opacity; - bool show_advanced_options; - } misc; - - bsnes_configuration() { - //======== - //external - //======== - - attach(snes.config.controller_port1 = SNES::Input::DeviceJoypad, "snes.controller_port1"); - attach(snes.config.controller_port2 = SNES::Input::DeviceJoypad, "snes.controller_port2"); - attach(snes.config.expansion_port = SNES::ExpansionBSX, "snes.expansion_port"); - attach(snes.config.region = SNES::Autodetect, "snes.region"); - - attach(snes.config.file.autodetect_type = false, "file.autodetect_type", "Detect filetype by header, rather than file extension"); - attach(snes.config.file.bypass_patch_crc32 = false, "file.bypass_patch_crc32", "Apply UPS patches even when checksum match fails"); - - attach(snes.config.path.rom = "", "path.rom"); - attach(snes.config.path.save = "", "path.save"); - attach(snes.config.path.patch = "", "path.patch"); - attach(snes.config.path.cheat = "", "path.cheat"); - attach(snes.config.path.data = "", "path.data"); - attach(snes.config.path.bsx = "", "path.bsx"); - attach(snes.config.path.st = "", "path.st"); - - attach(snes.config.cpu.ntsc_clock_rate = 21477272, "cpu.ntsc_clock_rate"); - attach(snes.config.cpu.pal_clock_rate = 21281370, "cpu.pal_clock_rate"); - attach(snes.config.cpu.alu_mul_delay = 2, "cpu.alu_mul_delay"); - attach(snes.config.cpu.alu_div_delay = 2, "cpu.alu_div_delay"); - attach(snes.config.cpu.wram_init_value = 0x55, "cpu.wram_init_value"); - - attach(snes.config.smp.ntsc_clock_rate = 32041 * 768, "smp.ntsc_clock_rate"); - attach(snes.config.smp.pal_clock_rate = 32041 * 768, "smp.pal_clock_rate"); - - //======== - //internal - //======== - - *bsnes_cfg = 0; - *locale_cfg = 0; - - attach(system.video = "", "system.video", "Video hardware interface"); - attach(system.audio = "", "system.audio", "Audio hardware interface"); - attach(system.input = "", "system.input", "Input hardware interface"); - - attach(system.invoke_crash_handler = false, "system.invoke_crash_handler", "Do not modify! Used to detect crashes caused by driver initialization"); - attach(system.emulation_speed = 2, "system.emulation_speed", "Relative speed of emulator compared to hardware"); - - video.mode = 0; - attach(video.synchronize = false, "video.synchronize", "Synchronize to video refresh rate"); - - attach(video.windowed.aspect_correction = true, "video.windowed.aspect_correction"); - attach(video.windowed.region = 0, "video.windowed.region"); - attach(video.windowed.multiplier = 2, "video.windowed.multiplier"); - attach(video.windowed.hardware_filter = 1, "video.windowed.hardware_filter"); - attach(video.windowed.software_filter = 0, "video.windowed.software_filter"); - - attach(video.fullscreen.aspect_correction = true, "video.fullscreen.aspect_correction"); - attach(video.fullscreen.region = 0, "video.fullscreen.region"); - attach(video.fullscreen.multiplier = 2, "video.fullscreen.multiplier"); - attach(video.fullscreen.hardware_filter = 1, "video.fullscreen.hardware_filter"); - attach(video.fullscreen.software_filter = 0, "video.fullscreen.software_filter"); - - attach(video.aspect_ntsc_x = 54, "video.aspect_ntsc_x", "NTSC TV aspect correction ratio"); - attach(video.aspect_ntsc_y = 47, "video.aspect_ntsc_y"); - attach(video.aspect_pal_x = 32, "video.aspect_pal_x", "PAL TV aspect correction ratio"); - attach(video.aspect_pal_y = 23, "video.aspect_pal_y"); - - video.frameskip = 0; - attach(video.contrast = 0, "video.contrast"); - attach(video.brightness = 0, "video.brightness"); - attach(video.gamma = 100, "video.gamma"); - - attach(video.gamma_ramp = true, "video.gamma_ramp"); - attach(video.sepia = false, "video.sepia"); - attach(video.grayscale = false, "video.grayscale"); - attach(video.invert = false, "video.invert"); - attach(video.ntsc_filter_merge_fields = true, "video.ntsc_filter_merge_fields"); - - attach(audio.output_frequency = 48000, "audio.output_frequency"); - attach(audio.input_frequency = 32000, "audio.input_frequency"); - attach(audio.latency = 100, "audio.latency"); - attach(audio.volume = 100, "audio.volume"); - attach(audio.mute = false, "audio.mute"); - attach(audio.synchronize = true, "audio.synchronize"); - - attach(input.capture_mode = 2, "input.capture_mode", "Capture method: 0 = allow, 1 = ignore, 2 = pause"); - attach(input.allow_invalid_input = false, "input.allow_invalid_input", "Allow D-pad up+down and left+right combinations (not recommended)"); - attach(input.analog_axis_resistance = 50, "input.analog_axis_resistance", "Analog stick resistance percentage; lower = less, higher = more"); - - attach(input.joypad1.up = "up", "input.joypad1.up"); - attach(input.joypad1.down = "down", "input.joypad1.down"); - attach(input.joypad1.left = "left", "input.joypad1.left"); - attach(input.joypad1.right = "right", "input.joypad1.right"); - attach(input.joypad1.a = "x", "input.joypad1.a"); - attach(input.joypad1.b = "z", "input.joypad1.b"); - attach(input.joypad1.x = "s", "input.joypad1.x"); - attach(input.joypad1.y = "a", "input.joypad1.y"); - attach(input.joypad1.l = "d", "input.joypad1.l"); - attach(input.joypad1.r = "c", "input.joypad1.r"); - attach(input.joypad1.select = "rshift", "input.joypad1.select"); - attach(input.joypad1.start = "return", "input.joypad1.start"); - - attach_joypad(input.joypad2, "input.joypad2"); - attach_joypad(input.multitap1a, "input.multitap1a"); - attach_joypad(input.multitap1b, "input.multitap1b"); - attach_joypad(input.multitap1c, "input.multitap1c"); - attach_joypad(input.multitap1d, "input.multitap1d"); - attach_joypad(input.multitap2a, "input.multitap2a"); - attach_joypad(input.multitap2b, "input.multitap2b"); - attach_joypad(input.multitap2c, "input.multitap2c"); - attach_joypad(input.multitap2d, "input.multitap2d"); - - attach(input.mouse1.x = "mouse1.x", "input.mouse1.x"); - attach(input.mouse1.y = "mouse1.y", "input.mouse1.y"); - attach(input.mouse1.l = "mouse1.button00", "input.mouse1.l"); - attach(input.mouse1.r = "mouse1.button02", "input.mouse1.r"); - - attach(input.mouse2.x = "mouse2.x", "input.mouse2.x"); - attach(input.mouse2.y = "mouse2.y", "input.mouse2.y"); - attach(input.mouse2.l = "mouse2.button00", "input.mouse2.l"); - attach(input.mouse2.r = "mouse2.button02", "input.mouse2.r"); - - attach(input.superscope.x = "mouse.x", "input.superscope.x"); - attach(input.superscope.y = "mouse.y", "input.superscope.y"); - attach(input.superscope.trigger = "mouse.button00", "input.superscope.trigger"); - attach(input.superscope.cursor = "mouse.button02", "input.superscope.cursor"); - attach(input.superscope.turbo = "t", "input.superscope.turbo"); - attach(input.superscope.pause = "p", "input.superscope.pause"); - - attach(input.justifier1.x = "mouse.x", "input.justifier1.x"); - attach(input.justifier1.y = "mouse.y", "input.justifier1.y"); - attach(input.justifier1.trigger = "mouse.button00", "input.justifier1.trigger"); - attach(input.justifier1.start = "mouse.button02", "input.justifier1.start"); - - attach(input.justifier2.x = "none", "input.justifier2.x"); - attach(input.justifier2.y = "none", "input.justifier2.y"); - attach(input.justifier2.trigger = "none", "input.justifier2.trigger"); - attach(input.justifier2.start = "none", "input.justifier2.start"); - - attach(input.gui.load = "none", "input.gui.load"); - attach(input.gui.pause = "f12", "input.gui.pause"); - attach(input.gui.reset = "none", "input.gui.reset"); - attach(input.gui.power = "none", "input.gui.power"); - attach(input.gui.quit = "none", "input.gui.quit"); - - attach(input.gui.speed_decrease = "divide", "input.gui.speed_decrease"); - attach(input.gui.speed_increase = "multiply", "input.gui.speed_increase"); - attach(input.gui.frameskip_decrease = "subtract", "input.gui.frameskip_decrease"); - attach(input.gui.frameskip_increase = "add", "input.gui.frameskip_increase"); - - attach(input.gui.toggle_fullscreen = "f11", "input.gui.toggle_fullscreen"); - attach(input.gui.toggle_menubar = "escape", "input.gui.toggle_menubar"); - attach(input.gui.toggle_statusbar = "escape", "input.gui.toggle_statusbar"); - - attach(input.debugger.export_memory = "none", "input.debugger.export_memory"); - attach(input.debugger.toggle_cputrace = "none", "input.debugger.toggle_cputrace"); - attach(input.debugger.toggle_cputracemask = "none", "input.debugger.toggle_cputracemask"); - attach(input.debugger.toggle_smptrace = "none", "input.debugger.toggle_smptrace"); - attach(input.debugger.toggle_smptracemask = "none", "input.debugger.toggle_smptracemask"); - - attach(misc.start_in_fullscreen_mode = false, "misc.start_in_fullscreen_mode"); - attach(misc.window_opacity = 100, "misc.window_opacity", "Translucency percentage of helper windows (50%-100%)"); - attach(misc.show_advanced_options = false, "misc.show_advanced_options", "Enable developer-oriented GUI options"); - } - - void attach_joypad(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"); - } -} config; diff --git a/src/ui_hiro/event/debugger.cpp b/src/ui_hiro/event/debugger.cpp deleted file mode 100644 index e99e0ad1..00000000 --- a/src/ui_hiro/event/debugger.cpp +++ /dev/null @@ -1,70 +0,0 @@ -void export_memory() { - file fp; - - fp.open(Cartridge::filepath("wram.bin", snes.config.path.data), file::mode_write); - for(unsigned i = 0; i < memory::wram.size(); i++) fp.write(memory::wram[i]); - fp.close(); - - fp.open(Cartridge::filepath("apuram.bin", snes.config.path.data), file::mode_write); - for(unsigned i = 0; i < memory::apuram.size(); i++) fp.write(memory::apuram[i]); - fp.close(); - - fp.open(Cartridge::filepath("vram.bin", snes.config.path.data), file::mode_write); - for(unsigned i = 0; i < memory::vram.size(); i++) fp.write(memory::vram[i]); - fp.close(); - - fp.open(Cartridge::filepath("oam.bin", snes.config.path.data), file::mode_write); - for(unsigned i = 0; i < memory::oam.size(); i++) fp.write(memory::oam[i]); - fp.close(); - - fp.open(Cartridge::filepath("cgram.bin", snes.config.path.data), file::mode_write); - for(unsigned i = 0; i < memory::cgram.size(); i++) fp.write(memory::cgram[i]); - fp.close(); - - status.flush(); - status.enqueue(translate["Memory exported."]); -} - -void toggle_cputrace() { - if(!tracer.enabled()) tracer.enable(true); - - bool state = !tracer.cpuop_enabled(); - tracer.cpuop_enable(state); - status.flush(); - status.enqueue(state - ? translate["S-CPU tracing enabled."] - : translate["S-CPU tracing disabled."] - ); -} - -void toggle_cputracemask() { - bool state = !tracer.cpuopmask_enabled(); - tracer.cpuopmask_enable(state); - status.flush(); - status.enqueue(state - ? translate["S-CPU trace mask enabled."] - : translate["S-CPU trace mask disabled."] - ); -} - -void toggle_smptrace() { - if(!tracer.enabled()) tracer.enable(true); - - bool state = !tracer.smpop_enabled(); - tracer.smpop_enable(state); - status.flush(); - status.enqueue(state - ? translate["S-SMP tracing enabled."] - : translate["S-SMP tracing disabled."] - ); -} - -void toggle_smptracemask() { - bool state = !tracer.smpopmask_enabled(); - tracer.smpopmask_enable(state); - status.flush(); - status.enqueue(state - ? translate["S-SMP trace mask enabled."] - : translate["S-SMP trace mask disabled."] - ); -} diff --git a/src/ui_hiro/event/debugger.hpp b/src/ui_hiro/event/debugger.hpp deleted file mode 100644 index b706647d..00000000 --- a/src/ui_hiro/event/debugger.hpp +++ /dev/null @@ -1,5 +0,0 @@ -void export_memory(); -void toggle_cputrace(); -void toggle_cputracemask(); -void toggle_smptrace(); -void toggle_smptracemask(); diff --git a/src/ui_hiro/event/event.cpp b/src/ui_hiro/event/event.cpp deleted file mode 100644 index 9cafbfc8..00000000 --- a/src/ui_hiro/event/event.cpp +++ /dev/null @@ -1,512 +0,0 @@ -namespace event { - -#include "debugger.cpp" - -void input_event(uint16_t code) { - if(code == keyboard::escape && input.acquired()) { - unacquire(); - return; - } - - if(window_main.focused()) { - if(code == inputuigeneral.load.code) load_cart(); - if(code == inputuigeneral.pause.code) { - app.pause = !app.pause; //toggle pause state - if(app.pause) { - audio.clear(); - if(cartridge.loaded()) status.update(); - } - } - if(code == inputuigeneral.reset.code) modify_system_state(Reset); - if(code == inputuigeneral.power.code) modify_system_state(PowerCycle); - if(code == inputuigeneral.quit.code) quit(); - if(code == inputuigeneral.speed_decrease.code) { - update_emulation_speed(config.system.emulation_speed - 1); - } - if(code == inputuigeneral.speed_increase.code) { - update_emulation_speed(config.system.emulation_speed + 1); - } - if(code == inputuigeneral.frameskip_decrease.code) { - update_frameskip(config.video.frameskip - 1); - } - if(code == inputuigeneral.frameskip_increase.code) { - update_frameskip(config.video.frameskip + 1); - } - if(code == inputuigeneral.toggle_fullscreen.code) toggle_fullscreen(); - if(code == inputuigeneral.toggle_menubar.code) toggle_menubar(); - if(code == inputuigeneral.toggle_statusbar.code) toggle_statusbar(); - - if(code == inputuidebugger.export_memory.code) export_memory(); - if(code == inputuidebugger.toggle_cputrace.code) toggle_cputrace(); - if(code == inputuidebugger.toggle_cputracemask.code) toggle_cputracemask(); - if(code == inputuidebugger.toggle_smptrace.code) toggle_smptrace(); - if(code == inputuidebugger.toggle_smptracemask.code) toggle_smptracemask(); - } -} - -void acquire() { - if(cartridge.loaded() == true) { - if(snes.config.controller_port1 == SNES::Input::DeviceMouse - || snes.config.controller_port2 == SNES::Input::DeviceMouse - || snes.config.controller_port2 == SNES::Input::DeviceSuperScope - || snes.config.controller_port2 == SNES::Input::DeviceJustifier - || snes.config.controller_port2 == SNES::Input::DeviceJustifiers - ) input.acquire(); - } -} - -void unacquire() { - input.unacquire(); -} - -void load_video_settings() { - video_settings.mode = config.video.mode; - video_settings.synchronize = config.video.synchronize; - - switch(video_settings.mode) { default: - case 0: { //windowed - video_settings.aspect_correction = config.video.windowed.aspect_correction; - video_settings.region = config.video.windowed.region; - video_settings.multiplier = config.video.windowed.multiplier; - video_settings.hardware_filter = config.video.windowed.hardware_filter; - video_settings.software_filter = config.video.windowed.software_filter; - } break; - - case 1: { //fullscreen - video_settings.aspect_correction = config.video.fullscreen.aspect_correction; - video_settings.region = config.video.fullscreen.region; - video_settings.multiplier = config.video.fullscreen.multiplier; - video_settings.hardware_filter = config.video.fullscreen.hardware_filter; - video_settings.software_filter = config.video.fullscreen.software_filter; - } break; - } -} - -void update_aspect_correction(bool aspect_correction) { - switch(config.video.mode) { default: - case 0: config.video.windowed.aspect_correction = aspect_correction; break; - case 1: config.video.fullscreen.aspect_correction = aspect_correction; break; - } - update_video_settings(); -} - -void update_multiplier(unsigned multiplier) { - switch(config.video.mode) { default: - case 0: config.video.windowed.multiplier = multiplier; break; - case 1: config.video.fullscreen.multiplier = multiplier; break; - } - update_video_settings(); -} - -void update_region(unsigned region) { - switch(config.video.mode) { default: - case 0: config.video.windowed.region = region; break; - case 1: config.video.fullscreen.region = region; break; - } - update_video_settings(); -} - -void update_hardware_filter(unsigned hardware_filter) { - switch(config.video.mode) { default: - case 0: config.video.windowed.hardware_filter = hardware_filter; break; - case 1: config.video.fullscreen.hardware_filter = hardware_filter; break; - } - update_video_settings(); -} - -void update_software_filter(unsigned software_filter) { - switch(config.video.mode) { default: - case 0: config.video.windowed.software_filter = software_filter; break; - case 1: config.video.fullscreen.software_filter = software_filter; break; - } - update_video_settings(); -} - -void update_frameskip(int speed) { - config.video.frameskip = max(0, min(9, speed)); - window_main.sync(); -} - -void update_emulation_speed(int speed) { - config.system.emulation_speed = speed = max(0, min(4, speed)); - - double scale[] = { 0.50, 0.75, 1.00, 1.50, 2.00 }; - unsigned outfreq = config.audio.output_frequency; - unsigned infreq = config.audio.input_frequency * scale[speed] + 0.5; - - audio.set(Audio::Resample, outfreq != infreq); //only resample when necessary - audio.set(Audio::ResampleOutputFrequency, outfreq); - audio.set(Audio::ResampleInputFrequency, infreq); - - window_main.sync(); -} - -void modify_system_state(system_state_t state) { - video.clear(); - audio.clear(); - - switch(state) { - case LoadCart: { - if(cartridge.loaded() == false) break; - - app.power = true; - app.pause = false; - snes.power(); - - status.flush(); - string t = translate["Loaded $."]; - t.replace("$", cartridge.name()); - status.enqueue(t); - if(cartridge.patched()) status.enqueue(translate["UPS patch applied."]); - - //warn if unsupported hardware detected - string message; - message = translate["Warning: unsupported $ chip detected."]; - if(cartridge.has_superfx()) { message.replace("$", "SuperFX"); status.enqueue(message); } - if(cartridge.has_sa1()) { message.replace("$", "SA-1"); status.enqueue(message); } - if(cartridge.has_st011()) { message.replace("$", "ST011"); status.enqueue(message); } - if(cartridge.has_st018()) { message.replace("$", "ST018"); status.enqueue(message); } - - message = translate["Warning: partially supported $ chip detected."]; - if(cartridge.has_dsp3()) { message.replace("$", "DSP-3"); status.enqueue(message); } - } break; - - case UnloadCart: { - if(cartridge.loaded() == true) break; - cartridge.unload(); - - app.power = false; - app.pause = true; - - status.flush(); - string t = translate["Unloaded $."]; - t.replace("$", cartridge.name()); - status.enqueue(t); - } break; - - case PowerOn: { - if(cartridge.loaded() == false || app.power == true) break; - - app.power = true; - app.pause = false; - snes.power(); - - status.flush(); - status.enqueue(translate["Power on."]); - } break; - - case PowerOff: { - if(cartridge.loaded() == false || app.power == false) break; - - app.power = false; - app.pause = true; - - status.flush(); - status.enqueue(translate["Power off."]); - } break; - - case PowerCycle: { - if(cartridge.loaded() == false) break; - - app.power = true; - app.pause = false; - snes.power(); - - status.flush(); - status.enqueue(translate["System power was cycled."]); - } break; - - case Reset: { - if(cartridge.loaded() == false || app.power == false) break; - - app.pause = false; - snes.reset(); - - status.flush(); - status.enqueue(translate["System was reset."]); - } break; - } - - window_main.menu_system_power.enable(cartridge.loaded()); - window_main.menu_system_reset.enable(cartridge.loaded() && app.power); - window_main.menu_system_expansion_port_none.enable(cartridge.loaded() && !app.power); - window_main.menu_system_expansion_port_bsx.enable(cartridge.loaded() && !app.power); - window_main.menu_system_region_auto.enable(cartridge.loaded() && !app.power); - window_main.menu_system_region_ntsc.enable(cartridge.loaded() && !app.power); - window_main.menu_system_region_pal.enable(cartridge.loaded() && !app.power); - app.power - ? window_main.menu_system_power_on.check() - : window_main.menu_system_power_off.check(); - window_cheat_editor.refresh(); - if(cartridge.loaded() == false) window_cheat_code_editor.hide(); -} - -void update_controller_port1(int device) { - unsigned current_device = snes.config.controller_port1; - - if(device != current_device) { - snes.input.port_set_device(0, snes.config.controller_port1 = device); - } - - window_main.sync(); -} - -void update_controller_port2(int device) { - unsigned current_device = snes.config.controller_port2; - - if(device != current_device) { - snes.input.port_set_device(1, snes.config.controller_port2 = device); - } - - window_main.sync(); -} - -void update_video_settings() { - load_video_settings(); - - SNES::Video::Mode mode = (video_settings.region == 0 ? SNES::Video::ModeNTSC : SNES::Video::ModePAL); - unsigned width = 256; - unsigned height = (mode == SNES::Video::ModeNTSC ? 224 : 239); - unsigned multiplier = max(1, min(5, video_settings.multiplier)); - - width *= multiplier; - height *= multiplier; - if(video_settings.aspect_correction == true) { - double scalar; - if(mode == SNES::Video::ModeNTSC) { - scalar = (double)config.video.aspect_ntsc_x / (double)config.video.aspect_ntsc_y; - } else { - scalar = (double)config.video.aspect_pal_x / (double)config.video.aspect_pal_y; - } - width = (unsigned)((double)width * (double)scalar); - } - - if(video_settings.mode == 0) { - window_main.unfullscreen(); - window_main.resize(width, height); - } else { - window_main.fullscreen(); - } - - //get maximum possible size for visible area - unsigned viewwidth = window_main.get_width(); - unsigned viewheight = window_main.get_height(); - - //if requested size exceeds visible area, - //constrain proportions and preserve aspect ratio - if(height > viewheight) { - double scalar = (double)viewheight / (double)height; - width = (unsigned)((double)width * (double)scalar); - height = viewheight; - } - - if(width > viewwidth) { - double scalar = (double)viewwidth / (double)width; - width = viewwidth; - height = (unsigned)((double)height * (double)scalar); - } - - //center video output within visible area - window_main.move(window_main.view, (viewwidth - width) / 2, (viewheight - height) / 2); - window_main.view.resize(width, height); - - //update software filter mode - libfilter::FilterInterface::FilterType filter; - switch(video_settings.software_filter) { default: - case 0: filter = libfilter::FilterInterface::Direct; break; - case 1: filter = libfilter::FilterInterface::Scanline; break; - case 2: filter = libfilter::FilterInterface::Scale2x; break; - case 3: filter = libfilter::FilterInterface::HQ2x; break; - case 4: filter = libfilter::FilterInterface::NTSC; break; - } - libfilter::filter.set(filter); - - snes.video.set_mode(mode); - video.set(Video::Synchronize, video_settings.synchronize); - video.set(Video::Filter, video_settings.hardware_filter); - window_main.sync(); //update main window video mode checkbox settings -} - -void update_opacity() { - //convert opacity from 50-100 (percentage) to 128-255 (8-bit alpha) - unsigned opacity = max(50, min(100, config.misc.window_opacity)); - opacity = unsigned(256.0 / 100.0 * opacity); - opacity = max(128, min(255, opacity)); - - window_about.set_opacity(opacity); - window_bsxloader.set_opacity(opacity); - window_cheat_code_editor.set_opacity(opacity); - window_input_capture.set_opacity(opacity); - window_settings.set_opacity(opacity); - window_stloader.set_opacity(opacity); - window_textview.set_opacity(opacity); -} - -void toggle_fullscreen() { - if(config.video.mode != 1) { //switch to fullscreen mode if not already in it - config.video.mode = 1; - } else { //switch to windowed mode if already in fullscreen mode - config.video.mode = 0; - } - update_video_settings(); -} - -void toggle_menubar() { - window_main.menu.show(!window_main.menu.visible()); - update_video_settings(); -} - -void toggle_statusbar() { - window_main.status.show(!window_main.status.visible()); - update_video_settings(); -} - -// - -bool load_cart(char *fn) { - audio.clear(); - - lstring dir; - strcpy(fn, ""); - dir[0] = snes.config.path.rom; - dir[0].replace("\\", "/"); - if(dir[0].length() && !strend(dir[0], "/")) dir[0].append("/"); - - //append base path if rom path is relative - if(strbegin(dir[0], "./")) { - ltrim(dir[0], "./"); - dir[1].assign(dir[0]); - dir[0].assign(snes.config.path.base); - dir[0].append(dir[1]); - } - - return hiro().file_open(0, fn, - dir[0], - "SNES images\t" - "*.sfc,*.smc,*.swc,*.fig,*.bs,*.st" - #if defined(GZIP_SUPPORT) - ",*.gz,*.z,*.zip" - #endif - #if defined(JMA_SUPPORT) - ",*.jma" - #endif - "\n" - "All files\t" - "*" - ); -} - -//used by File -> Load ROM and "Load Cartridge" hotkey -void load_cart() { - char fn[PATH_MAX]; - if(load_cart(fn) == false) return; - load_image(fn); -} - -void load_image(const char *filename) { - switch(cartridge.detect_image_type(filename)) { - case Cartridge::TypeNormal: { - load_cart_normal(filename); - } break; - - case Cartridge::TypeBsxSlotted: { - window_bsxloader.mode = BSXLoaderWindow::ModeBSC; - window_bsxloader.set_text(translate["Load BS-X Slotted Cartridge"]); - window_bsxloader.tbase.set_text(filename); - window_bsxloader.tslot.set_text(""); - window_bsxloader.load.focus(); - window_bsxloader.focus(); - } break; - - case Cartridge::TypeBsxBios: { - window_bsxloader.mode = BSXLoaderWindow::ModeBSX; - window_bsxloader.set_text(translate["Load BS-X Cartridge"]); - window_bsxloader.tbase.set_text(filename); - window_bsxloader.tslot.set_text(""); - window_bsxloader.load.focus(); - window_bsxloader.focus(); - } break; - - case Cartridge::TypeBsx: { - window_bsxloader.mode = BSXLoaderWindow::ModeBSX; - window_bsxloader.set_text(translate["Load BS-X Cartridge"]); - window_bsxloader.tbase.set_text(snes.config.path.bsx); - window_bsxloader.tslot.set_text(filename); - window_bsxloader.load.focus(); - window_bsxloader.focus(); - } break; - - case Cartridge::TypeSufamiTurboBios: { - window_stloader.tbase.set_text(filename); - window_stloader.tslotA.set_text(""); - window_stloader.tslotB.set_text(""); - window_stloader.load.focus(); - window_stloader.focus(); - } break; - - case Cartridge::TypeSufamiTurbo: { - window_stloader.tbase.set_text(snes.config.path.st); - window_stloader.tslotA.set_text(filename); - window_stloader.tslotB.set_text(""); - window_stloader.load.focus(); - window_stloader.focus(); - } break; - } -} - -void load_cart_normal(const char *base) { - if(!base || !*base) return; - - unload_cart(); - cartridge.load_normal(base); - if(cartridge.loaded() == false) return; - modify_system_state(LoadCart); -} - -void load_cart_bsc(const char *base, const char *slot) { - if(!base || !*base) return; - - unload_cart(); - cartridge.load_bsx_slotted(base, slot); - if(cartridge.loaded() == false) return; - modify_system_state(LoadCart); -} - -void load_cart_bsx(const char *base, const char *slot) { - if(!base || !*base) return; - - unload_cart(); - cartridge.load_bsx(base, slot); - if(cartridge.loaded() == false) return; - modify_system_state(LoadCart); -} - -void load_cart_st(const char *base, const char *slotA, const char *slotB) { - if(!base || !*base) return; - - unload_cart(); - cartridge.load_sufami_turbo(base, slotA, slotB); - if(cartridge.loaded() == false) return; - modify_system_state(LoadCart); -} - -void unload_cart() { - if(cartridge.loaded() == false) return; - cartridge.unload(); - modify_system_state(UnloadCart); -} - -void quit() { - app.term = true; - window_main.hide(); - - window_about.hide(); - window_bsxloader.hide(); - window_cheat_code_editor.hide(); - window_input_capture.hide(); - window_settings.hide(); - window_stloader.hide(); - window_textview.hide(); -} - -}; diff --git a/src/ui_hiro/event/event.hpp b/src/ui_hiro/event/event.hpp deleted file mode 100644 index 29c6147d..00000000 --- a/src/ui_hiro/event/event.hpp +++ /dev/null @@ -1,54 +0,0 @@ -namespace event { - -#include "debugger.hpp" - -void input_event(uint16_t); - -void acquire(); -void unacquire(); - -struct VideoSettings { - unsigned mode; - bool synchronize; - bool aspect_correction; - unsigned region; - unsigned multiplier; - unsigned hardware_filter; - unsigned software_filter; -} video_settings; -void load_video_settings(); - -void update_aspect_correction(bool); -void update_multiplier(unsigned); -void update_region(unsigned); -void update_hardware_filter(unsigned); -void update_software_filter(unsigned); - -void update_frameskip(int); -void update_emulation_speed(int); - -enum system_state_t { LoadCart, UnloadCart, PowerOn, PowerOff, PowerCycle, Reset }; -void modify_system_state(system_state_t); - -void update_controller_port1(int); -void update_controller_port2(int); - -void update_video_settings(); -void update_opacity(); - -void toggle_fullscreen(); -void toggle_menubar(); -void toggle_statusbar(); - -bool load_cart(char*); -void load_cart(); -void load_image(const char*); -void load_cart_normal(const char*); -void load_cart_bsc(const char*, const char*); -void load_cart_bsx(const char*, const char*); -void load_cart_st(const char*, const char*, const char*); -void unload_cart(); - -void quit(); - -} //namespace event diff --git a/src/ui_hiro/inputdevices.cpp b/src/ui_hiro/inputdevices.cpp deleted file mode 100644 index 8342f39c..00000000 --- a/src/ui_hiro/inputdevices.cpp +++ /dev/null @@ -1,383 +0,0 @@ -struct InputCode { - enum Type { - KeyboardButton, - MouseAxis, - MouseButton, - JoypadAxis, - JoypadButton, - Unknown, - }; - - static Type type(uint16_t code) { - if(code < keyboard::limit) return KeyboardButton; - if(code >= mouse::x && code <= mouse::z) return MouseAxis; - if(code < mouse::limit) return MouseButton; - for(unsigned i = 0; i < joypad<>::count; i++) { - unsigned index = joypad<>::index(i, joypad<>::axis); - if(code >= index && code < index + joypad<>::axes) return JoypadAxis; - if(code < joypad<>::index(i, joypad<>::limit)) return JoypadButton; - } - return Unknown; - } - - static bool is_button(uint16_t code) { - Type id = type(code); - return (id == KeyboardButton || id == MouseButton || id == JoypadButton); - } - - static bool is_axis(uint16_t code) { - Type id = type(code); - return (id == MouseAxis || id == JoypadAxis); - } -}; - -struct InputObject { - enum Type { Button, Axis } type; - const char *name; - string &setting; - uint16_t code; - int16_t state; - - void bind() { code = input_find((const char*)setting); } - InputObject(Type t, const char *n, string &s) : type(t), name(n), setting(s) {} -}; - -struct InputGroup { - const char *name; - vector list; - - void attach(InputObject &object) { - list[list.size()] = &object; - } - - void bind() { - for(unsigned i = 0; i < list.size(); i++) list[i]->bind(); - } - - void clear() { - for(unsigned i = 0; i < list.size(); i++) { - list[i]->state = 0; - } - } - - void poll(int16_t *table) { - for(unsigned i = 0; i < list.size(); i++) { - if(InputCode::type(list[i]->code) == InputCode::MouseAxis && !input.acquired()) { - //mouse must be acquired (locked to window) to move axes - list[i]->state = 0; - } else if(InputCode::type(list[i]->code) == InputCode::JoypadAxis) { - //joypad axis range = -32768 to +32767, scale to -8 to +7 to roughly match mouse delta - list[i]->state = table[list[i]->code] / 4096; - } else { - list[i]->state = table[list[i]->code]; - } - } - } - - virtual int16_t state(unsigned index) { - if(index < list.size()) return list[index]->state; - return 0; - } - - InputGroup(const char *n) : name(n) {} -}; - -struct InputDevice : InputGroup { - SNES::Input::DeviceID id; - enum Port { Port1, Port2 }; - const bool port; - - InputDevice(SNES::Input::DeviceID i, bool p, const char *n) : InputGroup(n), id(i), port(p) {} -}; - -struct Joypad : InputDevice { - InputObject up, down, left, right; - InputObject a, b, x, y; - InputObject l, r, select, start; - - int16_t state(unsigned index) { - if(config.input.allow_invalid_input == 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( - 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); - } -}; - -struct Mouse : InputDevice { - InputObject x, y; - InputObject left, right; - - int16_t state(unsigned index) { - 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( - 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); - } -}; - -struct SuperScope : InputDevice { - InputObject x, y; - InputObject trigger, cursor, turbo, pause; - - int16_t state(unsigned index) { - 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( - 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); - } -}; - -struct Justifier : InputDevice { - InputObject x, y; - InputObject trigger, start; - - int16_t state(unsigned index) { - 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( - 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); - } -}; - -struct InputDevicePool { - vector list; - - void attach(InputDevice &device) { - list[list.size()] = &device; - } - - void bind() { - for(unsigned i = 0; i < list.size(); i++) list[i]->bind(); - } - - void clear() { - for(unsigned i = 0; i < list.size(); i++) list[i]->clear(); - } - - void poll(int16_t *table) { - for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table); - } - - InputDevice *find(SNES::Input::DeviceID id) { - for(unsigned i = 0; i < list.size(); i++) { - if(list[i]->id == id) return list[i]; - } - return 0; - } - - InputDevicePool(); -} inputpool; - -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.l, config.input.mouse1.r -); - -Mouse mouse2( -SNES::Input::DeviceIDMouse2, InputDevice::Port2, "Mouse", -config.input.mouse2.x, config.input.mouse2.y, config.input.mouse2.l, config.input.mouse2.r -); - -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 -); - -InputDevicePool::InputDevicePool() { - 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); -} diff --git a/src/ui_hiro/inputmanager.cpp b/src/ui_hiro/inputmanager.cpp deleted file mode 100644 index 437d218f..00000000 --- a/src/ui_hiro/inputmanager.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "inputdevices.cpp" -#include "inputui.cpp" - -class InputManager { -public: - void bind(); - void poll(); - void clear(); - void flush(); - - int16_t state(uint16_t code); - int16_t get_status(unsigned deviceid, unsigned id); - - void refresh(); - function on_input; - - InputManager(); - ~InputManager(); - -private: - bool active_state; - int16_t state_table[2][input_limit]; -} input_manager; - -//refresh input state for PC keyboard and joypads -//callback can be bound to on_input -//this should be called roughly every ~20-50ms -//however, this need not be called if no callback is attached -void InputManager::refresh() { - bool last = active_state; - active_state = !active_state; - bool next = active_state; - - input.poll(state_table[next]); - for(unsigned i = 0; i < input_limit; i++) { - //call on_input() whenever button is pressed down; ignores axes - if(!state_table[last][i] - && state_table[next][i] - && InputCode::is_button(i) - && on_input - ) on_input(i); - - //detect any change of state for UI input capture window - if(state_table[last][i] != state_table[next][i] - && window_input_capture.focused() - && window_input_capture.waiting - && !window_input_capture.locked - ) { - //buttons only map upon pressing down; axes map on movement in any direction - if(InputCode::is_button(i) == false || state_table[next][i]) { - window_input_capture.assign(i); - } - } - } - - //input capture locks to avoid immediate assignment of enter / spacebar / etc; - //in other words, inputs that can be used to trigger the input capture window. - //this will release the lock when none of said buttons are active. - if(window_input_capture.focused() - && window_input_capture.waiting - && window_input_capture.locked - ) { - window_input_capture.locked - = input_manager.state(keyboard::return_) - || input_manager.state(keyboard::spacebar) - || input_manager.state(mouse::button + 0); - } -} - -void InputManager::bind() { - inputpool.bind(); - inputuigeneral.bind(); - inputuidebugger.bind(); -} - -void InputManager::poll() { - inputpool.poll(state_table[active_state]); -} - -void InputManager::clear() { - inputpool.clear(); -} - -void InputManager::flush() { - for(unsigned i = 0; i < input_limit; i++) { - state_table[0][i] = 0; - state_table[1][i] = 0; - } -} - -int16_t InputManager::state(uint16_t code) { - return state_table[active_state][code]; -} - -int16_t InputManager::get_status(unsigned deviceid, unsigned id) { - InputDevice *device = inputpool.find((SNES::Input::DeviceID)deviceid); - if(device) return device->state(id); - return 0; -} - -InputManager::InputManager() { - active_state = 0; - flush(); -} - -InputManager::~InputManager() { -} diff --git a/src/ui_hiro/inputui.cpp b/src/ui_hiro/inputui.cpp deleted file mode 100644 index 49c16a1a..00000000 --- a/src/ui_hiro/inputui.cpp +++ /dev/null @@ -1,56 +0,0 @@ -struct InputUIGeneral : InputGroup { - InputObject load; - InputObject pause; - InputObject reset; - InputObject power; - InputObject quit; - InputObject speed_decrease; - InputObject speed_increase; - InputObject frameskip_decrease; - InputObject frameskip_increase; - InputObject toggle_fullscreen; - InputObject toggle_menubar; - InputObject toggle_statusbar; - - InputUIGeneral() - : InputGroup("General"), - load (InputObject::Button, "Load cartridge", config.input.gui.load), - pause (InputObject::Button, "Pause emulation", config.input.gui.pause), - reset (InputObject::Button, "Reset system", config.input.gui.reset), - power (InputObject::Button, "Power cycle system", config.input.gui.power), - quit (InputObject::Button, "Exit emulator", config.input.gui.quit), - speed_decrease (InputObject::Button, "Decrease emulation speed", config.input.gui.speed_decrease), - speed_increase (InputObject::Button, "Increase emulation speed", config.input.gui.speed_increase), - frameskip_decrease(InputObject::Button, "Decrease frameskip rate", config.input.gui.frameskip_decrease), - frameskip_increase(InputObject::Button, "Increase frameskip rate", config.input.gui.frameskip_increase), - toggle_fullscreen (InputObject::Button, "Toggle fullscreen mode", config.input.gui.toggle_fullscreen), - toggle_menubar (InputObject::Button, "Toggle menubar", config.input.gui.toggle_menubar), - toggle_statusbar (InputObject::Button, "Toggle statusbar", config.input.gui.toggle_statusbar) - { - attach(load); attach(pause); attach(reset); attach(power); attach(quit); - attach(speed_decrease); attach(speed_increase); - attach(frameskip_decrease); attach(frameskip_increase); - attach(toggle_fullscreen); attach(toggle_menubar); attach(toggle_statusbar); - } -} inputuigeneral; - -struct InputUIDebug : InputGroup { - InputObject export_memory; - InputObject toggle_cputrace; - InputObject toggle_cputracemask; - InputObject toggle_smptrace; - InputObject toggle_smptracemask; - - InputUIDebug() - : InputGroup("Debugger"), - export_memory (InputObject::Button, "Export memory", config.input.debugger.export_memory), - toggle_cputrace (InputObject::Button, "Toggle S-CPU tracing", config.input.debugger.toggle_cputrace), - toggle_cputracemask(InputObject::Button, "Toggle S-CPU trace mask", config.input.debugger.toggle_cputracemask), - toggle_smptrace (InputObject::Button, "Toggle S-SMP tracing", config.input.debugger.toggle_smptrace), - toggle_smptracemask(InputObject::Button, "Toggle S-SMP trace mask", config.input.debugger.toggle_smptracemask) - { - attach(export_memory); - attach(toggle_cputrace); attach(toggle_cputracemask); - attach(toggle_smptrace); attach(toggle_smptracemask); - } -} inputuidebugger; diff --git a/src/ui_hiro/interface.cpp b/src/ui_hiro/interface.cpp deleted file mode 100644 index 2806494a..00000000 --- a/src/ui_hiro/interface.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/***** - * SNES Interface class - * - * Interfaces SNES core with platform-specific functionality - * (video, audio, input, ...) - *****/ - -SNESInterface snesinterface; - -//video - -static unsigned frameskip_counter = 0; -static unsigned frameskip_offset = 0; - -void SNESInterface::video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height) { - if(ppu.renderer_enabled() == true) { - uint32_t *output; - unsigned opitch; - if(video.lock(output, opitch) == true) { - unsigned owidth, oheight; - libfilter::filter.render(output, opitch, owidth, oheight, data, pitch, line, width, height); - video.unlock(); - video.refresh(owidth, oheight); - } - } - - if(config.video.frameskip == 0) { - ppu.enable_renderer(true); - } else { - frameskip_counter++; - frameskip_counter %= config.video.frameskip + 1; - if(frameskip_counter == 0) { - //randomize which frame of set will be rendered, - //helps with two-frame animations (such as blinking) - frameskip_offset = rand() % (config.video.frameskip + 1); - } - ppu.enable_renderer(frameskip_counter == frameskip_offset); - } -} - -//audio - -void SNESInterface::audio_sample(uint16 l_sample, uint16 r_sample) { - if(config.audio.mute == true) { - l_sample = 0; - r_sample = 0; - } - audio.sample(l_sample, r_sample); -} - -//input - -void SNESInterface::input_poll() { - if(window_main.input_ready() == false) { - input_manager.clear(); - } else { - input_manager.poll(); - } -} - -int16_t SNESInterface::input_poll(unsigned deviceid, unsigned id) { - return input_manager.get_status(deviceid, id); -} - -//core - -void SNESInterface::init() { - input_manager.bind(); - libfilter::colortable.set_format(libfilter::Colortable::RGB888); - libfilter::colortable.set_contrast(config.video.contrast); - libfilter::colortable.set_brightness(config.video.brightness); - libfilter::colortable.set_gamma(config.video.gamma); - libfilter::colortable.enable_gamma_ramp(config.video.gamma_ramp); - libfilter::colortable.enable_sepia(config.video.sepia); - libfilter::colortable.enable_grayscale(config.video.grayscale); - libfilter::colortable.enable_invert(config.video.invert); - libfilter::colortable.update(); - libfilter::filter_ntsc.adjust(0, 0, 0, 0, 0, config.video.ntsc_filter_merge_fields); -} - -void SNESInterface::term() { -} diff --git a/src/ui_hiro/license.hpp b/src/ui_hiro/license.hpp deleted file mode 100644 index 08a0c6db..00000000 --- a/src/ui_hiro/license.hpp +++ /dev/null @@ -1,87 +0,0 @@ -static const char text_license[] = - "bsnes (TM) Reference License\n" - "Copyright (C) 2004 - 2008 byuu\n" - "All rights reserved\n\n" - - "1. Definitions\n\n" - - "The terms 'reproduce', 'reproduction', 'distribute' and 'distribution' have the " - "same meaning here as under U.S. copyright law.\n\n" - - "'The software' means this software package as a whole, including, but not " - "limited to, this license, binaries, source code, documentation, and data.\n\n" - - "'You' means the licensee of the software.\n\n" - - "'The licensor' means the copyright holder of the software, byuu.\n\n" - - "2. Grant of Rights\n\n" - - "Subject to the terms of this license, the licensor grants you a " - "non-transferable, non-exclusive, worldwide, royalty-free copyright license to " - "reproduce the software for non-commercial use only, provided the software " - "remains unmodified, and there is no charge for the software itself, its' use, " - "nor for the medium upon which the software is distributed. The reproduction of " - "modified or derivative works of the software is strictly prohibited, except when " - "transmitted solely to the licensor.\n\n" - - "3. Limitations\n\n" - - "This license does not grant you any rights to use the licensor's name, logo or " - "trademarks.\n\n" - - "The software is provided 'as is', and any express or implied warranties, " - "including, but not limited to, the implied warranties of merchantability and " - "fitness for a particular purpose are disclaimed. In no event shall the licensor " - "be liable for any direct, indirect, incidental, special, exemplary, or " - "consequential damages (including, but not limited to, procurement of substitute " - "goods or services; loss of use, data, or profits; or business interruption) " - "however caused and on any theory of liability, whether in contract, strict " - "liability, or tort (including negligence or otherwise) arising in any way out of " - "the use of the software, even if advised of the possibility of such damage.\n\n" - - "In the event that this license is determined to be invalid or unenforceable, the " - "Grant of Rights will become null and void, and no rights shall be granted to the " - "licensee, within the scope of U.S. copyright law.\n\n" - - "4. Exemptions\n\n" - - "The software includes the work of other copyright holders, which is licensed " - "under different agreements, and exempt from this license. Below is a complete " - "list of all such software, and their respective copyright holders and licenses. " - "Further, respective source code files are labeled with their correct licensing " - "information in the header. The lack of such a header indicates said file falls " - "under the bsnes license.\n\n" - - "HQ2x filter, author: MaxST, license: LGPL\n" - "JMA decompressor, author: NSRT Team, license: GPL*\n" - "NTSC filter, author: blargg, license: LGPL\n" - "zlib decompressor, license: zlib license\n\n" - - "(* bsnes has received an exemption from the copyright holder to use this work.)\n\n" - - "The software also includes works which have been released to the public domain, " - "which are not bound to any licensing agreements. Below is a complete list of all " - "such software.\n\n" - - "libco, author: byuu\n" - "S-DD1 decompressor, author: Andreas Naive\n" - "SPC7110 decompressor, author: neviksti\n\n" - - "Any software listed above as exemptions may be relicensed individually from " - "bsnes under their respective terms. However, no bsnes licensed portions can be " - "combined with such a derivative work.\n\n" - - "The software also includes the work of other copyright holders, which is " - "licensed under the terms of the bsnes license, with permission to do so from the " - "respective authors. Below is a complete list of all such software.\n\n" - - "Cx4 emu, authors: anomie, Overload, zsKnight, Nach\n" - "DSP-1 emu, authors: Overload, John Weidman, Neviksti, Andreas Naive\n" - "DSP-2 emu, author: Overload\n" - "DSP-3 emu, authors: John Weidman, Kris Bleakley, Lancer, z80 gaiden\n" - "DSP-4 emu, authors: Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden\n" - "S-DSP emu, author: blargg\n" - "ST-010 emu, authors: John Weidman, Matthew Kendora, Overload, Feather" - - ""; diff --git a/src/ui_hiro/loader/bsxloader.cpp b/src/ui_hiro/loader/bsxloader.cpp deleted file mode 100644 index e443c84e..00000000 --- a/src/ui_hiro/loader/bsxloader.cpp +++ /dev/null @@ -1,93 +0,0 @@ -uintptr_t BSXLoaderWindow::close(event_t) { - hide(); - return false; -} - -uintptr_t BSXLoaderWindow::bbase_tick(event_t) { - char fn[PATH_MAX]; - if(event::load_cart(fn) == true) tbase.set_text(fn); - return true; -} - -uintptr_t BSXLoaderWindow::cbase_tick(event_t) { - tbase.set_text(""); - return true; -} - -uintptr_t BSXLoaderWindow::bslot_tick(event_t) { - char fn[PATH_MAX]; - if(event::load_cart(fn) == true) tslot.set_text(fn); - return true; -} - -uintptr_t BSXLoaderWindow::cslot_tick(event_t) { - tslot.set_text(""); - return true; -} - -uintptr_t BSXLoaderWindow::load_tick(event_t) { - char base[PATH_MAX], slot[PATH_MAX]; - tbase.get_text(base, PATH_MAX); - tslot.get_text(slot, PATH_MAX); - - if(mode == ModeBSX) { - snes.config.path.bsx = base; - event::load_cart_bsx(base, slot); - } else if(mode == ModeBSC) { - event::load_cart_bsc(base, slot); - } - - tbase.set_text(""); - tslot.set_text(""); - hide(); - return true; -} - -uintptr_t BSXLoaderWindow::cancel_tick(event_t) { - tbase.set_text(""); - tslot.set_text(""); - hide(); - return true; -} - -void BSXLoaderWindow::setup() { - create(Window::AutoCenter, 565, 131, translate["Load BS-X Cartridge"]); - set_icon(48, 48, (uint32_t*)resource::icon48); - - lbase.create(0, 555, 18, translate["Base cartridge:"]); - tbase.create(0, 345, 25); - bbase.create(0, 100, 25, translate["Browse ..."]); - cbase.create(0, 100, 25, translate["Clear"]); - - lslot.create(0, 555, 18, translate["Slot cartridge:"]); - tslot.create(0, 345, 25); - bslot.create(0, 100, 25, translate["Browse ..."]); - cslot.create(0, 100, 25, translate["Clear"]); - - load.create (0, 275, 25, translate["Load"]); - cancel.create(0, 275, 25, translate["Cancel"]); - - unsigned y = 5; - attach(lbase, 5, y); y += 18; - attach(tbase, 5, y); - attach(bbase, 355, y); - attach(cbase, 460, y); y += 25 + 5; - attach(lslot, 5, y); y += 18; - attach(tslot, 5, y); - attach(bslot, 355, y); - attach(cslot, 460, y); y += 25 + 5; - attach(load, 5, y); - attach(cancel, 285, y); y += 25 + 5; - - on_close = bind(&BSXLoaderWindow::close, this); - bbase.on_tick = bind(&BSXLoaderWindow::bbase_tick, this); - cbase.on_tick = bind(&BSXLoaderWindow::cbase_tick, this); - bslot.on_tick = bind(&BSXLoaderWindow::bslot_tick, this); - cslot.on_tick = bind(&BSXLoaderWindow::cslot_tick, this); - load.on_tick = bind(&BSXLoaderWindow::load_tick, this); - cancel.on_tick = bind(&BSXLoaderWindow::cancel_tick, this); -} - -BSXLoaderWindow::BSXLoaderWindow() { - mode = ModeBSX; -} diff --git a/src/ui_hiro/loader/bsxloader.hpp b/src/ui_hiro/loader/bsxloader.hpp deleted file mode 100644 index e6f3207a..00000000 --- a/src/ui_hiro/loader/bsxloader.hpp +++ /dev/null @@ -1,28 +0,0 @@ -class BSXLoaderWindow : public Window { -public: - enum Mode { - ModeBSX, //BS-X cartridge - ModeBSC, //BS-X slotted cartridge - } mode; - - Label lbase; - Editbox tbase; - Button bbase, cbase; - - Label lslot; - Editbox tslot; - Button bslot, cslot; - - Button load, cancel; - - void setup(); - uintptr_t close(event_t); - uintptr_t bbase_tick(event_t); - uintptr_t cbase_tick(event_t); - uintptr_t bslot_tick(event_t); - uintptr_t cslot_tick(event_t); - uintptr_t load_tick(event_t); - uintptr_t cancel_tick(event_t); - - BSXLoaderWindow(); -} window_bsxloader; diff --git a/src/ui_hiro/loader/stloader.cpp b/src/ui_hiro/loader/stloader.cpp deleted file mode 100644 index b48a5f94..00000000 --- a/src/ui_hiro/loader/stloader.cpp +++ /dev/null @@ -1,110 +0,0 @@ -uintptr_t STLoaderWindow::close(event_t) { - hide(); - return false; -} - -uintptr_t STLoaderWindow::bbase_tick(event_t) { - char fn[PATH_MAX]; - if(event::load_cart(fn) == true) tbase.set_text(fn); - return true; -} - -uintptr_t STLoaderWindow::cbase_tick(event_t) { - tbase.set_text(""); - return true; -} - -uintptr_t STLoaderWindow::bslotA_tick(event_t) { - char fn[PATH_MAX]; - if(event::load_cart(fn) == true) tslotA.set_text(fn); - return true; -} - -uintptr_t STLoaderWindow::cslotA_tick(event_t) { - tslotA.set_text(""); - return true; -} - -uintptr_t STLoaderWindow::bslotB_tick(event_t) { - char fn[PATH_MAX]; - if(event::load_cart(fn) == true) tslotB.set_text(fn); - return true; -} - -uintptr_t STLoaderWindow::cslotB_tick(event_t) { - tslotB.set_text(""); - return true; -} - -uintptr_t STLoaderWindow::load_tick(event_t) { - char base[PATH_MAX], slotA[PATH_MAX], slotB[PATH_MAX]; - tbase.get_text(base, PATH_MAX); - tslotA.get_text(slotA, PATH_MAX); - tslotB.get_text(slotB, PATH_MAX); - - snes.config.path.st = base; - event::load_cart_st(base, slotA, slotB); - - tbase.set_text(""); - tslotA.set_text(""); - tslotB.set_text(""); - hide(); - return true; -} - -uintptr_t STLoaderWindow::cancel_tick(event_t) { - tbase.set_text(""); - tslotA.set_text(""); - tslotB.set_text(""); - hide(); - return true; -} - -void STLoaderWindow::setup() { - create(Window::AutoCenter, 565, 179, translate["Load Sufami Turbo Cartridge"]); - set_icon(48, 48, (uint32_t*)resource::icon48); - - lbase.create(0, 555, 18, translate["Base cartridge:"]); - tbase.create(0, 345, 25); - bbase.create(0, 100, 25, translate["Browse ..."]); - cbase.create(0, 100, 25, translate["Clear"]); - - lslotA.create(0, 555, 18, translate["Slot A cartridge:"]); - tslotA.create(0, 345, 25); - bslotA.create(0, 100, 25, translate["Browse ..."]); - cslotA.create(0, 100, 25, translate["Clear"]); - - lslotB.create(0, 555, 18, translate["Slot B cartridge:"]); - tslotB.create(0, 345, 25); - bslotB.create(0, 100, 25, translate["Browse ..."]); - cslotB.create(0, 100, 25, translate["Clear"]); - - load.create (0, 275, 25, translate["Load"]); - cancel.create(0, 275, 25, translate["Cancel"]); - - unsigned y = 5; - attach(lbase, 5, y); y += 18; - attach(tbase, 5, y); - attach(bbase, 355, y); - attach(cbase, 460, y); y += 25 + 5; - attach(lslotA, 5, y); y += 18; - attach(tslotA, 5, y); - attach(bslotA, 355, y); - attach(cslotA, 460, y); y += 25 + 5; - attach(lslotB, 5, y); y += 18; - attach(tslotB, 5, y); - attach(bslotB, 355, y); - attach(cslotB, 460, y); y += 25 + 5; - attach(load, 5, y); - attach(cancel, 285, y); y += 25 + 5; - - on_close = bind(&STLoaderWindow::close, this); - bbase.on_tick = bind(&STLoaderWindow::bbase_tick, this); - cbase.on_tick = bind(&STLoaderWindow::cbase_tick, this); - bslotA.on_tick = bind(&STLoaderWindow::bslotA_tick, this); - cslotA.on_tick = bind(&STLoaderWindow::cslotA_tick, this); - bslotB.on_tick = bind(&STLoaderWindow::bslotB_tick, this); - cslotB.on_tick = bind(&STLoaderWindow::cslotB_tick, this); - load.on_tick = bind(&STLoaderWindow::load_tick, this); - cancel.on_tick = bind(&STLoaderWindow::cancel_tick, this); -} diff --git a/src/ui_hiro/loader/stloader.hpp b/src/ui_hiro/loader/stloader.hpp deleted file mode 100644 index f6499ec3..00000000 --- a/src/ui_hiro/loader/stloader.hpp +++ /dev/null @@ -1,27 +0,0 @@ -class STLoaderWindow : public Window { -public: - Label lbase; - Editbox tbase; - Button bbase, cbase; - - Label lslotA; - Editbox tslotA; - Button bslotA, cslotA; - - Label lslotB; - Editbox tslotB; - Button bslotB, cslotB; - - Button load, cancel; - - void setup(); - uintptr_t close(event_t); - uintptr_t bbase_tick(event_t); - uintptr_t cbase_tick(event_t); - uintptr_t bslotA_tick(event_t); - uintptr_t cslotA_tick(event_t); - uintptr_t bslotB_tick(event_t); - uintptr_t cslotB_tick(event_t); - uintptr_t load_tick(event_t); - uintptr_t cancel_tick(event_t); -} window_stloader; diff --git a/src/ui_hiro/main.cpp b/src/ui_hiro/main.cpp deleted file mode 100644 index 13d5bb76..00000000 --- a/src/ui_hiro/main.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include <../base.hpp> -#include <../cart/cart.hpp> - -#include "main.hpp" -#include "config.cpp" - -#include -using namespace ruby; - -#include -using namespace libhiro; - -#include - -#include "ui.hpp" -#include "status.hpp" -#include "event/event.hpp" - -#include "inputmanager.cpp" -#include "interface.cpp" - -#include "ui.cpp" -#include "status.cpp" -#include "event/event.cpp" - -void get_paths(const char *image) { - char temp[PATH_MAX] = ""; - - if(realpath(image, temp)) { - //remove program name - for(signed i = strlen(temp) - 1; i >= 0; i--) { - if(temp[i] == '/' || temp[i] == '\\') { - temp[i] = 0; - break; - } - } - - if(strend(temp, "/") == false) strcat(temp, "/"); - snes.config.path.base = temp; - } else { - snes.config.path.base = ""; - } - - if(userpath(temp)) { - if(strend(temp, "/") == false) strcat(temp, "/"); - snes.config.path.user = temp; - } else { - snes.config.path.user = ""; - } -} - -void set_config_filenames() { - char filename[PATH_MAX]; - - //locate bsnes.cfg - strcpy(filename, snes.config.path.base); - strcat(filename, "bsnes.cfg"); - if(!file::exists(filename)) { - strcpy(filename, snes.config.path.user); - strcat(filename, ".bsnes"); - mkdir(filename); - strcat(filename, "/bsnes.cfg"); - } - strcpy(config.bsnes_cfg, filename); - - //locate locale.cfg - strcpy(filename, snes.config.path.base); - strcat(filename, "locale.cfg"); - if(!file::exists(filename)) { - strcpy(filename, snes.config.path.user); - strcat(filename, ".bsnes"); - mkdir(filename); - strcat(filename, "/locale.cfg"); - } - strcpy(config.locale_cfg, filename); -} - -void run() { - while(hiro().pending()) hiro().run(); - status.update(); - input_manager.refresh(); - - if(config.input.capture_mode == 2) { - bool inactive = (window_main.focused() == false); - if(app.autopause == false && inactive == true) { - app.autopause = true; - audio.clear(); - } else if(app.autopause == true && inactive == false) { - app.autopause = false; - } - } else { - app.autopause = false; - } - - if(cartridge.loaded() == false || app.pause == true || app.autopause == true) { - usleep(20 * 1000); //prevent bsnes from consuming 100% CPU resources when idle - } else { - snes.runtoframe(); - } -} - -int hiromain(int argc, const char *const argv[]) { - get_paths(argv[0]); - set_config_filenames(); - - config.load(config.bsnes_cfg); - if(file::exists(config.bsnes_cfg) == false) { - //in case program crashes on first run, save config file - //settings, so that they can be modified by hand ... - config.save(config.bsnes_cfg); - } - translate.import(config.locale_cfg); - - ui_init(); - if(app.term == false) { - snes.init(); - if(argc >= 2) event::load_image(argv[1]); - while(app.term == false) run(); - event::unload_cart(); - } - - config.save(config.bsnes_cfg); - snes.term(); - ui_term(); - return 0; -} diff --git a/src/ui_hiro/main.hpp b/src/ui_hiro/main.hpp deleted file mode 100644 index 4400acd6..00000000 --- a/src/ui_hiro/main.hpp +++ /dev/null @@ -1,8 +0,0 @@ -struct Application { - bool term; - bool power; - bool pause; - bool autopause; - - Application() : term(false), power(false), pause(false), autopause(false) {} -} app; diff --git a/src/ui_hiro/readme.hpp b/src/ui_hiro/readme.hpp deleted file mode 100644 index a7a16e64..00000000 --- a/src/ui_hiro/readme.hpp +++ /dev/null @@ -1,80 +0,0 @@ -static const char text_readme[] = - "1. General:\n\n" - - "bsnes is a Super Nintendo / Super Famicom emulator that began development on October 14th, 2004.\n" - "The latest version can be downloaded from: http://byuu.org/\n\n" - - "2. Configuration:\n\n" - - "bsnes has two configuration files: bsnes.cfg, for program settings; and locale.cfg, for localization.\n" - "For each file, bsnes will start by looking inside the same folder where the " - "bsnes executable is located. If said file is not found, it will then check your " - "user profile folder. On Windows, this is located at '%APPDATA%/.bsnes'. On all " - "other operating systems, this is located at '~/.bsnes'. If said file is still " - "not found, it will automatically be created in your user profile folder.\n\n" - - "If you wish to use bsnes in single-user mode, be sure that both files exist " - "inside the same folder as the bsnes executable. If they do not, you can simply " - "create new blank files and bsnes will use them in the future.\n\n" - - "If you wish to use bsnes in multi-user mode, simply delete these two files from " - "the bsnes executable directory if they exist.\n\n" - - "If you wish to have multiple configuration profiles for the same user, you will " - "need to make copies of the bsnes executable, and use each one in single-user " - "mode.\n\n" - - "3. Known Limitations:\n\n" - - "S-CPU\n" - "- Multiply / divide register delays not implemented\n" - "- 'Glitch' when reading joypad registers during auto polling not implemented\n" - - "S-PPU\n" - "- Uses scanline-based renderer. This is very inaccurate, but few (if any) " - "games rely on mid-scanline writes to function correctly\n" - "- Does not support FirstSprite+Y priority\n" - "- OAM / CGRAM accesses during active display not supported correctly\n" - "- RTO flags are not calculated on frames that are skipped when frameskipping " - "is enabled. This provides a major speedup, however it will cause in issues " - "in games that test these flags, eg the SNES Test Program Electronics Test. " - "Turning frameskipping off will allow RTO flag calculation on every frame\n\n" - - "Hardware Bugs\n" - "- S-CPU.r1 HDMA crashing bug not emulated\n" - "- S-CPU<>S-SMP communication bus conflicts not emulated\n\n" - - "4. Unsupported Hardware:\n\n" - - "SA-1\n" - "Coprocessor used in many popular games, including:\n" - "- Dragon Ball Z Hyper Dimension\n" - "- Kirby Super Star\n" - "- Kirby's Dreamland 3\n" - "- Marvelous\n" - "- SD Gundam G-NEXT\n" - "- Super Mario RPG\n\n" - - "Super FX\n" - "Coprocessor used in many popular games, including:\n" - "- Doom\n" - "- Star Fox\n" - "- Star Fox 2 (unreleased beta)\n" - "- Super Mario World 2: Yoshi's Island\n\n" - - "ST-011\n" - "SETA DSP used by Quick-move Shogi Match with Nidan Rank-holder Morita\n\n" - - "ST-018\n" - "SETA RISC CPU used by Quick-move Shogi Match with Nidan Rank-holder Morita 2\n\n" - - "Super Gameboy\n" - "Cartridge passthrough used for playing Gameboy games\n\n" - - "5. Contributors:\n\n" - - "Andreas Naive, anomie, blargg, DMV27, FitzRoy, GIGO, Jonas Quinn, kode54, krom, " - "Matthew Callis, Nach, neviksti, Overload, RedDwarf, Richard Bannister, " - "tetsuo55, TRAC, zones" - - ""; diff --git a/src/ui_hiro/resource.cpp b/src/ui_hiro/resource.cpp deleted file mode 100644 index 512215a4..00000000 --- a/src/ui_hiro/resource.cpp +++ /dev/null @@ -1,12 +0,0 @@ -namespace resource { - -static uint8_t *icon48; -static uint8_t *controller; - -void init() { - //note: resources were removed, as hiro port is deprecated - icon48 = new(zeromemory) uint8_t[48 * 48 * 4]; - controller = new(zeromemory) uint8_t[372 * 178 * 4]; -} - -} //namespace resource diff --git a/src/ui_hiro/settings/advanced.cpp b/src/ui_hiro/settings/advanced.cpp deleted file mode 100644 index 3c4d56d9..00000000 --- a/src/ui_hiro/settings/advanced.cpp +++ /dev/null @@ -1,104 +0,0 @@ -uintptr_t AdvancedWindow::list_activate(event_t) { - int item = list.get_selection(); - if(item >= 0) { - //if item is integral_setting::boolean, toggle its state - if(config.list[lookup[item]].type == configuration::boolean_t) { - *(bool*)config.list[lookup[item]].data = *(bool*)config.list[lookup[item]].data ? false : true; - update(item); - } - } - return true; -} - -uintptr_t AdvancedWindow::list_change(event_t) { - int item = list.get_selection(); - edit.enable(item >= 0); - set.enable (item >= 0); - edit.set_text(item >= 0 ? config.list[lookup[item]].get() : translate[""]); - return true; -} - -uintptr_t AdvancedWindow::set_tick(event_t) { - int item = list.get_selection(); - if(item >= 0) { - char value[4096]; - edit.get_text(value, sizeof value); - config.list[lookup[item]].set(value); - update(item); - } - return true; -} - -void AdvancedWindow::update(unsigned item) { - edit.set_text(config.list[lookup[item]].get()); - list.set_item(item, string() - << config.list[lookup[item]].name << "\t" - << config.list[lookup[item]].get() << "\t" - << config.list[lookup[item]].desc - ); - list.autosize_columns(); -} - -void AdvancedWindow::load() { - lookup.reset(); - - for(unsigned i = 0; i < config.list.size(); i++) { - string name = config.list[i].name; - - //blacklist (omit/hide options that can be configured through the standard UI) - if(name == "snes.expansion_port") continue; - if(name == "snes.region") continue; - if(strbegin(name, "system.")) continue; - if(strbegin(name, "path.")) continue; - if(strbegin(name, "snes.controller_port")) continue; - if(name == "system.emulation_speed") continue; - if(strbegin(name, "video.windowed.")) continue; - if(strbegin(name, "video.fullscreen.")) continue; - if(name == "video.synchronize") continue; - if(name == "video.contrast") continue; - if(name == "video.brightness") continue; - if(name == "video.gamma") continue; - if(name == "video.gamma_ramp") continue; - if(name == "video.ntsc_filter_merge_fields") continue; - if(strbegin(name, "audio.")) continue; - if(name == "input.capture_mode") continue; - if(strbegin(name, "input.joypad")) continue; - if(strbegin(name, "input.multitap")) continue; - if(strbegin(name, "input.mouse")) continue; - if(strbegin(name, "input.superscope")) continue; - if(strbegin(name, "input.justifier")) continue; - if(strbegin(name, "input.gui")) continue; - if(strbegin(name, "input.debugger")) continue; - - list.add_item(string() - << name << "\t" - << config.list[i].get() << "\t" - << config.list[i].desc - ); - lookup.add(i); - } -} - -void AdvancedWindow::setup() { - create(0, 451, 370); - - list.create(Listbox::Header | Listbox::VerticalScrollAlways, 451, 340, - string() << translate["Name"] << "\t" << translate["Value"] << "\t" << translate["Description"]); - edit.create(0, 346, 25, translate[""]); - set.create (0, 100, 25, translate["{{advanced}}Set"]); - - unsigned y = 0; - attach(list, 0, y); y += 340 + 5; - attach(edit, 0, y); - attach(set, 351, y); - - load(); - list.autosize_columns(); - - edit.disable(); - set.disable(); - - list.on_activate = bind(&AdvancedWindow::list_activate, this); - list.on_change = bind(&AdvancedWindow::list_change, this); - set.on_tick = bind(&AdvancedWindow::set_tick, this); -} diff --git a/src/ui_hiro/settings/advanced.hpp b/src/ui_hiro/settings/advanced.hpp deleted file mode 100644 index 10cb04b5..00000000 --- a/src/ui_hiro/settings/advanced.hpp +++ /dev/null @@ -1,15 +0,0 @@ -class AdvancedWindow : public Window { -public: - Listbox list; - Editbox edit; - Button set; - - array lookup; - void update(unsigned item); - void load(); - void setup(); - - uintptr_t list_activate(event_t); - uintptr_t list_change(event_t); - uintptr_t set_tick(event_t); -} window_advanced; diff --git a/src/ui_hiro/settings/audiosettings.cpp b/src/ui_hiro/settings/audiosettings.cpp deleted file mode 100644 index e01f9c76..00000000 --- a/src/ui_hiro/settings/audiosettings.cpp +++ /dev/null @@ -1,124 +0,0 @@ -uintptr_t AudioSettingsWindow::volume_change(event_t) { - config.audio.volume = 25 + cvolume.get_selection() * 25; - audio.set(Audio::Volume, config.audio.volume); - - sync_ui(); - return true; -} - -uintptr_t AudioSettingsWindow::latency_change(event_t) { - config.audio.latency = 20 + clatency.get_selection() * 20; - audio.set(Audio::Latency, config.audio.latency); - - sync_ui(); - return true; -} - -uintptr_t AudioSettingsWindow::frequency_change(event_t) { - switch(cfrequency.get_selection()) { - case 0: config.audio.output_frequency = 32000; break; - case 1: config.audio.output_frequency = 44100; break; default: - case 2: config.audio.output_frequency = 48000; break; - case 3: config.audio.output_frequency = 96000; break; - } - - audio.set(Audio::Frequency, config.audio.output_frequency); - event::update_emulation_speed(config.system.emulation_speed); - - sync_ui(); - return true; -} - -uintptr_t AudioSettingsWindow::skew_change(event_t) { - config.audio.input_frequency = sskew.get_position() + 32000 - 200; - event::update_emulation_speed(config.system.emulation_speed); - - sync_ui(); - return true; -} - -void AudioSettingsWindow::sync_ui() { - cvolume.set_selection((config.audio.volume - 25) / 25); - - unsigned position; - if(config.audio.output_frequency <= 32000) position = 0; - else if(config.audio.output_frequency <= 44100) position = 1; - else if(config.audio.output_frequency <= 48000) position = 2; - else position = 3; - cfrequency.set_selection(position); - - clatency.set_selection((config.audio.latency - 20) / 20); - - lskew.set_text(string() << translate["{{audio}}Frequency adjust:"] << " " << (int)config.audio.input_frequency << "hz"); - sskew.set_position(config.audio.input_frequency - 32000 + 200); -} - -void AudioSettingsWindow::setup() { - create(0, 451, 370); - - lvolume.create(0, 147, 18, translate["{{audio}}Volume:"]); - cvolume.create(0, 147, 25); - cvolume.add_item( "25%"); - cvolume.add_item( "50%"); - cvolume.add_item( "75%"); - cvolume.add_item("100%"); - if(config.misc.show_advanced_options == true) { - cvolume.add_item("125%"); - cvolume.add_item("150%"); - cvolume.add_item("175%"); - cvolume.add_item("200%"); - } - - lfrequency.create(0, 147, 18, translate["{{audio}}Frequency:"]); - cfrequency.create(0, 147, 25); - cfrequency.add_item("32Khz"); - cfrequency.add_item("44.1Khz"); - cfrequency.add_item("48Khz"); - if(config.misc.show_advanced_options == true) { - cfrequency.add_item("96Khz"); - } - - llatency.create(0, 147, 18, translate["{{audio}}Latency:"]); - clatency.create(0, 147, 25); - clatency.add_item( "20ms"); - clatency.add_item( "40ms"); - clatency.add_item( "60ms"); - clatency.add_item( "80ms"); - clatency.add_item("100ms"); - clatency.add_item("120ms"); - if(config.misc.show_advanced_options == true) { - clatency.add_item("140ms"); - clatency.add_item("160ms"); - } - - lskew.create(0, 451, 18, translate["{{audio}}Frequency adjust:"]); - sskew.create(0, 451, 30, 401); - - note.create(0, 451, 54, string() - << translate["{{audio}}Frequency adjust is used to improve video sync timing."] << "\n" - << translate["{{audio}}Lower value to clean audio output."] << "\n" - << translate["{{audio}}Raise value to smooth video output."] - ); - - unsigned y = 0; - - attach(lvolume, 0, y); - attach(lfrequency, 152, y); - attach(llatency, 304, y); y += 18; - - attach(cvolume, 0, y); - attach(cfrequency, 152, y); - attach(clatency, 304, y); y += 30; - - attach(lskew, 0, y); y += 18; - attach(sskew, 0, y); y += 30; - - attach(note, 0, y); - - cvolume.on_change = bind(&AudioSettingsWindow::volume_change, this); - cfrequency.on_change = bind(&AudioSettingsWindow::frequency_change, this); - clatency.on_change = bind(&AudioSettingsWindow::latency_change, this); - sskew.on_change = bind(&AudioSettingsWindow::skew_change, this); - - sync_ui(); -} diff --git a/src/ui_hiro/settings/audiosettings.hpp b/src/ui_hiro/settings/audiosettings.hpp deleted file mode 100644 index b0220fbf..00000000 --- a/src/ui_hiro/settings/audiosettings.hpp +++ /dev/null @@ -1,20 +0,0 @@ -class AudioSettingsWindow : public Window { -public: - Label lvolume; - Combobox cvolume; - Label lfrequency; - Combobox cfrequency; - Label llatency; - Combobox clatency; - Label lskew; - Slider sskew; - Label note; - - uintptr_t volume_change(event_t); - uintptr_t latency_change(event_t); - uintptr_t frequency_change(event_t); - uintptr_t skew_change(event_t); - - void sync_ui(); - void setup(); -} window_audio_settings; diff --git a/src/ui_hiro/settings/cheateditor.cpp b/src/ui_hiro/settings/cheateditor.cpp deleted file mode 100644 index c7c50591..00000000 --- a/src/ui_hiro/settings/cheateditor.cpp +++ /dev/null @@ -1,225 +0,0 @@ -//================= -//CheatEditorWindow -//================= - -void CheatEditorWindow::setup() { - create(0, 451, 370); - - list.create(Listbox::Header | Listbox::VerticalScrollAlways, 451, 340, - string() << translate["Status"] << "\t" << translate["Code"] << "\t" << translate["Description"]); - add_code.create (0, 147, 25, translate["Add Code"]); - edit_code.create (0, 147, 25, translate["Edit Code"]); - delete_code.create(0, 147, 25, translate["Delete Code"]); - - unsigned y = 0; - attach(list, 0, y); y += 340 + 5; - attach(add_code, 0, y); - attach(edit_code, 152, y); - attach(delete_code, 304, y); y += 25 + 5; - - list.on_activate = bind(&CheatEditorWindow::toggle_code_state, this); - list.on_change = bind(&CheatEditorWindow::list_change, this); - add_code.on_tick = bind(&CheatEditorWindow::add_tick, this); - edit_code.on_tick = bind(&CheatEditorWindow::edit_tick, this); - delete_code.on_tick = bind(&CheatEditorWindow::delete_tick, this); - - sync_ui(); - window_cheat_code_editor.setup(); -} - -void CheatEditorWindow::sync_ui() { - add_code.enable(cartridge.loaded()); - edit_code.enable(cartridge.loaded() && list.get_selection() >= 0); - delete_code.enable(cartridge.loaded() && list.get_selection() >= 0); -} - -string CheatEditorWindow::read_code(unsigned index) { - string s; - - Cheat::cheat_t item; - cheat.get(index, item); - s << (item.enabled ? translate["Enabled"] : translate["Disabled"]) << "\t"; - - lstring line; - line.split("+", item.code); - if(line.size() > 1) line[0] << "+..."; - s << line[0] << "\t"; - - line.split("\n", item.desc); - if(line.size() > 1) line[0] << " ..."; - s << line[0]; - - return s; -} - -void CheatEditorWindow::refresh() { - list.reset(); - for(unsigned i = 0; i < cheat.count(); i++) list.add_item(read_code(i)); - list.autosize_columns(); - - sync_ui(); -} - -uintptr_t CheatEditorWindow::toggle_code_state(event_t) { - int index = list.get_selection(); - if(index >= 0 && index < cheat.count()) { - cheat.enabled(index) ? cheat.disable(index) : cheat.enable(index); - list.set_item(index, read_code(index)); - } - return true; -} - -//enables "Edit Code" / "Delete Code" buttons when a code is selected -uintptr_t CheatEditorWindow::list_change(event_t) { - int index = list.get_selection(); - edit_code.enable(index >= 0); - delete_code.enable(index >= 0); - return true; -} - -uintptr_t CheatEditorWindow::add_tick(event_t) { - add_code.disable(); - edit_code.disable(); - delete_code.disable(); - window_cheat_code_editor.show(false); - return true; -} - -uintptr_t CheatEditorWindow::edit_tick(event_t) { - add_code.disable(); - edit_code.disable(); - delete_code.disable(); - window_cheat_code_editor.show(true, list.get_selection()); - return true; -} - -uintptr_t CheatEditorWindow::delete_tick(event_t) { - int index = list.get_selection(); - if(index >= 0 && index < cheat.count()) { - cheat.remove(index); - refresh(); - } - return true; -} - -//===================== -//CheatCodeEditorWindow -//===================== - -uintptr_t CheatCodeEditorWindow::close(event_t) { - hide(); - window_cheat_editor.sync_ui(); - return false; -} - -uintptr_t CheatCodeEditorWindow::validate(event_t) { - char s_codes[1024]; - codes.get_text(s_codes, sizeof s_codes); - - string s_code = s_codes; - strtr(s_code, " ,;&|\t\n", "+++++++"); - while(strpos(s_code, "++") >= 0) s_code.replace("++", "+"); - trim(s_code, "+"); - - Cheat::cheat_t item; - bool valid = cheat.decode(s_code, item); - - lvalid.set_text(valid ? "" : translate["Cheat code is invalid."]); - ok.enable(valid); - return true; -} - -uintptr_t CheatCodeEditorWindow::ok_tick(event_t) { - char s_desc[1024], s_codes[1024]; - description.get_text(s_desc, sizeof s_desc); - codes.get_text(s_codes, sizeof s_codes); - - string s_code = s_codes; - strtr(s_code, " ,;&|\t\n", "+++++++"); - while(strpos(s_code, "++") >= 0) s_code.replace("++", "+"); - trim(s_code, "+"); - - if(active_mode == false) { - //add a new code - cheat.add(enabled.checked(), s_code, s_desc); - } else { - //modify an existing code - cheat.edit(active_code, enabled.checked(), s_code, s_desc); - } - - hide(); - window_cheat_editor.refresh(); - return true; -} - -uintptr_t CheatCodeEditorWindow::cancel_tick(event_t) { - hide(); - window_cheat_editor.sync_ui(); - return true; -} - -uintptr_t CheatCodeEditorWindow::clear_tick(event_t) { - description.set_text(""); - codes.set_text(""); - enabled.check(false); - return true; -} - -void CheatCodeEditorWindow::show(bool editmode, unsigned codenumber) { - active_mode = editmode; - active_code = codenumber; - - if(active_mode == false) { - set_text(translate["Add new cheat code"]); - description.set_text(""); - codes.set_text(""); - enabled.check(false); - } else { - Cheat::cheat_t item; - cheat.get(active_code, item); - - set_text(translate["Modify existing cheat code"]); - description.set_text(item.desc); - string s = item.code; - s.replace("+", " + "); - codes.set_text(s); - enabled.check(item.enabled); - } - - enabled.focus(); - validate(event_t(event_t::Change)); - Window::show(); -} - -void CheatCodeEditorWindow::setup() { - create(Window::AutoCenter, 395, 235); - set_icon(48, 48, (uint32_t*)resource::icon48); - - ldescription.create(0, 385, 18, translate["Description:"]); - description.create(Editbox::Multiline | Editbox::HorizontalScrollNever, 385, 65); - lcodes.create(0, 385, 18, translate["Enter one or more cheat codes below:"]); - codes.create(Editbox::Multiline | Editbox::HorizontalScrollNever, 385, 65); - enabled.create(0, 190, 18, translate["Enable this cheat code"]); - lvalid.create(0, 190, 18); - ok.create(0, 125, 25, translate["Ok"]); - cancel.create(0, 125, 25, translate["Cancel"]); - clear.create(0, 125, 25, translate["Clear"]); - - unsigned y = 5; - attach(ldescription, 5, y); y += 18; - attach(description, 5, y); y += 65 + 5; - attach(lcodes, 5, y); y += 18; - attach(codes, 5, y); y += 65 + 5; - attach(enabled, 5, y); - attach(lvalid, 200, y); y += 18 + 5; - attach(ok, 5, y); - attach(cancel, 135, y); - attach(clear, 265, y); y += 25 + 5; - lvalid.disable(); - - on_close = bind(&CheatCodeEditorWindow::close, this); - codes.on_change = bind(&CheatCodeEditorWindow::validate, this); - ok.on_tick = bind(&CheatCodeEditorWindow::ok_tick, this); - cancel.on_tick = bind(&CheatCodeEditorWindow::cancel_tick, this); - clear.on_tick = bind(&CheatCodeEditorWindow::clear_tick, this); -} diff --git a/src/ui_hiro/settings/cheateditor.hpp b/src/ui_hiro/settings/cheateditor.hpp deleted file mode 100644 index c94e33c5..00000000 --- a/src/ui_hiro/settings/cheateditor.hpp +++ /dev/null @@ -1,46 +0,0 @@ -//main editor window for all codes -class CheatEditorWindow : public Window { -public: - Listbox list; - Button add_code; - Button edit_code; - Button delete_code; - - void sync_ui(); - void setup(); - - string read_code(unsigned index); - void refresh(); - - uintptr_t toggle_code_state(event_t); - uintptr_t list_change(event_t); - uintptr_t add_tick(event_t); - uintptr_t edit_tick(event_t); - uintptr_t delete_tick(event_t); -} window_cheat_editor; - -//individual cheat code editor -class CheatCodeEditorWindow : public Window { -public: - Label ldescription; - Editbox description; - Label lcodes; - Editbox codes; - Checkbox enabled; - Label lvalid; - Button ok; - Button cancel; - Button clear; - - bool active_mode; - unsigned active_code; - - void show(bool editmode, unsigned codenumber = 0); - void setup(); - - uintptr_t close(event_t); - uintptr_t validate(event_t); - uintptr_t ok_tick(event_t); - uintptr_t cancel_tick(event_t); - uintptr_t clear_tick(event_t); -} window_cheat_code_editor; diff --git a/src/ui_hiro/settings/driverselect.cpp b/src/ui_hiro/settings/driverselect.cpp deleted file mode 100644 index 5f8aeb31..00000000 --- a/src/ui_hiro/settings/driverselect.cpp +++ /dev/null @@ -1,148 +0,0 @@ -uintptr_t DriverSelectWindow::video_change(event_t) { - lstring part; - part.split(";", video.driver_list()); - config.system.video = part[cvideo.get_selection()]; - return true; -} - -uintptr_t DriverSelectWindow::audio_change(event_t) { - lstring part; - part.split(";", audio.driver_list()); - config.system.audio = part[caudio.get_selection()]; - return true; -} - -uintptr_t DriverSelectWindow::input_change(event_t) { - lstring part; - part.split(";", input.driver_list()); - config.system.input = part[cinput.get_selection()]; - return true; -} - -void DriverSelectWindow::setup() { - create(0, 451, 370); - - //this is only displayed if application crashed on last run - crash_message.create(0, 451, 36, string() - << translate["Warning: bsnes crashed on last startup due to incompatible driver settings."] << "\n" - << translate["Please select a different driver configuration below."] - ); - - lstring part; - - lvideo.create(0, 147, 18, translate["Video driver:"]); - cvideo.create(0, 147, 25); - - part.split(";", video.driver_list()); - for(unsigned i = 0; i < part.size(); i++) { - cvideo.add_item(translate[string() << "{{videodriver}}" << part[i]]); - if(part[i] == config.system.video) cvideo.set_selection(i); - } - - laudio.create(0, 147, 18, translate["Audio driver:"]); - caudio.create(0, 147, 25); - - part.split(";", audio.driver_list()); - for(unsigned i = 0; i < part.size(); i++) { - caudio.add_item(translate[string() << "{{audiodriver}}" << part[i]]); - if(part[i] == config.system.audio) caudio.set_selection(i); - } - - linput.create(0, 147, 18, translate["Input driver:"]); - cinput.create(0, 147, 25); - - part.split(";", input.driver_list()); - for(unsigned i = 0; i < part.size(); i++) { - cinput.add_item(translate[string() << "{{inputdriver}}" << part[i]]); - if(part[i] == config.system.input) cinput.set_selection(i); - } - - video_caps.create(0, 451, 18); - - video_sync.create(0, 147, 18, translate["{{video}}Synchronize"]); - video_sync.disable(); - video_filter.create(0, 147, 18, translate["Hardware filtering"]); - video_filter.disable(); - - audio_caps.create(0, 451, 18); - - audio_sync.create(0, 147, 18, translate["{{audio}}Synchronize"]); - audio_sync.disable(); - audio_freq.create(0, 147, 18, translate["Frequency control"]); - audio_freq.disable(); - audio_latency.create(0, 147, 18, translate["Latency control"]); - audio_latency.disable(); - - input_caps.create(0, 451, 18); - - input_keyboard.create(0, 147, 18, translate["Keyboard support"]); - input_keyboard.disable(); - input_mouse.create(0, 147, 18, translate["Mouse support"]); - input_mouse.disable(); - input_joypad.create(0, 147, 18, translate["Joypad support"]); - input_joypad.disable(); - - restart_message.create(0, 451, 36, - translate["Note: bsnes must be restarted for changes to take effect."]); - - bool crashed = config.system.invoke_crash_handler; - - string t = translate["Capabilities of active video driver ($):"]; - t.replace("$", config.system.video); - video_caps.set_text(t); - - video_sync.check(video.cap(Video::Synchronize)); - video_filter.check(video.cap(Video::Filter)); - - t = translate["Capabilities of active audio driver ($):"]; - t.replace("$", config.system.audio); - audio_caps.set_text(t); - - audio_sync.check(audio.cap(Audio::Synchronize)); - audio_freq.check(audio.cap(Audio::Frequency)); - audio_latency.check(audio.cap(Audio::Latency)); - - t = translate["Capabilities of active input driver ($):"]; - t.replace("$", config.system.input); - input_caps.set_text(t); - - input_keyboard.check(input.cap(Input::KeyboardSupport)); - input_mouse.check(input.cap(Input::MouseSupport)); - input_joypad.check(input.cap(Input::JoypadSupport)); - - unsigned y = 0; - - if(crashed == true) { - attach(crash_message, 0, y); y += 36 + 5; - } - - attach(lvideo, 0, y); - attach(laudio, 152, y); - attach(linput, 304, y); y += 18; - - attach(cvideo, 0, y); - attach(caudio, 152, y); - attach(cinput, 304, y); y += 25 + 5; - - if(crashed == false) { - attach(video_caps, 0, y); y += 18; - attach(video_sync, 0, y); - attach(video_filter, 152, y); y += 18 + 5; - - attach(audio_caps, 0, y); y += 18; - attach(audio_sync, 0, y); - attach(audio_freq, 152, y); - attach(audio_latency, 304, y); y += 18 + 5; - - attach(input_caps, 0, y); y += 18; - attach(input_keyboard, 0, y); - attach(input_mouse, 152, y); - attach(input_joypad, 304, y); y += 18 + 5; - - attach(restart_message, 0, y); y += 36 + 5; - } - - cvideo.on_change = bind(&DriverSelectWindow::video_change, this); - caudio.on_change = bind(&DriverSelectWindow::audio_change, this); - cinput.on_change = bind(&DriverSelectWindow::input_change, this); -} diff --git a/src/ui_hiro/settings/driverselect.hpp b/src/ui_hiro/settings/driverselect.hpp deleted file mode 100644 index a16d2105..00000000 --- a/src/ui_hiro/settings/driverselect.hpp +++ /dev/null @@ -1,33 +0,0 @@ -class DriverSelectWindow : public Window { -public: - Label crash_message; - - Label lvideo; - Combobox cvideo; - Label laudio; - Combobox caudio; - Label linput; - Combobox cinput; - - Label video_caps; - Checkbox video_sync; - Checkbox video_filter; - - Label audio_caps; - Checkbox audio_sync; - Checkbox audio_freq; - Checkbox audio_latency; - - Label input_caps; - Checkbox input_keyboard; - Checkbox input_mouse; - Checkbox input_joypad; - - Label restart_message; - - uintptr_t video_change(event_t); - uintptr_t audio_change(event_t); - uintptr_t input_change(event_t); - - void setup(); -} window_driver_select; diff --git a/src/ui_hiro/settings/inputconfig.cpp b/src/ui_hiro/settings/inputconfig.cpp deleted file mode 100644 index cc38e4a3..00000000 --- a/src/ui_hiro/settings/inputconfig.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* InputConfigWindow */ - -void InputConfigWindow::setup() { - create(0, 451, 370); - - capture_mode.create(0, 451, 18, translate["{{input}}When emulation window does not have focus:"]); - RadioboxGroup group; - group.add(&capture_always); - group.add(&capture_focus); - group.add(&capture_pause); - capture_always.create(group, 0, 147, 18, translate["{{input}}Allow input"]); - capture_focus.create (group, 0, 147, 18, translate["{{input}}Ignore input"]); - capture_pause.create (group, 0, 147, 18, translate["{{input}}Pause emulation"]); - - config_type.create(0, 223, 25); - config_type.add_item(translate["{{input}}Controller Port 1"]); - config_type.add_item(translate["{{input}}Controller Port 2"]); - config_type.add_item(translate["{{input}}User Interface"]); - config_type.set_selection(0); - - config_subtype.create(0, 223, 25); - refresh_subtype(); - - list.create(Listbox::Header | Listbox::VerticalScrollAlways, 451, 269, - string() << translate["{{input}}Name"] << "\t" << translate["{{input}}Value"]); - setkey.create(0, 223, 25, string() << translate["{{input}}Assign Key"] << " ..."); - setkey.disable(); - clrkey.create(0, 223, 25, translate["{{input}}Unassign Key"]); - clrkey.disable(); - - unsigned y = 0; - attach(capture_mode, 0, y); y += 18; - attach(capture_always, 0, y); - attach(capture_focus, 152, y); - attach(capture_pause, 304, y); y += 18 + 5; - attach(config_type, 0, y); - attach(config_subtype, 228, y); y += 25 + 5; - attach(list, 0, y); y += 269 + 5; - attach(setkey, 0, y); - attach(clrkey, 228, y); y += 25 + 5; - - capture_always.on_tick = bind(&InputConfigWindow::capture_change, this); - capture_focus.on_tick = bind(&InputConfigWindow::capture_change, this); - capture_pause.on_tick = bind(&InputConfigWindow::capture_change, this); - config_type.on_change = bind(&InputConfigWindow::type_change, this); - config_subtype.on_change = bind(&InputConfigWindow::subtype_change, this); - list.on_change = bind(&InputConfigWindow::list_change, this); - list.on_activate = bind(&InputConfigWindow::set_tick, this); - setkey.on_tick = bind(&InputConfigWindow::set_tick, this); - clrkey.on_tick = bind(&InputConfigWindow::clr_tick, this); - - if(config.input.capture_mode == 1) capture_focus.check(); - else if(config.input.capture_mode == 2) capture_pause.check(); - else config.input.capture_mode = 0; //capture_always - - refresh_list(); - window_input_capture.setup(); -} - -InputGroup* InputConfigWindow::get_group() { - unsigned port = config_type.get_selection(); - unsigned index = config_subtype.get_selection(); - - if(port == 0 || port == 1) { - //SNES controller - InputDevice *device = 0; - for(unsigned i = 0; i < inputpool.list.size(); i++) { - if(inputpool.list[i]->port == port) { - if(index-- == 0) { - device = inputpool.list[i]; - break; - } - } - } - return device; - } else { - //user interface - switch(index) { default: - case 0: return &inputuigeneral; - case 1: return &inputuidebugger; - } - } -} - -bool InputConfigWindow::assign(uint16_t code) { - InputGroup *group = get_group(); - if(!group) return false; - - int pos = list.get_selection(); - if(pos < 0 || pos >= group->list.size()) return false; - - //make sure boolean buttons map to boolean input; axes to mouse / joypad axes - switch(group->list[pos]->type) { - case InputObject::Button: { - if(InputCode::is_button(code) == false) return false; - } break; - - case InputObject::Axis: { - if(InputCode::is_axis(code) == false) return false; - int16_t state = input_manager.state(code); - //add a bit of resistance to prevent infinitesimally small movements from triggering assignment - if(InputCode::type(code) == InputCode::MouseAxis && abs(state) < 8) return false; - //joypad axis range = -32768 to +32767 - //some joypads have pressure-sensitive buttons that read +32767 when depressed ... - //therefore, range test between 25% and 75% pressure before triggering assignment - if(InputCode::type(code) == InputCode::JoypadAxis && (abs(state) < 8192 || abs(state) > 24576)) return false; - } break; - } - - group->list[pos]->setting = input_find(code); - input_manager.bind(); - return true; -} - -void InputConfigWindow::refresh_subtype() { - config_subtype.reset(); - unsigned port = config_type.get_selection(); - - if(port == 0 || port == 1) { - //SNES controller - for(unsigned device = 0; device < inputpool.list.size(); device++) { - if(inputpool.list[device]->port == port) { - config_subtype.add_item(translate[inputpool.list[device]->name]); - } - } - } else { - //user interface - config_subtype.add_item(translate[inputuigeneral.name]); - config_subtype.add_item(translate[inputuidebugger.name]); - } - - config_subtype.set_selection(0); -} - -void InputConfigWindow::refresh_list() { - setkey.disable(); - clrkey.disable(); - list.reset(); - InputGroup *group = get_group(); - if(!group) return; - - for(unsigned i = 0; i < group->list.size(); i++) { - list.add_item(string() - << translate[group->list[i]->name] - << "\t" - << group->list[i]->setting); - } - - list.autosize_columns(); -} - -uintptr_t InputConfigWindow::capture_change(event_t e) { - if(e.widget == &capture_always) config.input.capture_mode = 0; - if(e.widget == &capture_focus) config.input.capture_mode = 1; - if(e.widget == &capture_pause) config.input.capture_mode = 2; - return true; -} - -uintptr_t InputConfigWindow::type_change(event_t) { - refresh_subtype(); - refresh_list(); - return true; -} - -uintptr_t InputConfigWindow::subtype_change(event_t) { - refresh_list(); - return true; -} - -uintptr_t InputConfigWindow::list_change(event_t) { - int pos = list.get_selection(); - setkey.enable(pos >= 0); - clrkey.enable(pos >= 0); - return true; -} - -uintptr_t InputConfigWindow::set_tick(event_t) { - InputGroup *group = get_group(); - if(!group) return true; - - int pos = list.get_selection(); - if(pos < 0 || pos >= group->list.size()) return true; - - string message; - if(group->list[pos]->type == InputObject::Button) { - message = translate["Press a key or button to assign to $ ..."]; - } else { - message = translate["Move mouse or analog joypad axis to assign to $ ..."]; - } - - message.replace("$", translate[group->list[pos]->name]); - window_input_capture.label.set_text(message); - - bool show_controller_graphic = false; - InputDevice *device = dynamic_cast(group); - if(device) { - SNES::Input::DeviceID id = device->id; - if(id == SNES::Input::DeviceIDJoypad1 || id == SNES::Input::DeviceIDJoypad2 - || id == SNES::Input::DeviceIDMultitap1A || id == SNES::Input::DeviceIDMultitap2A - || id == SNES::Input::DeviceIDMultitap1B || id == SNES::Input::DeviceIDMultitap2B - || id == SNES::Input::DeviceIDMultitap1C || id == SNES::Input::DeviceIDMultitap2C - || id == SNES::Input::DeviceIDMultitap1D || id == SNES::Input::DeviceIDMultitap2D - ) { - show_controller_graphic = true; - } - } - - window_input_capture.index = pos; - window_input_capture.canvas.show(show_controller_graphic); - window_input_capture.show(); - return true; -} - -uintptr_t InputConfigWindow::clr_tick(event_t) { - if(list.get_selection() >= 0) { - assign(keyboard::none); - refresh_list(); - } - return true; -} - -/* InputCaptureWindow */ - -void InputCaptureWindow::assign(uint16_t code) { - if(window_input_config.assign(code)) { - waiting = false; - hide(); - window_input_config.refresh_list(); - input_manager.flush(); - } -} - -void InputCaptureWindow::show() { - input_manager.refresh(); - waiting = true; - //certain keys (eg spacebar) can activate the key assignment window, - //which would then auto-bind those keys. detect these keys, and set - //a lock so that these keys will not be registered unless they - //are released and then re-pressed. - locked = input_manager.state(keyboard::return_) - || input_manager.state(keyboard::spacebar) - || input_manager.state(mouse::button + 0); - Window::focus(); -} - -uintptr_t InputCaptureWindow::close(event_t) { - hide(); - return false; -} - -void InputCaptureWindow::setup() { - create(Window::AutoCenter, 382, 206, translate["bsnes Key Capture"]); - set_icon(48, 48, (uint32_t*)resource::icon48); - - label.create(0, 340, 18); - canvas.create(0, 372, 178); - memcpy(canvas.buffer(), resource::controller, 372 * 178 * 4); - attach(label, 5, 5); - attach(canvas, 5, 23); - on_close = bind(&InputCaptureWindow::close, this); -} - -InputCaptureWindow::InputCaptureWindow() { - waiting = false; - locked = false; - index = 0; -} diff --git a/src/ui_hiro/settings/inputconfig.hpp b/src/ui_hiro/settings/inputconfig.hpp deleted file mode 100644 index 3db7735a..00000000 --- a/src/ui_hiro/settings/inputconfig.hpp +++ /dev/null @@ -1,47 +0,0 @@ -class InputGroup; - -class InputConfigWindow : public Window { -public: - Label capture_mode; - Radiobox capture_always; - Radiobox capture_focus; - Radiobox capture_pause; - Combobox config_type; - Combobox config_subtype; - Listbox list; - Button setkey; - Button clrkey; - - void setup(); - - InputGroup* get_group(); - bool assign(uint16_t code); - - void refresh_subtype(); - void refresh_list(); - - uintptr_t capture_change(event_t); - uintptr_t type_change(event_t); - uintptr_t subtype_change(event_t); - uintptr_t list_change(event_t); - uintptr_t set_tick(event_t); - uintptr_t clr_tick(event_t); -} window_input_config; - -class InputCaptureWindow : public Window { -public: - Label label; - Canvas canvas; - - bool waiting; - bool locked; - unsigned index; - - void assign(uint16_t code); - void show(); - void setup(); - - uintptr_t close(event_t); - - InputCaptureWindow(); -} window_input_capture; diff --git a/src/ui_hiro/settings/pathsettings.cpp b/src/ui_hiro/settings/pathsettings.cpp deleted file mode 100644 index c0e19d96..00000000 --- a/src/ui_hiro/settings/pathsettings.cpp +++ /dev/null @@ -1,187 +0,0 @@ -//======== -//ROM path -//======== - -uintptr_t PathSettingsWindow::selectpath_rom(event_t) { - char t[PATH_MAX]; - if(hiro().folder_select(&window_settings, t) == true) { - snes.config.path.rom = t; - update_paths(); - } - return true; -} - -uintptr_t PathSettingsWindow::defaultpath_rom(event_t) { - snes.config.path.rom = ""; - update_paths(); - return true; -} - -//============= -//save RAM path -//============= - -uintptr_t PathSettingsWindow::selectpath_save(event_t) { - char t[PATH_MAX]; - if(hiro().folder_select(&window_settings, t) == true) { - snes.config.path.save = t; - update_paths(); - } - return true; -} - -uintptr_t PathSettingsWindow::defaultpath_save(event_t) { - snes.config.path.save = ""; - update_paths(); - return true; -} - -//============== -//UPS patch path -//============== - -uintptr_t PathSettingsWindow::selectpath_patch(event_t) { - char t[PATH_MAX]; - if(hiro().folder_select(&window_settings, t) == true) { - snes.config.path.patch = t; - update_paths(); - } - return true; -} - -uintptr_t PathSettingsWindow::defaultpath_patch(event_t) { - snes.config.path.patch = ""; - update_paths(); - return true; -} - -//========== -//cheat path -//========== - -uintptr_t PathSettingsWindow::selectpath_cheat(event_t) { - char t[PATH_MAX]; - if(hiro().folder_select(&window_settings, t) == true) { - snes.config.path.cheat = t; - update_paths(); - } - return true; -} - -uintptr_t PathSettingsWindow::defaultpath_cheat(event_t) { - snes.config.path.cheat = ""; - update_paths(); - return true; -} - -//=========== -//export path -//=========== - -uintptr_t PathSettingsWindow::selectpath_export(event_t) { - char t[PATH_MAX]; - if(hiro().folder_select(&window_settings, t) == true) { - snes.config.path.data = t; - update_paths(); - } - return true; -} - -uintptr_t PathSettingsWindow::defaultpath_export(event_t) { - snes.config.path.data = ""; - update_paths(); - return true; -} - -//============== -//user interface -//============== - -void PathSettingsWindow::update_paths() { - if(snes.config.path.rom != "") rompath.set_text(snes.config.path.rom); - else rompath.set_text(translate[""]); - - if(snes.config.path.save != "") savepath.set_text(snes.config.path.save); - else savepath.set_text(translate[""]); - - if(snes.config.path.patch != "") patchpath.set_text(snes.config.path.patch); - else patchpath.set_text(translate[""]); - - if(snes.config.path.cheat != "") cheatpath.set_text(snes.config.path.cheat); - else cheatpath.set_text(translate[""]); - - if(snes.config.path.data != "") exportpath.set_text(snes.config.path.data); - else exportpath.set_text(translate[""]); -} - -void PathSettingsWindow::setup() { - create(0, 451, 370); - - lrompath.create(0, 451, 18, translate["Games:"]); - rompath.create(Editbox::Readonly, 241, 25); - romselect.create(0, 100, 25, string() << translate["{{path}}Select"] << " ..."); - romdefault.create(0, 100, 25, translate["{{path}}Default"]); - - lsavepath.create(0, 451, 18, translate["Save RAM:"]); - savepath.create(Editbox::Readonly, 241, 25); - saveselect.create(0, 100, 25, string() << translate["{{path}}Select"] << " ..."); - savedefault.create(0, 100, 25, translate["{{path}}Default"]); - - lpatchpath.create(0, 451, 18, translate["UPS patches:"]); - patchpath.create(Editbox::Readonly, 241, 25); - patchselect.create(0, 100, 25, string() << translate["{{path}}Select"] << " ..."); - patchdefault.create(0, 100, 25, translate["{{path}}Default"]); - - lcheatpath.create(0, 451, 18, translate["Cheat codes:"]); - cheatpath.create(Editbox::Readonly, 241, 25); - cheatselect.create(0, 100, 25, string() << translate["{{path}}Select"] << " ..."); - cheatdefault.create(0, 100, 25, translate["{{path}}Default"]); - - lexportpath.create(0, 451, 18, translate["Export data:"]); - exportpath.create(Editbox::Readonly, 241, 25); - exportselect.create(0, 100, 25, string() << translate["{{path}}Select"] << " ..."); - exportdefault.create(0, 100, 25, translate["{{path}}Default"]); - - unsigned y = 0; - attach(lrompath, 0, y); y += 18; - attach(rompath, 0, y); - attach(romselect, 246, y); - attach(romdefault, 351, y); y += 25 + 5; - - attach(lsavepath, 0, y); y += 18; - attach(savepath, 0, y); - attach(saveselect, 246, y); - attach(savedefault, 351, y); y += 25 + 5; - - attach(lpatchpath, 0, y); y += 18; - attach(patchpath, 0, y); - attach(patchselect, 246, y); - attach(patchdefault, 351, y); y += 25 + 5; - - attach(lcheatpath, 0, y); y += 18; - attach(cheatpath, 0, y); - attach(cheatselect, 246, y); - attach(cheatdefault, 351, y); y += 25 + 5; - - attach(lexportpath, 0, y); y += 18; - attach(exportpath, 0, y); - attach(exportselect, 246, y); - attach(exportdefault, 351, y); y += 25 + 5; - - romselect.on_tick = bind(&PathSettingsWindow::selectpath_rom, this); - romdefault.on_tick = bind(&PathSettingsWindow::defaultpath_rom, this); - - saveselect.on_tick = bind(&PathSettingsWindow::selectpath_save, this); - savedefault.on_tick = bind(&PathSettingsWindow::defaultpath_save, this); - - patchselect.on_tick = bind(&PathSettingsWindow::selectpath_patch, this); - patchdefault.on_tick = bind(&PathSettingsWindow::defaultpath_patch, this); - - cheatselect.on_tick = bind(&PathSettingsWindow::selectpath_cheat, this); - cheatdefault.on_tick = bind(&PathSettingsWindow::defaultpath_cheat, this); - - exportselect.on_tick = bind(&PathSettingsWindow::selectpath_export, this); - exportdefault.on_tick = bind(&PathSettingsWindow::defaultpath_export, this); - - update_paths(); -} diff --git a/src/ui_hiro/settings/pathsettings.hpp b/src/ui_hiro/settings/pathsettings.hpp deleted file mode 100644 index 9f52ecf6..00000000 --- a/src/ui_hiro/settings/pathsettings.hpp +++ /dev/null @@ -1,45 +0,0 @@ -class PathSettingsWindow : public Window { -public: - Label lrompath; - Editbox rompath; - Button romselect; - Button romdefault; - - Label lsavepath; - Editbox savepath; - Button saveselect; - Button savedefault; - - Label lpatchpath; - Editbox patchpath; - Button patchselect; - Button patchdefault; - - Label lcheatpath; - Editbox cheatpath; - Button cheatselect; - Button cheatdefault; - - Label lexportpath; - Editbox exportpath; - Button exportselect; - Button exportdefault; - - uintptr_t selectpath_rom(event_t); - uintptr_t defaultpath_rom(event_t); - - uintptr_t selectpath_save(event_t); - uintptr_t defaultpath_save(event_t); - - uintptr_t selectpath_patch(event_t); - uintptr_t defaultpath_patch(event_t); - - uintptr_t selectpath_cheat(event_t); - uintptr_t defaultpath_cheat(event_t); - - uintptr_t selectpath_export(event_t); - uintptr_t defaultpath_export(event_t); - - void update_paths(); - void setup(); -} window_path_settings; diff --git a/src/ui_hiro/settings/settings.cpp b/src/ui_hiro/settings/settings.cpp deleted file mode 100644 index 60cbcf2e..00000000 --- a/src/ui_hiro/settings/settings.cpp +++ /dev/null @@ -1,64 +0,0 @@ -void SettingsWindow::setup() { - create(Window::AutoCenter, 580, 380, translate["bsnes Configuration Settings"]); - set_icon(48, 48, (uint32_t*)resource::icon48); - - panel_list.create(0, 114, 370); - panel_list.add_item(translate["Drivers"]); - panel_list.add_item(translate["Video"]); - panel_list.add_item(translate["Audio"]); - panel_list.add_item(translate["Input"]); - panel_list.add_item(translate["Paths"]); - panel_list.add_item(translate["Cheat Codes"]); - panel_list.add_item(translate["Advanced"]); - - attach(panel_list, 5, 5); - attach(window_driver_select, 124, 5); - attach(window_video_settings, 124, 5); - attach(window_audio_settings, 124, 5); - attach(window_input_config, 124, 5); - attach(window_path_settings, 124, 5); - attach(window_cheat_editor, 124, 5); - attach(window_advanced, 124, 5); - - on_close = bind(&SettingsWindow::close, this); - panel_list.on_change = bind(&SettingsWindow::list_change, this); - - //if emulator crashed on last run, default to driver select window and disable list selection, - //otherwise default to input configuration (most frequently used panel) - panel_list.set_selection(config.system.invoke_crash_handler == true ? 0 : 3); - panel_list.enable(config.system.invoke_crash_handler == false); - list_change(event_t(event_t::Change)); -} - -uintptr_t SettingsWindow::close(event_t) { - hide(); - return false; -} - -uintptr_t SettingsWindow::list_change(event_t) { - window_driver_select.hide(); - window_video_settings.hide(); - window_audio_settings.hide(); - window_input_config.hide(); - window_path_settings.hide(); - window_cheat_editor.hide(); - window_advanced.hide(); - - switch(panel_list.get_selection()) { - case 0: window_driver_select.show(); break; - case 1: window_video_settings.show(); break; - case 2: window_audio_settings.show(); break; - case 3: window_input_config.show(); break; - case 4: window_path_settings.show(); break; - case 5: window_cheat_editor.show(); break; - case 6: window_advanced.show(); break; - } - - panel_list.focus(); - return true; -} - -void SettingsWindow::show() { - Window::show(); - panel_list.focus(); -} diff --git a/src/ui_hiro/settings/settings.hpp b/src/ui_hiro/settings/settings.hpp deleted file mode 100644 index 5266606d..00000000 --- a/src/ui_hiro/settings/settings.hpp +++ /dev/null @@ -1,9 +0,0 @@ -class SettingsWindow : public Window { -public: - Listbox panel_list; - - void setup(); - void show(); - uintptr_t close(event_t); - uintptr_t list_change(event_t); -} window_settings; diff --git a/src/ui_hiro/settings/videosettings.cpp b/src/ui_hiro/settings/videosettings.cpp deleted file mode 100644 index 8bf5c69d..00000000 --- a/src/ui_hiro/settings/videosettings.cpp +++ /dev/null @@ -1,103 +0,0 @@ -void VideoSettingsWindow::setup() { - create(0, 451, 370); - - lcontrast.create (0, 451, 18); - contrast.create (0, 451, 30, 191); - lbrightness.create (0, 451, 18); - brightness.create (0, 451, 30, 191); - lgamma.create (0, 451, 18); - gamma.create (0, 451, 30, 191); - gamma_ramp.create (0, 223, 18, translate["Simulate TV gamma ramp"]); - merge_fields.create(0, 223, 18, translate["Merge fields for NTSC filter"]); - - unsigned y = 0; - attach(lcontrast, 0, y); y += 18; - attach(contrast, 0, y); y += 30; - attach(lbrightness, 0, y); y += 18; - attach(brightness, 0, y); y += 30; - attach(lgamma, 0, y); y += 18; - attach(gamma, 0, y); y += 30; - - attach(gamma_ramp, 0, y); - attach(merge_fields, 228, y); y += 18; - - contrast.on_change = bind(&VideoSettingsWindow::contrast_change, this); - brightness.on_change = bind(&VideoSettingsWindow::brightness_change, this); - gamma.on_change = bind(&VideoSettingsWindow::gamma_change, this); - gamma_ramp.on_tick = bind(&VideoSettingsWindow::gammaramp_tick, this); - merge_fields.on_tick = bind(&VideoSettingsWindow::merge_fields_tick, this); - - sync_ui(); -} - -//update all UI controls to match config file values ... -void VideoSettingsWindow::sync_ui() { - contrast.set_position(config.video.contrast + 95); - lcontrast.set_text(string() - << translate["Contrast adjust"] << ": " - << ((int)config.video.contrast > 0 ? "+" : "") - << (int)config.video.contrast << "%"); - brightness.set_position(config.video.brightness + 95); - lbrightness.set_text(string() - << translate["Brightness adjust"] << ": " - << ((int)config.video.brightness > 0 ? "+" : "") - << (int)config.video.brightness << "%"); - gamma.set_position(config.video.gamma - 5); - lgamma.set_text(string() - << translate["Gamma adjust"] << ": " - << ((int)config.video.gamma > 100 ? "+" : "") - << (int)(config.video.gamma - 100) << "%"); - - gamma_ramp.check(config.video.gamma_ramp); - merge_fields.check(config.video.ntsc_filter_merge_fields); - - libfilter::colortable.set_contrast(config.video.contrast); - libfilter::colortable.set_brightness(config.video.brightness); - libfilter::colortable.set_gamma(config.video.gamma); - libfilter::colortable.enable_gamma_ramp(config.video.gamma_ramp); - libfilter::colortable.enable_sepia(config.video.sepia); - libfilter::colortable.enable_grayscale(config.video.grayscale); - libfilter::colortable.enable_invert(config.video.invert); - libfilter::colortable.update(); -} - -uintptr_t VideoSettingsWindow::contrast_change(event_t) { - if(config.video.contrast != contrast.get_position() - 95) { - config.video.contrast = contrast.get_position() - 95; - sync_ui(); - } - return true; -} - -uintptr_t VideoSettingsWindow::brightness_change(event_t) { - if(config.video.brightness != brightness.get_position() - 95) { - config.video.brightness = brightness.get_position() - 95; - sync_ui(); - } - return true; -} - -uintptr_t VideoSettingsWindow::gamma_change(event_t) { - if(config.video.gamma != gamma.get_position() + 5) { - config.video.gamma = gamma.get_position() + 5; - sync_ui(); - } - return true; -} - -uintptr_t VideoSettingsWindow::gammaramp_tick(event_t) { - if(config.video.gamma_ramp != gamma_ramp.checked()) { - config.video.gamma_ramp = gamma_ramp.checked(); - sync_ui(); - } - return true; -} - -uintptr_t VideoSettingsWindow::merge_fields_tick(event_t) { - if(config.video.ntsc_filter_merge_fields != merge_fields.checked()) { - config.video.ntsc_filter_merge_fields = merge_fields.checked(); - libfilter::filter_ntsc.adjust(0, 0, 0, 0, 0, config.video.ntsc_filter_merge_fields); - sync_ui(); - } - return true; -} diff --git a/src/ui_hiro/settings/videosettings.hpp b/src/ui_hiro/settings/videosettings.hpp deleted file mode 100644 index 09be3112..00000000 --- a/src/ui_hiro/settings/videosettings.hpp +++ /dev/null @@ -1,22 +0,0 @@ -class VideoSettingsWindow : public Window { -public: - Label lcontrast; - Label lbrightness; - Label lgamma; - Slider contrast; - Slider brightness; - Slider gamma; - - Checkbox gamma_ramp; - Checkbox merge_fields; - - void setup(); - void sync_ui(); - - uintptr_t contrast_change(event_t); - uintptr_t brightness_change(event_t); - uintptr_t gamma_change(event_t); - - uintptr_t gammaramp_tick(event_t); - uintptr_t merge_fields_tick(event_t); -} window_video_settings; diff --git a/src/ui_hiro/status.cpp b/src/ui_hiro/status.cpp deleted file mode 100644 index 599ad43f..00000000 --- a/src/ui_hiro/status.cpp +++ /dev/null @@ -1,80 +0,0 @@ -void Status::update() { - string output; - - if(queue[0].valid == true) { - output = queue[0].text; - time_t currenttime = time(0); - if((int)(currenttime - displaytime) >= 3) { - displaytime = currenttime; - - //message displayed for 3 seconds or more, remove from queue - for(unsigned i = 0; i < 15; i++) { - queue[i].valid = queue[i + 1].valid; - queue[i].text = queue[i + 1].text; - } - queue[15].valid = false; - queue[15].text = ""; - } - } else if(!cartridge.loaded()) { - output = ""; - } else if(app.power == false) { - output = string() << cartridge.name() << " : " << translate["Power off."]; - } else if(app.pause || app.autopause) { - output = translate["Paused."]; - } else if(ppu.status.frames_updated) { - ppu.status.frames_updated = false; - - unsigned max_framerate = snes.region() == SNES::NTSC ? 60 : 50; - switch(config.system.emulation_speed) { - case 0: max_framerate = unsigned(0.50 * max_framerate); break; - case 1: max_framerate = unsigned(0.75 * max_framerate); break; - case 2: max_framerate = unsigned(1.00 * max_framerate); break; - case 3: max_framerate = unsigned(1.50 * max_framerate); break; - case 4: max_framerate = unsigned(2.00 * max_framerate); break; - case 5: max_framerate = 0; break; - } - - output = string() << cartridge.name() << " : " << (int)ppu.status.frames_executed; - if(max_framerate != 0) { - output << " / "; - output << (int)max_framerate; - } - } else { - //no operation - return; - } - - if(text != output) { - //refresh status text if it has changed since last redraw - text = output; - window.status.set_text(text); - } -} - -void Status::flush() { - for(unsigned i = 0; i < 16; i++) { - queue[i].valid = false; - queue[i].text = ""; - } -} - -bool Status::enqueue(const char *message) { - unsigned index = 0; - while(index < 16) { - if(queue[index].valid == false) break; - index++; - } - //queue full? - if(index >= 16) return false; - - queue[index].valid = true; - queue[index].text = message; - displaytime = time(0); - update(); - - return true; -} - -Status::Status() : window(window_main) { - flush(); -} diff --git a/src/ui_hiro/status.hpp b/src/ui_hiro/status.hpp deleted file mode 100644 index 9d6dcd3e..00000000 --- a/src/ui_hiro/status.hpp +++ /dev/null @@ -1,18 +0,0 @@ -class Status { -public: - void update(); - void flush(); - bool enqueue(const char *message); - - Status(); - -private: - Window &window; - string text; - - struct Queue { - bool valid; - string text; - } queue[16]; - time_t displaytime; -} status; diff --git a/src/ui_hiro/ui.cpp b/src/ui_hiro/ui.cpp deleted file mode 100644 index 9fe824fd..00000000 --- a/src/ui_hiro/ui.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "resource.cpp" - -#include "base/main.cpp" -#include "base/textview.cpp" -#include "base/about.cpp" - -#include "loader/bsxloader.cpp" -#include "loader/stloader.cpp" - -#include "settings/settings.cpp" -#include "settings/driverselect.cpp" -#include "settings/videosettings.cpp" -#include "settings/audiosettings.cpp" -#include "settings/inputconfig.cpp" -#include "settings/pathsettings.cpp" -#include "settings/cheateditor.cpp" -#include "settings/advanced.cpp" - -void ui_init() { - hiro().disable_screensaver(); - resource::init(); - - //ruby can initialize with "", but driver selection window needs active driver name - 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.invoke_crash_handler == false) { - video.driver(config.system.video); - audio.driver(config.system.audio); - input.driver(config.system.input); - } - - window_main.setup(); - window_textview.setup(); - window_about.setup(); - - window_bsxloader.setup(); - window_stloader.setup(); - - window_driver_select.setup(); - window_video_settings.setup(); - window_audio_settings.setup(); - window_input_config.setup(); - window_path_settings.setup(); - window_cheat_editor.setup(); - window_advanced.setup(); - window_settings.setup(); - - config.video.mode = (config.misc.start_in_fullscreen_mode == false ? 0 : 1); - event::update_opacity(); - event::update_video_settings(); //call first time to resize main window and update menubar - - if(config.system.invoke_crash_handler == true) { - //application crashed during driver setup on last run ... - //allow selection of new drivers, and then exit emulator. - window_settings.show(); - while(window_settings.visible()) { - while(hiro().pending()) hiro().run(); - usleep(20 * 1000); - } - config.system.invoke_crash_handler = false; - event::quit(); - return; - } - - window_main.show(); - while(hiro().pending()) hiro().run(); - - //detect crashes during driver initialization - config.system.invoke_crash_handler = true; - config.save(config.bsnes_cfg); - - video.set(Video::Handle, window_main.view.handle()); - video.set(Video::Synchronize, config.video.synchronize); - audio.set(Audio::Handle, window_main.handle()); - audio.set(Audio::Synchronize, config.audio.synchronize); - audio.set(Audio::Volume, config.audio.volume); - audio.set(Audio::Frequency, config.audio.output_frequency); - audio.set(Audio::Latency, config.audio.latency); - input.set(Input::Handle, window_main.handle()); - input.set(Input::AnalogAxisResistance, config.input.analog_axis_resistance); - - //sets Audio::Resample, Audio::ResampleOutputFrequency and Audio::ResampleInputFrequency - event::update_emulation_speed(config.system.emulation_speed); - - video.init(); - audio.init(); - input.init(); - - video.clear(); - audio.clear(); - - //if code has reached this point, driver initialized successfully - config.system.invoke_crash_handler = false; - config.save(config.bsnes_cfg); - - event::update_video_settings(); //call second time to update video class settings - - //UI setup complete, hook input callback - input_manager.on_input = bind(&event::input_event); -} - -void ui_term() { - window_main.hide(); - - video.term(); - audio.term(); - input.term(); -} diff --git a/src/ui_hiro/ui.hpp b/src/ui_hiro/ui.hpp deleted file mode 100644 index f7c38801..00000000 --- a/src/ui_hiro/ui.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -nall::dictionary translate; - -#include "readme.hpp" -#include "license.hpp" - -#include "base/main.hpp" -#include "base/textview.hpp" -#include "base/about.hpp" - -#include "loader/bsxloader.hpp" -#include "loader/stloader.hpp" - -#include "settings/settings.hpp" -#include "settings/driverselect.hpp" -#include "settings/videosettings.hpp" -#include "settings/audiosettings.hpp" -#include "settings/inputconfig.hpp" -#include "settings/pathsettings.hpp" -#include "settings/cheateditor.hpp" -#include "settings/advanced.hpp" diff --git a/src/ui_qt/Makefile b/src/ui_qt/Makefile index 28c94b7f..a9b15ae1 100644 --- a/src/ui_qt/Makefile +++ b/src/ui_qt/Makefile @@ -8,11 +8,15 @@ moc = moc rcc = rcc ifeq ($(platform),x) # X11 + link += $(call mklib,Xtst) link += `pkg-config --libs QtCore QtGui` qtflags = `pkg-config --cflags QtCore QtGui` else ifeq ($(platform),win) # Windows qtdir = c:/qt450 - link += -L$(qtdir)/lib + + link += $(call mklibpath,$(qtdir)/lib) + link += $(call mklibpath,$(qtdir)/plugins/imageformats) + link += $(call mklib,mingw32) link += $(call mklib,qtmain) link += $(call mklib,QtGui) @@ -27,9 +31,15 @@ else ifeq ($(platform),win) # Windows link += $(call mklib,advapi32) link += $(call mklib,ws2_32) link += $(call mklib,uuid) - qtflags = $(call mkinc,$(qtdir)/include) - qtflags += $(call mkinc,$(qtdir)/include/QtCore) - qtflags += $(call mkinc,$(qtdir)/include/QtGui) + link += $(call mklib,gdi32) + + # optional image-file support: + # link += $(call mklib,qjpeg) + # link += $(call mklib,qmng) + + qtflags = $(call mkincpath,$(qtdir)/include) + qtflags += $(call mkincpath,$(qtdir)/include/QtCore) + qtflags += $(call mkincpath,$(qtdir)/include/QtGui) endif moc_objects = \ diff --git a/src/ui_qt/base/about.cpp b/src/ui_qt/base/about.cpp index 79f1cd8e..eb13f3c7 100644 --- a/src/ui_qt/base/about.cpp +++ b/src/ui_qt/base/about.cpp @@ -15,7 +15,7 @@ void AboutWindow::setup() { "" "" "" - "" + "" "
Version: " BSNES_VERSION "
Author: byuu
Homepage: http://byuu.org/
Homepage: http://byuu.org/
" ); layout->addWidget(info); @@ -28,20 +28,6 @@ void AboutWindow::setup() { window->setLayout(layout); } -void AboutWindow::show() { - window->show(); - - static bool firstShow = true; - if(firstShow == true) { - firstShow = false; - utility.centerWindow(window); - } - - application.processEvents(); - window->activateWindow(); - window->raise(); -} - void AboutWindow::Logo::paintEvent(QPaintEvent*) { QPainter painter(this); QPixmap pixmap(":/logo.png"); diff --git a/src/ui_qt/base/about.hpp b/src/ui_qt/base/about.hpp index c71f39fd..83123949 100644 --- a/src/ui_qt/base/about.hpp +++ b/src/ui_qt/base/about.hpp @@ -11,7 +11,6 @@ public: QWidget *spacer; void setup(); - void show(); public slots: } *winAbout; diff --git a/src/ui_qt/base/htmlviewer.cpp b/src/ui_qt/base/htmlviewer.cpp index 8fa87f3e..58553150 100644 --- a/src/ui_qt/base/htmlviewer.cpp +++ b/src/ui_qt/base/htmlviewer.cpp @@ -10,21 +10,11 @@ void HtmlViewerWindow::setup() { } window->setLayout(layout); - window->resize(560, 480); + window->setMinimumSize(560, 480); } void HtmlViewerWindow::show(const char *title, const char *htmlData) { document->setHtml(utf8() << htmlData); window->setWindowTitle(title); - window->show(); - - static bool firstShow = true; - if(firstShow == true) { - firstShow = false; - utility.centerWindow(window); - } - - application.processEvents(); - window->activateWindow(); - window->raise(); + utility.showCentered(window); } diff --git a/src/ui_qt/base/loader.cpp b/src/ui_qt/base/loader.cpp index 059ddd5f..18422051 100644 --- a/src/ui_qt/base/loader.cpp +++ b/src/ui_qt/base/loader.cpp @@ -133,21 +133,8 @@ void LoaderWindow::loadSufamiTurboCartridge(const char *fileBase, const char *fi void LoaderWindow::showWindow(const char *title) { window->setWindowTitle(title); - window->resize(0, 0); //shrink window as much as possible (visible widgets will forcefully increase size) - window->show(); - window->resize(0, 0); + utility.showCentered(window); load->setFocus(); - - static bool firstShow = true; - if(firstShow) { - //center window, but only on first show (to save user positioning for later shows) - firstShow = false; - utility.centerWindow(window); - } - - application.processEvents(); - window->activateWindow(); - window->raise(); } void LoaderWindow::selectBaseCartridge() { @@ -190,9 +177,19 @@ void LoaderWindow::onLoad() { string slot2 = slot2File->text().toUtf8().data(); switch(mode) { - case ModeBsxSlotted: utility.loadCartridgeBsxSlotted(base, slot1); break; - case ModeBsx: utility.loadCartridgeBsx(snes.config.path.bsx = base, slot1); break; - case ModeSufamiTurbo: utility.loadCartridgeSufamiTurbo(snes.config.path.st = base, slot1, slot2); break; + case ModeBsxSlotted: { + utility.loadCartridgeBsxSlotted(base, slot1); + } break; + + case ModeBsx: { + snes.config.path.bsx = base; + utility.loadCartridgeBsx(base, slot1); + } break; + + case ModeSufamiTurbo: { + snes.config.path.st = base; + utility.loadCartridgeSufamiTurbo(base, slot1, slot2); + } break; } } diff --git a/src/ui_qt/base/main.cpp b/src/ui_qt/base/main.cpp index cef4e132..6d2d8bde 100644 --- a/src/ui_qt/base/main.cpp +++ b/src/ui_qt/base/main.cpp @@ -124,7 +124,7 @@ void MainWindow::setup() { canvasLayout = new QVBoxLayout; { canvasLayout->setMargin(0); - canvasLayout->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + canvasLayout->setAlignment(Qt::AlignCenter); canvas = new CanvasWidget; canvas->setAcceptDrops(true); @@ -191,8 +191,6 @@ void MainWindow::setup() { connect(help_license, SIGNAL(triggered()), this, SLOT(showLicense())); connect(help_about, SIGNAL(triggered()), this, SLOT(showAbout())); - utility.resizeMainWindow(); - utility.centerWindow(window); syncUi(); } @@ -306,7 +304,7 @@ void MainWindow::syncVideo() { config.video.synchronize = settings_emulationSpee void MainWindow::syncAudio() { config.audio.synchronize = settings_emulationSpeed_syncAudio->isChecked(); utility.updateAvSync(); } void MainWindow::showConfigWindow() { - winSettings->show(); + utility.showCentered(winSettings->window); } void MainWindow::showDocumentation() { @@ -325,7 +323,7 @@ void MainWindow::showLicense() { } } void MainWindow::showAbout() { - winAbout->show(); + utility.showCentered(winAbout->window); } void MainWindow::Window::closeEvent(QCloseEvent*) { diff --git a/src/ui_qt/config.cpp b/src/ui_qt/config.cpp index d75e099e..e764d63a 100644 --- a/src/ui_qt/config.cpp +++ b/src/ui_qt/config.cpp @@ -30,7 +30,6 @@ public: struct Input { enum policy_t { FocusPolicyPauseEmulation, FocusPolicyIgnoreInput, FocusPolicyAllowInput }; unsigned focusPolicy; - unsigned analogAxisResistance; bool allowInvalidInput; struct Joypad { @@ -147,22 +146,22 @@ public: attach(audio.inputFrequency = 32000, "audio.inputFrequency"); attach(input.focusPolicy = Input::FocusPolicyPauseEmulation, "input.focusPolicy"); - attach(input.analogAxisResistance = 50, "input.analogAxisResistance", "Percentage; lower = less resistance"); - attach(input.allowInvalidInput = false, "input.allowInvalidInput", "Allow up+down / left+right combinations; may trigger bugs in some games"); + attach(input.allowInvalidInput = false, "input.allowInvalidInput", "Allow up+down / left+right combinations; may trigger bugs in some games"); - attach(input.joypad1.up = "up", "input.joypad1.up"); - attach(input.joypad1.down = "down", "input.joypad1.down"); - attach(input.joypad1.left = "left", "input.joypad1.left"); - attach(input.joypad1.right = "right", "input.joypad1.right"); - attach(input.joypad1.a = "x", "input.joypad1.a"); - attach(input.joypad1.b = "z", "input.joypad1.b"); - attach(input.joypad1.x = "s", "input.joypad1.x"); - attach(input.joypad1.y = "a", "input.joypad1.y"); - attach(input.joypad1.l = "d", "input.joypad1.l"); - attach(input.joypad1.r = "c", "input.joypad1.r"); - attach(input.joypad1.select = "rshift", "input.joypad1.select"); - attach(input.joypad1.start = "return", "input.joypad1.start"); + 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"); @@ -173,44 +172,46 @@ public: attachJoypad(input.multitap2c, "input.multitap2c"); attachJoypad(input.multitap2d, "input.multitap2d"); - attach(input.mouse1.x = "mouse.x", "input.mouse1.x"); - attach(input.mouse1.y = "mouse.y", "input.mouse1.y"); - attach(input.mouse1.left = "mouse.button00", "input.mouse1.left"); - attach(input.mouse1.right = "mouse.button02", "input.mouse1.right"); + 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"); - attach(input.mouse2.x = "mouse.x", "input.mouse2.x"); - attach(input.mouse2.y = "mouse.y", "input.mouse2.y"); - attach(input.mouse2.left = "mouse.button00", "input.mouse2.left"); - attach(input.mouse2.right = "mouse.button02", "input.mouse2.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"); - attach(input.superscope.x = "mouse.x", "input.superscope.x"); - attach(input.superscope.y = "mouse.y", "input.superscope.y"); - attach(input.superscope.trigger = "mouse.button00", "input.superscope.trigger"); - attach(input.superscope.cursor = "mouse.button02", "input.superscope.cursor"); - attach(input.superscope.turbo = "t", "input.superscope.turbo"); - attach(input.superscope.pause = "p", "input.superscope.pause"); + //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 = "mouse.x", "input.justifier1.x"); - attach(input.justifier1.y = "mouse.y", "input.justifier1.y"); - attach(input.justifier1.trigger = "mouse.button00", "input.justifier1.trigger"); - attach(input.justifier1.start = "mouse.button02", "input.jusitifer1.start"); + 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 = "none", "input.justifier2.x"); - attach(input.justifier2.y = "none", "input.justifier2.y"); - attach(input.justifier2.trigger = "none", "input.justifier2.trigger"); - attach(input.justifier2.start = "none", "input.justifier2.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 = "pause", "input.uiGeneral.pauseEmulation"); - attach(input.uiGeneral.resetSystem = "none", "input.uiGeneral.resetSystem"); - attach(input.uiGeneral.powerCycleSystem = "none", "input.uiGeneral.powerCycleSystem"); - attach(input.uiGeneral.lowerSpeed = "subtract", "input.uiGeneral.lowerSpeed"); - attach(input.uiGeneral.raiseSpeed = "add", "input.uiGeneral.raiseSpeed"); - attach(input.uiGeneral.toggleCheatSystem = "none", "input.uiGeneral.toggleCheatSystem"); - attach(input.uiGeneral.toggleFullscreen = "f11", "input.uiGeneral.toggleFullscreen"); - attach(input.uiGeneral.toggleMenu = "escape", "input.uiGeneral.toggleMenu"); - attach(input.uiGeneral.toggleStatus = "escape", "input.uiGeneral.toggleStatus"); - attach(input.uiGeneral.exitEmulator = "none", "input.uiGeneral.exitEmulator"); + 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.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"); } void attachJoypad(Input::Joypad &joypad, const char *name) { diff --git a/src/ui_qt/input/input.cpp b/src/ui_qt/input/input.cpp index 9ba40b43..f958685c 100644 --- a/src/ui_qt/input/input.cpp +++ b/src/ui_qt/input/input.cpp @@ -1,6 +1,70 @@ #include "device.cpp" #include "userinterface.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 //============ @@ -30,11 +94,15 @@ void InputManager::flush() { } } -int16_t InputManager::state(uint16_t code) { - return stateTable[activeState][code]; +int16_t InputManager::state(uint16_t code) const { + return stateTable[ activeState][code]; } -int16_t InputManager::getStatus(unsigned deviceid, unsigned id) { +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; @@ -52,35 +120,33 @@ void InputManager::refresh() { } } +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(); -} -//========= -//InputCode -//========= - -InputCode::type_t InputCode::type(uint16_t code) { - if(code < keyboard::limit) return KeyboardButton; - if(code >= mouse::x && code <= mouse::z) return MouseAxis; - if(code < mouse::limit) return MouseButton; for(unsigned i = 0; i < joypad<>::count; i++) { - unsigned index = joypad<>::index(i, joypad<>::axis); - if(code >= index && code < index + joypad<>::axes) return JoypadAxis; - if(code < joypad<>::index(i, joypad<>::limit)) return JoypadButton; + pad[i].calibrated = false; + for(unsigned n = 0; n < joypad<>::axes; n++) pad[i].axis[n] = InputCode::InvalidAxis; } - return Unknown; -} - -bool InputCode::isButton(uint16_t code) { - type_t n = type(code); - return (n == KeyboardButton || n == MouseButton || n == JoypadButton); -} - -bool InputCode::isAxis(uint16_t code) { - type_t n = type(code); - return (n == MouseAxis || n == JoypadAxis); } //=========== @@ -88,7 +154,86 @@ bool InputCode::isAxis(uint16_t code) { //=========== void InputObject::bind() { - code = nall::input_find((const char*)id); + lstring part; + part.split("::", id); + + 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; + } + + if(code == nall::input_none) id = "none"; +} + +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 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; + } else { + state = newState; + } } InputObject::InputObject(InputObject::type_t t, const char *n, string &s) : parent(0), type(t), name(n), id(s) { @@ -112,22 +257,7 @@ void InputGroup::clear() { } void InputGroup::poll(const int16_t *table) { - for(unsigned i = 0; i < list.size(); i++) { - InputCode::type_t type = InputCode::type(list[i]->code); - - if(type == InputCode::MouseAxis && !input.acquired()) { - //mouse must be acquired (locked to window) to move axes - list[i]->state = 0; - } else if(type == InputCode::MouseButton && !input.acquired()) { - //same for buttons - list[i]->state = 0; - } else if(type == InputCode::JoypadAxis) { - //joypad axis range = -32768 to +32767, scale to -8 to +7 to roughly match mouse delta - list[i]->state = table[list[i]->code] / 4096; - } else { - list[i]->state = table[list[i]->code]; - } - } + for(unsigned i = 0; i < list.size(); i++) list[i]->poll(table[list[i]->code]); } int16_t InputGroup::state(unsigned index) const { diff --git a/src/ui_qt/input/input.hpp b/src/ui_qt/input/input.hpp index 203058f6..9f536820 100644 --- a/src/ui_qt/input/input.hpp +++ b/src/ui_qt/input/input.hpp @@ -1,3 +1,24 @@ +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(); @@ -5,10 +26,14 @@ public: void clear(); void flush(); - int16_t state(uint16_t code); - int16_t getStatus(unsigned deviceid, unsigned id); + 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 onInput; InputManager(); @@ -16,34 +41,32 @@ public: 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 InputCode { - enum type_t { - KeyboardButton, - MouseAxis, - MouseButton, - JoypadAxis, - JoypadButton, - Unknown, - }; - - static type_t type(uint16_t code); - static bool isButton(uint16_t code); - static bool isAxis(uint16_t code); -}; - struct InputGroup; struct InputObject { InputGroup *parent; - enum type_t { Button, Axis } type; - const char *name; - string &id; - uint16_t code; - int16_t state; + 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() void bind(); + void bind(uint16_t code); + void poll(int16_t state); InputObject(type_t t, const char *n, string &s); }; diff --git a/src/ui_qt/main.cpp b/src/ui_qt/main.cpp index 168ed900..764b55a4 100644 --- a/src/ui_qt/main.cpp +++ b/src/ui_qt/main.cpp @@ -1,12 +1,10 @@ #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: - utf8& operator<<(const string &s) { string::operator<<(s); return *this; } - utf8& operator<<(const char *s) { string::operator<<(s); return *this; } - utf8& operator<<(int n) { string::operator<<(n); return *this; } - utf8& operator<<(double d) { string::operator<<(d); return *this; } + template utf8& operator<<(T t) { string::operator<<(t); return *this; } operator const QString() const { return QString::fromUtf8(*this); } }; @@ -19,21 +17,25 @@ public: #include "utility/utility.cpp" const char defaultStylesheet[] = - "QLabel.title {\n" - " background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(255, 0, 0, 48), stop: 1 rgba(0, 0, 0, 32));\n" - " font-weight: bold;\n" - " margin-bottom: 5px;\n" - " padding: 3px;\n" - "}\n" + "QLabel.title {" + " background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(255, 0, 0, 48), stop: 1 rgba(128, 0, 0, 96));" + " font-weight: bold;" + " margin-bottom: 5px;" + " padding: 3px;" + "}" "\n" - "#backdrop {\n" - " background: #000000;\n" - "}\n" + "#backdrop {" + " background: #000000;" + "}" "\n" - "#about-window {\n" - " background: qlineargradient(x1: 0, y1: 0, x2: 0.5, y2: 1, stop: 0 #555555, stop: 1 #aaaaaa);\n" - "}\n" - ""; + "#mouse-capture-box {" + " background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, " + " stop: 0.00 rgba(128, 0, 0, 96), stop: 0.25 rgba(255, 0, 0, 48), " + " stop: 0.75 rgba(255, 0, 0, 48), stop: 1.00 rgba(128, 0, 0, 96));" + " color: #000000;" + " font-weight: bold;" + "}" + "\n"; void Application::initPaths(const char *basename) { char temp[PATH_MAX]; @@ -82,7 +84,7 @@ void Application::locateFile(string &filename, bool createDataDirectory) { } int Application::main(int argc, char **argv) { - app = new QApplication(argc, argv); + app = new App(argc, argv); #if !defined(_WIN32) //Windows port uses 256x256 icon from resource file app->setWindowIcon(QIcon(":/bsnes.png")); @@ -131,6 +133,8 @@ int Application::main(int argc, char **argv) { } else { usleep(20 * 1000); } + + supressScreenSaver(); } config.save(configFilename); diff --git a/src/ui_qt/main.hpp b/src/ui_qt/main.hpp index 84052d63..73227f29 100644 --- a/src/ui_qt/main.hpp +++ b/src/ui_qt/main.hpp @@ -6,6 +6,8 @@ #include #include +//Q_IMPORT_PLUGIN(QJpegPlugin) +//Q_IMPORT_PLUGIN(QMngPlugin) #include <../base.hpp> #include <../cart/cart.hpp> @@ -25,7 +27,13 @@ using namespace ruby; class Application { public: - QApplication *app; + class App : public QApplication { + public: + #ifdef _WIN32 + bool winEventFilter(MSG *msg, long *result); + #endif + App(int argc, char **argv) : QApplication(argc, argv) {} + } *app; bool terminate; //set to true to terminate main() loop and exit emulator bool power; diff --git a/src/ui_qt/platform.cpp b/src/ui_qt/platform.cpp index 05a967bb..d3abb4e0 100644 --- a/src/ui_qt/platform.cpp +++ b/src/ui_qt/platform.cpp @@ -39,7 +39,27 @@ strcpy(argv[i], nall::utf8_t(wargv[i])); } } + + bool Application::App::winEventFilter(MSG *msg, long *result) { + if(msg->message == WM_SYSCOMMAND) { + if(msg->wParam == SC_SCREENSAVE || msg->wParam == SC_MONITORPOWER) { + *result = 0; + return true; + } + } + return false; + } + + void supressScreenSaver() { + //handled by event filter above + } #else + #define None XNone + #define Window XWindow + #include + #undef None + #undef Window + //POSIX-compatible (Linux, BSD, etc.) char* userpath(char *path) { *path = 0; @@ -56,4 +76,24 @@ void initargs(int &argc, char **&argv) { } + + void supressScreenSaver() { + static clock_t delta_x = 0, delta_y = 0; + + delta_y = clock(); + if(delta_y - delta_x < CLOCKS_PER_SEC * 20) return; + delta_x = delta_y; + + //XSetScreenSaver(timeout = 0) does not work + //XResetScreenSaver() does not work + //XScreenSaverSuspend() does not work + //DPMSDisable() does not work + //XSendEvent(KeyPressMask) does not work + //use XTest extension to send fake keypress every ~20 seconds. + //keycode of 255 does not map to any actual key, + //but it will block screensaver and power management. + Display *display = XOpenDisplay(0); + XTestFakeKeyEvent(display, 255, True, 0); + XTestFakeKeyEvent(display, 255, False, 0); + } #endif diff --git a/src/ui_qt/settings/input.cpp b/src/ui_qt/settings/input.cpp index 7f231757..0220bdf4 100644 --- a/src/ui_qt/settings/input.cpp +++ b/src/ui_qt/settings/input.cpp @@ -34,6 +34,9 @@ void InputSettingsWindow::setup() { assign = new QPushButton("Assign ..."); controls->addWidget(assign); + assignAll = new QPushButton("Assign All ..."); + controls->addWidget(assignAll); + unassign = new QPushButton("Unassign"); controls->addWidget(unassign); } @@ -46,6 +49,7 @@ void InputSettingsWindow::setup() { connect(list, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(assignKey())); 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())); portChanged(); @@ -54,6 +58,8 @@ void InputSettingsWindow::setup() { void InputSettingsWindow::syncUi() { QList 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); } @@ -140,6 +146,16 @@ void InputSettingsWindow::assignKey() { } } +void InputSettingsWindow::assignAllKeys() { + int index = port->currentIndex(); + if(index < 2) { + index = device->currentIndex(); + if(index < deviceItem.size()) { + winInputCapture->activate(deviceItem[index]); + } + } +} + void InputSettingsWindow::unassignKey() { int index = device->currentIndex(); if(index < deviceItem.size()) { diff --git a/src/ui_qt/settings/input.hpp b/src/ui_qt/settings/input.hpp index 810dbcd6..97583be1 100644 --- a/src/ui_qt/settings/input.hpp +++ b/src/ui_qt/settings/input.hpp @@ -11,6 +11,7 @@ public: QTreeWidget *list; QHBoxLayout *controls; QPushButton *assign; + QPushButton *assignAll; QPushButton *unassign; void setup(); @@ -22,6 +23,7 @@ public slots: void listChanged(); void updateList(); void assignKey(); + void assignAllKeys(); void unassignKey(); private: diff --git a/src/ui_qt/settings/paths.cpp b/src/ui_qt/settings/paths.cpp index 345bc786..2b4b0cb9 100644 --- a/src/ui_qt/settings/paths.cpp +++ b/src/ui_qt/settings/paths.cpp @@ -5,7 +5,7 @@ void PathSettingsWindow::setup() { layout->setMargin(0); layout->setSpacing(0); - title = new QLabel("Default File Paths"); + title = new QLabel("Default Folder Paths"); title->setProperty("class", "title"); layout->addWidget(title); @@ -127,11 +127,11 @@ void PathSettingsWindow::setup() { } void PathSettingsWindow::syncUi() { - gamePath->setText (snes.config.path.rom == "" ? "" : (const char*)snes.config.path.rom); - savePath->setText (snes.config.path.save == "" ? "" : (const char*)snes.config.path.save); - patchPath->setText(snes.config.path.patch == "" ? "" : (const char*)snes.config.path.patch); - cheatPath->setText(snes.config.path.cheat == "" ? "" : (const char*)snes.config.path.cheat); - dataPath->setText (snes.config.path.data == "" ? "" : (const char*)snes.config.path.data); + gamePath->setText (snes.config.path.rom == "" ? "" : (const char*)snes.config.path.rom); + savePath->setText (snes.config.path.save == "" ? "" : (const char*)snes.config.path.save); + patchPath->setText(snes.config.path.patch == "" ? "" : (const char*)snes.config.path.patch); + cheatPath->setText(snes.config.path.cheat == "" ? "" : (const char*)snes.config.path.cheat); + dataPath->setText (snes.config.path.data == "" ? "" : (const char*)snes.config.path.data); } void PathSettingsWindow::selectGamePath() { diff --git a/src/ui_qt/settings/settings.cpp b/src/ui_qt/settings/settings.cpp index 921aa6a3..e2268e7e 100644 --- a/src/ui_qt/settings/settings.cpp +++ b/src/ui_qt/settings/settings.cpp @@ -70,21 +70,7 @@ void SettingsWindow::setup() { connect(list, SIGNAL(currentRowChanged(int)), this, SLOT(listChanged())); listChanged(); - window->resize(600, 360); -} - -void SettingsWindow::show() { - window->show(); - - static bool firstShow = true; - if(firstShow == true) { - firstShow = false; - utility.centerWindow(window); - } - - application.processEvents(); - window->activateWindow(); - window->raise(); + window->setMinimumSize(600, 360); } void SettingsWindow::listChanged() { diff --git a/src/ui_qt/settings/settings.hpp b/src/ui_qt/settings/settings.hpp index efa5ce24..8e970142 100644 --- a/src/ui_qt/settings/settings.hpp +++ b/src/ui_qt/settings/settings.hpp @@ -25,7 +25,6 @@ public: QStackedLayout *panelLayout; void setup(); - void show(); public slots: void listChanged(); diff --git a/src/ui_qt/settings/utility/codeeditor.cpp b/src/ui_qt/settings/utility/codeeditor.cpp index f5d654cb..f5d7c7fd 100644 --- a/src/ui_qt/settings/utility/codeeditor.cpp +++ b/src/ui_qt/settings/utility/codeeditor.cpp @@ -61,7 +61,7 @@ void CodeEditorWindow::setup() { layout->addLayout(finishControls); window->setLayout(layout); - window->resize(400, 375); + window->setMinimumSize(400, 375); connect(codeList, SIGNAL(itemSelectionChanged()), this, SLOT(listChanged())); connect(codeValue, SIGNAL(textChanged(const QString&)), this, SLOT(codeChanged())); @@ -148,7 +148,7 @@ void CodeEditorWindow::addCode() { codeList->clear(); codeValue->setText(""); enabled->setCheckState(Qt::Unchecked); - showWindow("Add new cheat code"); + showWindow("Add New Cheat Code"); } void CodeEditorWindow::editCode(unsigned code) { @@ -166,23 +166,13 @@ void CodeEditorWindow::editCode(unsigned code) { for(unsigned i = 0; i < item.count; i++) codeList->addItem(utf8() << part[i]); enabled->setCheckState(item.enabled ? Qt::Checked : Qt::Unchecked); - showWindow("Edit existing cheat code"); + showWindow("Edit Existing Cheat Code"); } void CodeEditorWindow::showWindow(const char *title) { syncUi(); window->setWindowTitle(title); - window->show(); - - static bool firstShow = true; - if(firstShow == true) { - firstShow = false; - utility.centerWindow(window); - } - - application.processEvents(); - window->activateWindow(); - window->raise(); + utility.showCentered(window); } CodeEditorWindow::CodeEditorWindow() { diff --git a/src/ui_qt/settings/utility/inputcapture.cpp b/src/ui_qt/settings/utility/inputcapture.cpp index b917e7b7..c954367d 100644 --- a/src/ui_qt/settings/utility/inputcapture.cpp +++ b/src/ui_qt/settings/utility/inputcapture.cpp @@ -14,25 +14,10 @@ void InputCaptureWindow::setup() { mouseAxes = new QPushButton(" Assign Mouse Axis "); mouseAxes->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - mouseAxisMenu = new QMenu; - mouseAxisX = mouseAxisMenu->addAction("X-axis"); - mouseAxisY = mouseAxisMenu->addAction("Y-axis"); - mouseAxes->setMenu(mouseAxisMenu); hlayout->addWidget(mouseAxes, 0, Qt::AlignTop); mouseButtons = new QPushButton(" Assign Mouse Button "); mouseButtons->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - mouseButtonMenu = new QMenu; - mouseButton[0] = mouseButtonMenu->addAction("Button 0 (left)"); - mouseButton[1] = mouseButtonMenu->addAction("Button 1 (middle)"); - mouseButton[2] = mouseButtonMenu->addAction("Button 2 (right)"); - mouseButtonMenu->addSeparator(); - mouseButton[3] = mouseButtonMenu->addAction("Button 3"); - mouseButton[4] = mouseButtonMenu->addAction("Button 4"); - mouseButton[5] = mouseButtonMenu->addAction("Button 5"); - mouseButton[6] = mouseButtonMenu->addAction("Button 6"); - mouseButton[7] = mouseButtonMenu->addAction("Button 7"); - mouseButtons->setMenu(mouseButtonMenu); hlayout->addWidget(mouseButtons, 0, Qt::AlignTop); } layout->addLayout(hlayout); @@ -49,20 +34,18 @@ void InputCaptureWindow::setup() { layout->addWidget(spacer); window->setLayout(layout); - connect(mouseAxisX, SIGNAL(triggered()), this, SLOT(assignMouseX())); - connect(mouseAxisY, SIGNAL(triggered()), this, SLOT(assignMouseY())); - connect(mouseButton[0], SIGNAL(triggered()), this, SLOT(assignMouse0())); - connect(mouseButton[1], SIGNAL(triggered()), this, SLOT(assignMouse1())); - connect(mouseButton[2], SIGNAL(triggered()), this, SLOT(assignMouse2())); - connect(mouseButton[3], SIGNAL(triggered()), this, SLOT(assignMouse3())); - connect(mouseButton[4], SIGNAL(triggered()), this, SLOT(assignMouse4())); - connect(mouseButton[5], SIGNAL(triggered()), this, SLOT(assignMouse5())); - connect(mouseButton[6], SIGNAL(triggered()), this, SLOT(assignMouse6())); - connect(mouseButton[7], SIGNAL(triggered()), this, SLOT(assignMouse7())); + connect(mouseAxes, SIGNAL(released()), this, SLOT(assignMouseAxis())); + connect(mouseButtons, SIGNAL(released()), this, SLOT(assignMouseButton())); + + winInputMouseCaptureWindow = new InputMouseCaptureWindow; + winInputMouseCaptureWindow->setup(); + + winInputCalibration = new InputCalibrationWindow; + winInputCalibration->setup(); } void InputCaptureWindow::activate(InputObject *object) { - window->hide(); + if(!activeGroup) window->hide(); utf8 info; info << "ID: "; @@ -97,79 +80,169 @@ void InputCaptureWindow::activate(InputObject *object) { } title->setText(info); - window->resize(0, 0); //shrink window as much as possible (visible widgets will forcefully increase size) - window->show(); - window->resize(0, 0); + utility.showCentered(window); +} - static bool firstShow = true; - if(firstShow == true) { - firstShow = false; - utility.centerWindow(window); - } - - application.processEvents(); - window->activateWindow(); - window->raise(); +void InputCaptureWindow::activate(InputGroup *group) { + activeGroup = group; + groupIndex = 0; + window->hide(); + activate((*activeGroup)[groupIndex]); } void InputCaptureWindow::inputEvent(uint16_t code, bool forceAssign /* = false */) { - if(!activeObject) return; + 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(winInputMouseCaptureWindow->window->isActiveWindow()) { + winInputMouseCaptureWindow->inputEvent(code); + return; + } + if(!window->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) { + winInputCalibration->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; - //only capture when axis is positioned at least 50% toward a given direction - if(abs(state) < 16384) 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 - || type == InputCode::JoypadAxis ) return; //only capture on button press, not release - if(state == false) return; + 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; + } + } + } } } - if(window->isActiveWindow()) { - activeObject->id = nall::input_find(code); - winInputSettings->updateList(); - inputManager.bind(); - activeObject = 0; + //bind code and update GUI input assignment list + activeObject->bind(code); + winInputSettings->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) { window->hide(); + winInputMouseCaptureWindow->window->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 + window->hide(); + winInputMouseCaptureWindow->window->hide(); + activeGroup = 0; + } } } -void InputCaptureWindow::assignMouseX() { inputEvent(mouse::x, true); } -void InputCaptureWindow::assignMouseY() { inputEvent(mouse::y, true); } -void InputCaptureWindow::assignMouse0() { inputEvent(mouse::button + 0, true); } -void InputCaptureWindow::assignMouse1() { inputEvent(mouse::button + 1, true); } -void InputCaptureWindow::assignMouse2() { inputEvent(mouse::button + 2, true); } -void InputCaptureWindow::assignMouse3() { inputEvent(mouse::button + 3, true); } -void InputCaptureWindow::assignMouse4() { inputEvent(mouse::button + 4, true); } -void InputCaptureWindow::assignMouse5() { inputEvent(mouse::button + 5, true); } -void InputCaptureWindow::assignMouse6() { inputEvent(mouse::button + 6, true); } -void InputCaptureWindow::assignMouse7() { inputEvent(mouse::button + 7, true); } +void InputCaptureWindow::assignMouseAxis() { + //refresh input state so that mouse release event (from SIGNAL(released()) + //is not sent immediately after window is visible. + inputManager.refresh(); + winInputMouseCaptureWindow->activate(InputMouseCaptureWindow::AxisMode); +} + +void InputCaptureWindow::assignMouseButton() { + inputManager.refresh(); + winInputMouseCaptureWindow->activate(InputMouseCaptureWindow::ButtonMode); +} InputCaptureWindow::InputCaptureWindow() { activeObject = 0; + activeGroup = 0; + groupIndex = 0; + inputLock = false; } void InputCaptureWindow::Window::closeEvent(QCloseEvent*) { //window closed by user, cancel key assignment winInputCapture->activeObject = 0; + winInputCapture->activeGroup = 0; } void InputCaptureWindow::ImageWidget::paintEvent(QPaintEvent*) { @@ -180,3 +253,202 @@ void InputCaptureWindow::ImageWidget::paintEvent(QPaintEvent*) { QPixmap pixmap(":/joypad.png"); painter.drawPixmap(0, 0, pixmap); } + +//======================= +//InputMouseCaptureWindow +//======================= + +void InputMouseCaptureWindow::setup() { + window = new QWidget; + window->setObjectName("input-mouse-capture-window"); + window->setWindowTitle("Mouse Input Capture"); + + layout = new QVBoxLayout; + layout->setMargin(Style::WindowMargin); + layout->setSpacing(0); + + 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); { + xAxis = new QPushButton("X-axis"); + buttonLayout->addWidget(xAxis); + + yAxis = new QPushButton("Y-axis"); + buttonLayout->addWidget(yAxis); + } + layout->addLayout(buttonLayout); + + spacer = new QWidget; + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout->addWidget(spacer); + + window->setLayout(layout); + connect(xAxis, SIGNAL(released()), this, SLOT(assignAxisX())); + connect(yAxis, SIGNAL(released()), this, SLOT(assignAxisY())); +} + +void InputMouseCaptureWindow::activate(InputMouseCaptureWindow::Mode mode_) { + window->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 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
" + << "over the capture box below, and then click any mouse button to set assignment." + ); + } + + utility.showCentered(window); +} + +//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 = window->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; + + winInputCapture->inputEvent(code, true); + return; + } + } +} + +void InputMouseCaptureWindow::assignAxisX() { + if(activeMouse >= 0) { + winInputCapture->inputEvent(mouse<>::index(activeMouse, mouse<>::x), true); + } +} + +void InputMouseCaptureWindow::assignAxisY() { + if(activeMouse >= 0) { + winInputCapture->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(window->isVisible()) return; + + activeJoypad = joy; + info->setText(utf8() + << "Joypad #" << joy << " needs to be calibrated before it can be mapped. " + << "Please ensure that
no buttons are pressed, " + << "and all axes are centered before pressing okay." + ); + + utility.showCentered(window); + ok->setFocus(); +} + +void InputCalibrationWindow::setup() { + window = new Window; + window->setObjectName("input-calibrate-window"); + window->setWindowTitle("Joypad Calibration"); + + layout = new QVBoxLayout; + layout->setMargin(Style::WindowMargin); + layout->setSpacing(0); + + info = new QLabel; + layout->addWidget(info); + layout->addSpacing(Style::WidgetSpacing); + + ok = new QPushButton("Ok"); + layout->addWidget(ok); + + spacer = new QWidget; + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout->addWidget(spacer); + + window->setLayout(layout); + connect(ok, SIGNAL(released()), this, SLOT(dismiss())); +} + +void InputCalibrationWindow::dismiss() { + window->hide(); + if(activeJoypad != -1) { + inputManager.calibrate(activeJoypad); + activeJoypad = -1; + } +} + +void InputCalibrationWindow::Window::closeEvent(QCloseEvent*) { + winInputCalibration->dismiss(); +} diff --git a/src/ui_qt/settings/utility/inputcapture.hpp b/src/ui_qt/settings/utility/inputcapture.hpp index 72fae3e3..f1972042 100644 --- a/src/ui_qt/settings/utility/inputcapture.hpp +++ b/src/ui_qt/settings/utility/inputcapture.hpp @@ -2,8 +2,6 @@ class InputCaptureWindow : public QObject { Q_OBJECT public: - InputObject *activeObject; - struct Window : public QWidget { void closeEvent(QCloseEvent*); } *window; @@ -11,12 +9,7 @@ public: QHBoxLayout *hlayout; QLabel *title; QPushButton *mouseAxes; - QMenu *mouseAxisMenu; - QAction *mouseAxisX; - QAction *mouseAxisY; QPushButton *mouseButtons; - QMenu *mouseButtonMenu; - QAction *mouseButton[8]; QWidget *imageSpacer; struct ImageWidget : public QWidget { void paintEvent(QPaintEvent*); @@ -25,18 +18,71 @@ public: void setup(); void activate(InputObject *object); + void activate(InputGroup *group); void inputEvent(uint16_t code, bool forceAssign = false); InputCaptureWindow(); public slots: - void assignMouseX(); - void assignMouseY(); - void assignMouse0(); - void assignMouse1(); - void assignMouse2(); - void assignMouse3(); - void assignMouse4(); - void assignMouse5(); - void assignMouse6(); - void assignMouse7(); + void assignMouseAxis(); + void assignMouseButton(); + +private: + InputObject *activeObject; + InputGroup *activeGroup; + unsigned groupIndex; + bool inputLock; + + friend class InputCaptureWindow::Window; } *winInputCapture; + +class InputMouseCaptureWindow : public QObject { + Q_OBJECT + +public: + enum Mode { AxisMode, ButtonMode }; + + QWidget *window; + QVBoxLayout *layout; + QLabel *info; + QLabel *captureBox; + QHBoxLayout *buttonLayout; + QPushButton *xAxis; + QPushButton *yAxis; + QWidget *spacer; + + void setup(); + void activate(Mode); + void inputEvent(uint16_t code); + +public slots: + void assignAxisX(); + void assignAxisY(); + +private: + Mode activeMode; + signed activeMouse; +} *winInputMouseCaptureWindow; + +class InputCalibrationWindow : public QObject { + Q_OBJECT + +public: + struct Window : public QWidget { + void closeEvent(QCloseEvent*); + } *window; + QVBoxLayout *layout; + QLabel *info; + QPushButton *ok; + QWidget *spacer; + + void setup(); + void activate(unsigned joy); + +public slots: + void dismiss(); + +private: + int activeJoypad; + + friend class InputCalibrationWindow::Window; +} *winInputCalibration; diff --git a/src/ui_qt/settings/video.cpp b/src/ui_qt/settings/video.cpp index cb2c1492..627e8ebb 100644 --- a/src/ui_qt/settings/video.cpp +++ b/src/ui_qt/settings/video.cpp @@ -97,7 +97,7 @@ void VideoSettingsWindow::gammaRampToggle(int state) { void VideoSettingsWindow::ntscFieldsToggle(int state) { config.video.enableNtscMergeFields = (state == Qt::Checked); syncUi(); - utility.updateColorFilter(); + utility.updateSoftwareFilter(); } void VideoSettingsWindow::contrastAdjust(int value) { diff --git a/src/ui_qt/ui.cpp b/src/ui_qt/ui.cpp index fb3fac77..9c9a2325 100644 --- a/src/ui_qt/ui.cpp +++ b/src/ui_qt/ui.cpp @@ -48,7 +48,8 @@ void Application::init() { winAbout->setup(); //window must be onscreen and visible before initializing video interface - winMain->window->show(); + utility.updateSystemState(); + utility.resizeMainWindow(); utility.updateFullscreenState(); application.processEvents(); @@ -74,7 +75,7 @@ void Application::init() { } audio.driver(config.system.audio); - audio.set(Audio::Handle, (uintptr_t)winMain->window->winId()); + audio.set(Audio::Handle, (uintptr_t)winMain->canvas->winId()); audio.set(Audio::Frequency, config.audio.outputFrequency); audio.set(Audio::Latency, config.audio.latency); audio.set(Audio::Volume, config.audio.volume); @@ -90,8 +91,7 @@ void Application::init() { } input.driver(config.system.input); - input.set(Input::Handle, (uintptr_t)winMain->window->winId()); - input.set(Input::AnalogAxisResistance, config.input.analogAxisResistance); + input.set(Input::Handle, (uintptr_t)winMain->canvas->winId()); if(input.init() == false) { QMessageBox::warning(0, "bsnes", utf8() << "

Warning: " << config.system.input << " input driver failed to initialize. " diff --git a/src/ui_qt/utility/utility.cpp b/src/ui_qt/utility/utility.cpp index faa014e2..945f549b 100644 --- a/src/ui_qt/utility/utility.cpp +++ b/src/ui_qt/utility/utility.cpp @@ -1,52 +1,85 @@ #include "cartridge.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) { - //if input capture assignment window is currently active, forward key-press event - if(winInputCapture->activeObject) winInputCapture->inputEvent(code); + //forward key-press event + //(in case window is currently active and capturing a new button / axis assignment) + winInputCapture->inputEvent(code); - //only match buttons being pressed down ... - if(InputCode::isButton(code) == false) return; - if(inputManager.state(code) == false) return; - - if(code == keyboard::escape && input.acquired()) { - input.unacquire(); - return; //do not trigger other UI actions that may be bound to escape key + //if escape key is pressed on *any* keyboard; release the mouse if it is acquired + for(unsigned i = 0; i < keyboard<>::count; i++) { + if(code == keyboard<>::index(i, keyboard<>::escape) && inputManager.state(code) && input.acquired()) { + input.unacquire(); + return; //do not trigger other UI actions that may be bound to escape key + } } if(winMain->window->isActiveWindow()) { bool resizeWindow = false; - if(code == inputUiGeneral.loadCartridge.code) { + if(isButtonDown(code, inputUiGeneral.loadCartridge)) { string filename = selectCartridge(); if(filename.length() > 0) loadCartridge(filename); } - if(code == inputUiGeneral.pauseEmulation.code) { + if(isButtonDown(code, inputUiGeneral.pauseEmulation)) { application.pause = !application.pause; } - if(code == inputUiGeneral.resetSystem.code) { + if(isButtonDown(code, inputUiGeneral.resetSystem)) { modifySystemState(Reset); } - if(code == inputUiGeneral.powerCycleSystem.code) { + if(isButtonDown(code, inputUiGeneral.powerCycleSystem)) { modifySystemState(PowerCycle); } - if(code == inputUiGeneral.lowerSpeed.code) { + if(isButtonDown(code, inputUiGeneral.lowerSpeed)) { config.system.speed--; updateEmulationSpeed(); winMain->syncUi(); } - if(code == inputUiGeneral.raiseSpeed.code) { + if(isButtonDown(code, inputUiGeneral.raiseSpeed)) { config.system.speed++; updateEmulationSpeed(); winMain->syncUi(); } - if(code == inputUiGeneral.toggleCheatSystem.code) { + if(isButtonDown(code, inputUiGeneral.toggleCheatSystem)) { if(cheat.enabled() == false) { cheat.enable(); showMessage("Cheat system enabled."); @@ -56,18 +89,18 @@ void Utility::inputEvent(uint16_t code) { } } - if(code == inputUiGeneral.toggleFullscreen.code) { + if(isButtonDown(code, inputUiGeneral.toggleFullscreen)) { config.video.isFullscreen = !config.video.isFullscreen; updateFullscreenState(); winMain->syncUi(); } - if(code == inputUiGeneral.toggleMenu.code) { + if(isButtonDown(code, inputUiGeneral.toggleMenu)) { winMain->window->menuBar()->setVisible(!winMain->window->menuBar()->isVisibleTo(winMain->window)); resizeWindow = true; } - if(code == inputUiGeneral.toggleStatus.code) { + if(isButtonDown(code, inputUiGeneral.toggleStatus)) { winMain->window->statusBar()->setVisible(!winMain->window->statusBar()->isVisibleTo(winMain->window)); resizeWindow = true; } @@ -77,7 +110,7 @@ void Utility::inputEvent(uint16_t code) { resizeMainWindow(); } - if(code == inputUiGeneral.exitEmulator.code) { + if(isButtonDown(code, inputUiGeneral.exitEmulator)) { application.terminate = true; } } @@ -154,13 +187,17 @@ void Utility::updateHardwareFilter() { void Utility::updateSoftwareFilter() { libfilter::FilterInterface::FilterType type; switch(config.video.context->swFilter) { default: - case 0: type = libfilter::FilterInterface::Direct; break; + 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::HQ2x; break; - case 4: type = libfilter::FilterInterface::NTSC; break; + case 2: type = libfilter::FilterInterface::Scale2x; break; + case 3: type = libfilter::FilterInterface::HQ2x; break; + case 4: 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); + } } void Utility::updateEmulationSpeed() { diff --git a/src/ui_qt/utility/utility.hpp b/src/ui_qt/utility/utility.hpp index 691ecb67..afbaf577 100644 --- a/src/ui_qt/utility/utility.hpp +++ b/src/ui_qt/utility/utility.hpp @@ -1,6 +1,7 @@ class Utility { public: //utility.cpp + bool isButtonDown(uint16_t inputCode, InputObject &object); void inputEvent(uint16_t code); void showMessage(const char *message); void updateSystemState(); @@ -29,7 +30,7 @@ public: void modifySystemState(system_state_t state); //window.cpp - void centerWindow(QWidget *window); + void showCentered(QWidget *window); void updateFullscreenState(); void constrainSize(unsigned &x, unsigned &y, unsigned max); void resizeMainWindow(); diff --git a/src/ui_qt/utility/window.cpp b/src/ui_qt/utility/window.cpp index b11450c7..cb8b144c 100644 --- a/src/ui_qt/utility/window.cpp +++ b/src/ui_qt/utility/window.cpp @@ -1,26 +1,36 @@ -//center specified top-level window onscreen: -//accounts for taskbar, dock, window frame, etc. -void Utility::centerWindow(QWidget *window) { - QRect deskRect = QApplication::desktop()->availableGeometry(); - unsigned deskWidth = (deskRect.right() - deskRect.left() + 1); - unsigned deskHeight = (deskRect.bottom() - deskRect.top() + 1); +//show specified window in the center of the screen. +void Utility::showCentered(QWidget *window) { + QRect deskRect = QApplication::desktop()->availableGeometry(window); - if(window->isVisible()) { - QRect windowRect = window->frameGeometry(); - unsigned windowWidth = (windowRect.right() - windowRect.left() + 1); - unsigned windowHeight = (windowRect.bottom() - windowRect.top() + 1); + //place window offscreen, so that it can be shown to get proper frameSize() + window->move(std::numeric_limits::max(), std::numeric_limits::max()); + window->showNormal(); - unsigned x = (deskWidth >= windowWidth ) ? (deskWidth - windowWidth ) / 2 : 0; - unsigned y = (deskHeight >= windowHeight) ? (deskHeight - windowHeight) / 2 : 0; - window->move(deskRect.left() + x, deskRect.top() + y); - } else { - unsigned x = (deskWidth >= window->size().width() ) ? (deskWidth - window->size().width() ) / 2 : 0; - unsigned y = (deskHeight >= window->size().height()) ? (deskHeight - window->size().height()) / 2 : 0; - window->setGeometry( - deskRect.left() + x, deskRect.top() + y, - window->size().width(), window->size().height() - ); + //force-resize window to be as small as minimumSize() will allow, and then center it + window->resize(0, 0); + window->move( + deskRect.center().x() - (window->frameSize().width() / 2), + deskRect.center().y() - (window->frameSize().height() / 2) + ); + + #ifndef _WIN32 + //Xlib frame size (excluding inside) is QSize(0, 0) at first, wait for it to be valid + for(unsigned counter = 0; counter < 4096; counter++) { + if(window->frameSize() != window->size()) break; + application.processEvents(); } + #endif + + //in case frame size changed, recenter window + window->move( + deskRect.center().x() - (window->frameSize().width() / 2), + deskRect.center().y() - (window->frameSize().height() / 2) + ); + + //ensure window has focus + application.processEvents(); + window->activateWindow(); + window->raise(); } void Utility::updateFullscreenState() { @@ -57,9 +67,7 @@ void Utility::constrainSize(unsigned &x, unsigned &y, unsigned max) { } void Utility::resizeMainWindow() { - //Xlib requires time to propogate window messages to window manager; - //repeat resize a few times to ensure window ends up correctly sized and centered - for(unsigned i = 0; i < 10; i++) { + for(unsigned i = 0; i < 8; i++) { unsigned multiplier = config.video.context->multiplier; unsigned width = 256 * config.video.context->multiplier; unsigned height = (config.video.context->region == 0 ? 224 : 239) * config.video.context->multiplier; @@ -72,45 +80,33 @@ void Utility::resizeMainWindow() { } } - QDesktopWidget *desktop = QApplication::desktop(); - application.processEvents(); - if(config.video.isFullscreen == false) { //get effective desktop work area region (ignore Windows taskbar, OS X doc, etc.) - QRect deskRect = desktop->availableGeometry(); - unsigned deskWidth = (deskRect.right() - deskRect.left() + 1); - unsigned deskHeight = (deskRect.bottom() - deskRect.top() + 1); + QRect deskRect = QApplication::desktop()->availableGeometry(winMain->window); //calculate frame geometry (window border + menubar + statusbar) - unsigned frameWidth, frameHeight; - if(winMain->window->isVisible()) { - QRect frameRect = winMain->window->frameGeometry(); - frameWidth = (frameRect.right() - frameRect.left() + 1) - winMain->canvasContainer->size().width(); - frameHeight = (frameRect.bottom() - frameRect.top() + 1) - winMain->canvasContainer->size().height(); - } else { - //frameGeometry() is inaccurate when window is not visible - //(especially before it is shown for the first time) - frameWidth = 10; //use reasonable defaults - frameHeight = 80; //for frame size - } + unsigned frameWidth = winMain->window->frameSize().width() - winMain->canvasContainer->size().width(); + unsigned frameHeight = winMain->window->frameSize().height() - winMain->canvasContainer->size().height(); //ensure window size will not be larger than viewable desktop area - constrainSize(height, width, deskHeight - frameHeight); - constrainSize(width, height, deskWidth - frameWidth ); + constrainSize(height, width, deskRect.height() - frameHeight); + constrainSize(width, height, deskRect.width() - frameWidth ); - //resize window such that it is as small as possible to hold canvas - //of size (width, height); and center resultant window onscreen + //resize window such that it is as small as possible to hold canvas of size (width, height) winMain->canvas->setFixedSize(width, height); - winMain->window->move( - deskRect.left() + ((deskWidth - (frameWidth + width )) / 2), - deskRect.top () + ((deskHeight - (frameHeight + height)) / 2) - ); winMain->window->resize(width, height); + + //center window onscreen + winMain->window->move( + deskRect.center().x() - (winMain->window->frameSize().width() / 2), + deskRect.center().y() - (winMain->window->frameSize().height() / 2) + ); } else { - //center canvas onscreen, ensure it is not larger than viewable area - winMain->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); constrainSize(height, width, winMain->canvasContainer->size().height()); constrainSize(width, height, winMain->canvasContainer->size().width()); + + //center canvas onscreen; ensure it is not larger than viewable area + winMain->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); winMain->canvas->setMaximumSize(width, height); }