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); }