From 4c43e8514132e347371f060e0a9637e0c6a48d78 Mon Sep 17 00:00:00 2001 From: byuu Date: Sat, 22 Dec 2007 18:26:54 +0000 Subject: [PATCH] Update to bsnes v027 release. This version replaces libui with miu -- a new GUI wrapper library, and cleans up large portions of the source code. Unfortunately, the GUI rewrite took far, far longer than I ever imagined. As a result, no work has gone into the core emulation for this version. But with the GUI rewrite out of the way, that should change in the near future. And thanks to the new UI library, I can now begin work on adding a cross-platform debugger to bsnes, at long last. Changelog: - Major source code cleanup (lib/, ui/miu/, ui/vai/) - Cheat code editor was broken in v0.026, this is now fixed - Cheat code file format simplified for human readability - Makefile install target improvements [belegdol] - libui replaced with miu GUI library - Custom video / audio / input drivers replaced with vai HW library - ppc and ppc64 libco targets added [Vas Crabb] - x86 and x86-64 libco targets now work on OS X [Lucas Newman] --- license.txt | 2 +- readme.txt | 2 +- src/Makefile | 654 ++++++++-------- src/base.h | 107 +-- src/cart/cart.cpp | 16 + src/cart/cart_file.cpp | 85 +-- src/cc.bat | 8 +- src/cc.sh | 4 +- src/cheat/cheat.cpp | 69 +- src/clean.bat | 4 +- src/clean.sh | 3 +- src/config/config.cpp | 4 +- src/configure | 5 - src/interface.h | 73 +- src/lib/barray.h | 87 +++ src/lib/{libbase.h => bbase.h} | 30 +- src/lib/{libconfig.h => bconfig.h} | 104 +-- src/lib/{libfunction.h => bfunction.h} | 27 +- src/lib/{libkeymap.h => bkeymap.h} | 9 +- src/lib/bstring.cpp | 95 +++ src/lib/bstring.h | 99 +++ src/lib/bstring/bstring.list.cpp | 14 + .../bstring.math.cpp} | 315 +++++--- src/lib/bstring/bstring.misc.cpp | 277 +++++++ .../bstring.replace.cpp} | 174 ++--- .../bstring.split.cpp} | 76 +- src/lib/bstring/bstring.strl.cpp | 31 + src/lib/bstring/bstring.trim.cpp | 39 + src/lib/{libvector.h => bvector.h} | 9 +- src/lib/libarray.h | 86 --- src/lib/libco.h | 37 + src/lib/libco/libco.ppc.s | 478 ++++++++++++ src/lib/libco/libco.ppc64.s | 513 +++++++++++++ src/lib/libco/libco.ucontext.cpp | 80 ++ src/lib/libco/libco.win.cpp | 66 ++ .../libco.x86-64.asm} | 269 ++++--- .../{libco_x86.asm => libco/libco.x86.asm} | 303 ++++---- src/lib/libco_x86.h | 26 - src/lib/libco_x86_64.h | 16 - src/lib/libstring.cpp | 456 ----------- src/lib/libstring.h | 220 ------ src/lib/libstring_array.cpp | 11 - src/lib/libstring_int.cpp | 5 - src/lib/libstring_oo.cpp | 47 -- src/lib/libstring_sprintf.cpp | 220 ------ src/lib/libui_gtk.cpp | 283 ------- src/lib/libui_gtk.h | 87 --- src/lib/libui_gtk_control.cpp | 676 ----------------- src/lib/libui_gtk_control.h | 265 ------- src/lib/libui_gtk_window.cpp | 119 --- src/lib/libui_win.cpp | 239 ------ src/lib/libui_win.h | 116 --- src/lib/libui_win_control.cpp | 710 ------------------ src/lib/libui_win_control.h | 271 ------- src/lib/libui_win_window.cpp | 290 ------- src/lib/miu.cpp | 253 +++++++ src/lib/miu.gtk/miu.gtk.button.cpp | 25 + src/lib/miu.gtk/miu.gtk.button.h | 12 + src/lib/miu.gtk/miu.gtk.canvas.cpp | 72 ++ src/lib/miu.gtk/miu.gtk.canvas.h | 19 + src/lib/miu.gtk/miu.gtk.checkbox.cpp | 37 + src/lib/miu.gtk/miu.gtk.checkbox.h | 15 + src/lib/miu.gtk/miu.gtk.combobox.cpp | 44 ++ src/lib/miu.gtk/miu.gtk.combobox.h | 16 + src/lib/miu.gtk/miu.gtk.cpp | 118 +++ src/lib/miu.gtk/miu.gtk.editbox.cpp | 62 ++ src/lib/miu.gtk/miu.gtk.editbox.h | 16 + src/lib/miu.gtk/miu.gtk.formcontrol.cpp | 32 + src/lib/miu.gtk/miu.gtk.formcontrol.h | 15 + src/lib/miu.gtk/miu.gtk.frame.cpp | 19 + src/lib/miu.gtk/miu.gtk.frame.h | 12 + src/lib/miu.gtk/miu.gtk.h | 58 ++ src/lib/miu.gtk/miu.gtk.keymap.cpp | 188 +++++ src/lib/miu.gtk/miu.gtk.label.cpp | 21 + src/lib/miu.gtk/miu.gtk.label.h | 12 + src/lib/miu.gtk/miu.gtk.listbox.cpp | 135 ++++ src/lib/miu.gtk/miu.gtk.listbox.h | 25 + src/lib/miu.gtk/miu.gtk.menucheckitem.cpp | 31 + src/lib/miu.gtk/miu.gtk.menucheckitem.h | 14 + src/lib/miu.gtk/miu.gtk.menucontrol.cpp | 20 + src/lib/miu.gtk/miu.gtk.menucontrol.h | 12 + src/lib/miu.gtk/miu.gtk.menugroup.cpp | 21 + src/lib/miu.gtk/miu.gtk.menugroup.h | 13 + src/lib/miu.gtk/miu.gtk.menuitem.cpp | 19 + src/lib/miu.gtk/miu.gtk.menuitem.h | 11 + src/lib/miu.gtk/miu.gtk.menuradioitem.cpp | 33 + src/lib/miu.gtk/miu.gtk.menuradioitem.h | 13 + src/lib/miu.gtk/miu.gtk.menuseparator.cpp | 14 + src/lib/miu.gtk/miu.gtk.menuseparator.h | 11 + src/lib/miu.gtk/miu.gtk.progressbar.cpp | 25 + src/lib/miu.gtk/miu.gtk.progressbar.h | 13 + src/lib/miu.gtk/miu.gtk.radiobox.cpp | 39 + src/lib/miu.gtk/miu.gtk.radiobox.h | 14 + src/lib/miu.gtk/miu.gtk.slider.cpp | 36 + src/lib/miu.gtk/miu.gtk.slider.h | 14 + src/lib/miu.gtk/miu.gtk.widget.cpp | 24 + src/lib/miu.gtk/miu.gtk.widget.h | 13 + src/lib/miu.gtk/miu.gtk.window.cpp | 135 ++++ src/lib/miu.gtk/miu.gtk.window.h | 32 + src/lib/miu.h | 506 +++++++++++++ src/lib/miu.win/miu.win.button.cpp | 14 + src/lib/miu.win/miu.win.button.h | 8 + src/lib/miu.win/miu.win.canvas.cpp | 54 ++ src/lib/miu.win/miu.win.canvas.h | 17 + src/lib/miu.win/miu.win.checkbox.cpp | 29 + src/lib/miu.win/miu.win.checkbox.h | 11 + src/lib/miu.win/miu.win.combobox.cpp | 28 + src/lib/miu.win/miu.win.combobox.h | 14 + src/lib/miu.win/miu.win.cpp | 318 ++++++++ src/lib/miu.win/miu.win.editbox.cpp | 37 + src/lib/miu.win/miu.win.editbox.h | 9 + src/lib/miu.win/miu.win.formcontrol.cpp | 31 + src/lib/miu.win/miu.win.formcontrol.h | 16 + src/lib/miu.win/miu.win.frame.cpp | 13 + src/lib/miu.win/miu.win.frame.h | 8 + src/lib/miu.win/miu.win.h | 73 ++ src/lib/miu.win/miu.win.keymap.cpp | 67 ++ src/lib/miu.win/miu.win.label.cpp | 13 + src/lib/miu.win/miu.win.label.h | 8 + src/lib/miu.win/miu.win.listbox.cpp | 92 +++ src/lib/miu.win/miu.win.listbox.h | 17 + src/lib/miu.win/miu.win.menucheckitem.cpp | 27 + src/lib/miu.win/miu.win.menucheckitem.h | 10 + src/lib/miu.win/miu.win.menucontrol.cpp | 25 + src/lib/miu.win/miu.win.menucontrol.h | 14 + src/lib/miu.win/miu.win.menugroup.cpp | 31 + src/lib/miu.win/miu.win.menugroup.h | 11 + src/lib/miu.win/miu.win.menuitem.cpp | 6 + src/lib/miu.win/miu.win.menuitem.h | 7 + src/lib/miu.win/miu.win.menuradioitem.cpp | 26 + src/lib/miu.win/miu.win.menuradioitem.h | 13 + src/lib/miu.win/miu.win.menuseparator.cpp | 5 + src/lib/miu.win/miu.win.menuseparator.h | 7 + src/lib/miu.win/miu.win.progressbar.cpp | 20 + src/lib/miu.win/miu.win.progressbar.h | 9 + src/lib/miu.win/miu.win.radiobox.cpp | 26 + src/lib/miu.win/miu.win.radiobox.h | 13 + src/lib/miu.win/miu.win.slider.cpp | 24 + src/lib/miu.win/miu.win.slider.h | 12 + src/lib/miu.win/miu.win.widget.cpp | 27 + src/lib/miu.win/miu.win.widget.h | 19 + src/lib/miu.win/miu.win.window.cpp | 183 +++++ src/lib/miu.win/miu.win.window.h | 39 + src/lib/{ => tool}/opgen.cpp | 2 + src/lib/{ => tool}/opgen_s.cpp | 2 + src/lib/{ => tool}/opgen_so.cpp | 2 + src/memory/memory.h | 8 + src/ui/audio/ao.cpp | 56 -- src/ui/audio/ao.h | 19 - src/ui/audio/audio.cpp | 21 - src/ui/audio/audio.h | 16 - src/ui/audio/dsound.cpp | 143 ---- src/ui/audio/dsound.h | 25 - src/ui/config.cpp | 22 +- src/ui/input/dinput.cpp | 238 ------ src/ui/input/dinput.h | 38 - src/ui/input/input.cpp | 1 - src/ui/input/input.h | 14 - src/ui/input/xinput.cpp | 143 ---- src/ui/input/xinput.h | 26 - src/ui/lui/loader/ui_bsxloader.cpp | 81 -- src/ui/lui/loader/ui_bsxloader.h | 24 - src/ui/lui/loader/ui_stloader.cpp | 89 --- src/ui/lui/loader/ui_stloader.h | 19 - src/ui/lui/settings/ui_advanced.cpp | 83 -- src/ui/lui/settings/ui_advanced.h | 11 - src/ui/lui/settings/ui_cheateditor.cpp | 82 -- src/ui/lui/settings/ui_cheateditor.h | 12 - src/ui/lui/settings/ui_inputconfig.cpp | 211 ------ src/ui/lui/settings/ui_inputconfig.h | 27 - src/ui/lui/settings/ui_rastersettings.cpp | 119 --- src/ui/lui/settings/ui_rastersettings.h | 20 - src/ui/lui/settings/ui_settings.cpp | 38 - src/ui/lui/settings/ui_settings.h | 7 - src/ui/lui/settings/ui_videosettings.cpp | 59 -- src/ui/lui/settings/ui_videosettings.h | 14 - src/ui/lui/ui.cpp | 90 --- src/ui/lui/ui_about.h | 6 - src/ui/lui/ui_main.cpp | 304 -------- src/ui/lui/ui_main.h | 74 -- src/ui/main.cpp | 21 +- src/ui/main.h | 1 - src/ui/{lui => miu}/event.cpp | 92 ++- src/ui/{lui => miu}/event.h | 3 +- src/ui/miu/loader/ui_bsxloader.cpp | 92 +++ src/ui/miu/loader/ui_bsxloader.h | 28 + src/ui/miu/loader/ui_stloader.cpp | 109 +++ src/ui/miu/loader/ui_stloader.h | 27 + src/ui/{lui => miu}/main.cpp | 25 +- src/ui/miu/settings/ui_advanced.cpp | 85 +++ src/ui/miu/settings/ui_advanced.h | 15 + src/ui/miu/settings/ui_cheateditor.cpp | 91 +++ src/ui/miu/settings/ui_cheateditor.h | 16 + src/ui/miu/settings/ui_inputconfig.cpp | 214 ++++++ src/ui/miu/settings/ui_inputconfig.h | 36 + src/ui/miu/settings/ui_rastersettings.cpp | 140 ++++ src/ui/miu/settings/ui_rastersettings.h | 33 + src/ui/miu/settings/ui_settings.cpp | 47 ++ src/ui/miu/settings/ui_settings.h | 9 + src/ui/miu/ui.cpp | 114 +++ src/ui/{lui => miu}/ui.h | 1 - src/ui/{lui => miu}/ui_about.cpp | 20 +- src/ui/miu/ui_about.h | 8 + src/ui/miu/ui_main.cpp | 343 +++++++++ src/ui/miu/ui_main.h | 78 ++ src/ui/sdl/bsnes.cpp | 66 -- src/ui/sdl/bsnes.h | 23 - src/ui/sdl/main.cpp | 162 ---- src/ui/sdl/main.h | 8 - src/ui/sdl/render.cpp | 18 - src/ui/vai/audio.h | 27 + src/ui/vai/audio/audio.ao.cpp | 85 +++ src/ui/vai/audio/audio.ao.h | 25 + src/ui/vai/audio/audio.directsound.cpp | 177 +++++ src/ui/vai/audio/audio.directsound.h | 26 + src/ui/vai/input.h | 29 + src/ui/vai/input/input.directinput.cpp | 293 ++++++++ src/ui/vai/input/input.directinput.h | 28 + src/ui/vai/input/input.x.cpp | 168 +++++ src/ui/vai/input/input.x.h | 24 + src/ui/vai/video.h | 35 + src/ui/vai/video/video.direct3d.cpp | 352 +++++++++ src/ui/vai/video/video.direct3d.h | 29 + src/ui/vai/video/video.directdraw.cpp | 177 +++++ src/ui/vai/video/video.directdraw.h | 29 + src/ui/vai/video/video.gdi.cpp | 98 +++ src/ui/{video/gdi.h => vai/video/video.gdi.h} | 22 +- src/ui/vai/video/video.gtk.cpp | 120 +++ src/ui/vai/video/video.gtk.h | 28 + src/ui/vai/video/video.xv.cpp | 195 +++++ src/ui/vai/video/video.xv.h | 29 + src/ui/video/d3d.cpp | 271 ------- src/ui/video/d3d.h | 58 -- src/ui/video/ddraw.cpp | 124 --- src/ui/video/ddraw.h | 24 - src/ui/video/gdi.cpp | 57 -- src/ui/video/gtk.cpp | 42 -- src/ui/video/gtk.h | 21 - src/ui/video/video.cpp | 1 - src/ui/video/video.h | 31 - src/ui/video/xv.cpp | 141 ---- src/ui/video/xv.h | 41 - 242 files changed, 10332 insertions(+), 8557 deletions(-) delete mode 100644 src/configure create mode 100644 src/lib/barray.h rename src/lib/{libbase.h => bbase.h} (92%) rename src/lib/{libconfig.h => bconfig.h} (64%) rename src/lib/{libfunction.h => bfunction.h} (86%) rename src/lib/{libkeymap.h => bkeymap.h} (94%) create mode 100644 src/lib/bstring.cpp create mode 100644 src/lib/bstring.h create mode 100644 src/lib/bstring/bstring.list.cpp rename src/lib/{libstring_math.cpp => bstring/bstring.math.cpp} (64%) create mode 100644 src/lib/bstring/bstring.misc.cpp rename src/lib/{libstring_replace.cpp => bstring/bstring.replace.cpp} (68%) rename src/lib/{libstring_split.cpp => bstring/bstring.split.cpp} (67%) create mode 100644 src/lib/bstring/bstring.strl.cpp create mode 100644 src/lib/bstring/bstring.trim.cpp rename src/lib/{libvector.h => bvector.h} (94%) delete mode 100644 src/lib/libarray.h create mode 100644 src/lib/libco.h create mode 100644 src/lib/libco/libco.ppc.s create mode 100644 src/lib/libco/libco.ppc64.s create mode 100644 src/lib/libco/libco.ucontext.cpp create mode 100644 src/lib/libco/libco.win.cpp rename src/lib/{libco_x86_64.asm => libco/libco.x86-64.asm} (61%) rename src/lib/{libco_x86.asm => libco/libco.x86.asm} (72%) delete mode 100644 src/lib/libco_x86.h delete mode 100644 src/lib/libco_x86_64.h delete mode 100644 src/lib/libstring.cpp delete mode 100644 src/lib/libstring.h delete mode 100644 src/lib/libstring_array.cpp delete mode 100644 src/lib/libstring_int.cpp delete mode 100644 src/lib/libstring_oo.cpp delete mode 100644 src/lib/libstring_sprintf.cpp delete mode 100644 src/lib/libui_gtk.cpp delete mode 100644 src/lib/libui_gtk.h delete mode 100644 src/lib/libui_gtk_control.cpp delete mode 100644 src/lib/libui_gtk_control.h delete mode 100644 src/lib/libui_gtk_window.cpp delete mode 100644 src/lib/libui_win.cpp delete mode 100644 src/lib/libui_win.h delete mode 100644 src/lib/libui_win_control.cpp delete mode 100644 src/lib/libui_win_control.h delete mode 100644 src/lib/libui_win_window.cpp create mode 100644 src/lib/miu.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.button.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.button.h create mode 100644 src/lib/miu.gtk/miu.gtk.canvas.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.canvas.h create mode 100644 src/lib/miu.gtk/miu.gtk.checkbox.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.checkbox.h create mode 100644 src/lib/miu.gtk/miu.gtk.combobox.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.combobox.h create mode 100644 src/lib/miu.gtk/miu.gtk.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.editbox.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.editbox.h create mode 100644 src/lib/miu.gtk/miu.gtk.formcontrol.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.formcontrol.h create mode 100644 src/lib/miu.gtk/miu.gtk.frame.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.frame.h create mode 100644 src/lib/miu.gtk/miu.gtk.h create mode 100644 src/lib/miu.gtk/miu.gtk.keymap.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.label.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.label.h create mode 100644 src/lib/miu.gtk/miu.gtk.listbox.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.listbox.h create mode 100644 src/lib/miu.gtk/miu.gtk.menucheckitem.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.menucheckitem.h create mode 100644 src/lib/miu.gtk/miu.gtk.menucontrol.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.menucontrol.h create mode 100644 src/lib/miu.gtk/miu.gtk.menugroup.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.menugroup.h create mode 100644 src/lib/miu.gtk/miu.gtk.menuitem.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.menuitem.h create mode 100644 src/lib/miu.gtk/miu.gtk.menuradioitem.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.menuradioitem.h create mode 100644 src/lib/miu.gtk/miu.gtk.menuseparator.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.menuseparator.h create mode 100644 src/lib/miu.gtk/miu.gtk.progressbar.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.progressbar.h create mode 100644 src/lib/miu.gtk/miu.gtk.radiobox.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.radiobox.h create mode 100644 src/lib/miu.gtk/miu.gtk.slider.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.slider.h create mode 100644 src/lib/miu.gtk/miu.gtk.widget.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.widget.h create mode 100644 src/lib/miu.gtk/miu.gtk.window.cpp create mode 100644 src/lib/miu.gtk/miu.gtk.window.h create mode 100644 src/lib/miu.h create mode 100644 src/lib/miu.win/miu.win.button.cpp create mode 100644 src/lib/miu.win/miu.win.button.h create mode 100644 src/lib/miu.win/miu.win.canvas.cpp create mode 100644 src/lib/miu.win/miu.win.canvas.h create mode 100644 src/lib/miu.win/miu.win.checkbox.cpp create mode 100644 src/lib/miu.win/miu.win.checkbox.h create mode 100644 src/lib/miu.win/miu.win.combobox.cpp create mode 100644 src/lib/miu.win/miu.win.combobox.h create mode 100644 src/lib/miu.win/miu.win.cpp create mode 100644 src/lib/miu.win/miu.win.editbox.cpp create mode 100644 src/lib/miu.win/miu.win.editbox.h create mode 100644 src/lib/miu.win/miu.win.formcontrol.cpp create mode 100644 src/lib/miu.win/miu.win.formcontrol.h create mode 100644 src/lib/miu.win/miu.win.frame.cpp create mode 100644 src/lib/miu.win/miu.win.frame.h create mode 100644 src/lib/miu.win/miu.win.h create mode 100644 src/lib/miu.win/miu.win.keymap.cpp create mode 100644 src/lib/miu.win/miu.win.label.cpp create mode 100644 src/lib/miu.win/miu.win.label.h create mode 100644 src/lib/miu.win/miu.win.listbox.cpp create mode 100644 src/lib/miu.win/miu.win.listbox.h create mode 100644 src/lib/miu.win/miu.win.menucheckitem.cpp create mode 100644 src/lib/miu.win/miu.win.menucheckitem.h create mode 100644 src/lib/miu.win/miu.win.menucontrol.cpp create mode 100644 src/lib/miu.win/miu.win.menucontrol.h create mode 100644 src/lib/miu.win/miu.win.menugroup.cpp create mode 100644 src/lib/miu.win/miu.win.menugroup.h create mode 100644 src/lib/miu.win/miu.win.menuitem.cpp create mode 100644 src/lib/miu.win/miu.win.menuitem.h create mode 100644 src/lib/miu.win/miu.win.menuradioitem.cpp create mode 100644 src/lib/miu.win/miu.win.menuradioitem.h create mode 100644 src/lib/miu.win/miu.win.menuseparator.cpp create mode 100644 src/lib/miu.win/miu.win.menuseparator.h create mode 100644 src/lib/miu.win/miu.win.progressbar.cpp create mode 100644 src/lib/miu.win/miu.win.progressbar.h create mode 100644 src/lib/miu.win/miu.win.radiobox.cpp create mode 100644 src/lib/miu.win/miu.win.radiobox.h create mode 100644 src/lib/miu.win/miu.win.slider.cpp create mode 100644 src/lib/miu.win/miu.win.slider.h create mode 100644 src/lib/miu.win/miu.win.widget.cpp create mode 100644 src/lib/miu.win/miu.win.widget.h create mode 100644 src/lib/miu.win/miu.win.window.cpp create mode 100644 src/lib/miu.win/miu.win.window.h rename src/lib/{ => tool}/opgen.cpp (94%) rename src/lib/{ => tool}/opgen_s.cpp (93%) rename src/lib/{ => tool}/opgen_so.cpp (94%) delete mode 100644 src/ui/audio/ao.cpp delete mode 100644 src/ui/audio/ao.h delete mode 100644 src/ui/audio/audio.cpp delete mode 100644 src/ui/audio/audio.h delete mode 100644 src/ui/audio/dsound.cpp delete mode 100644 src/ui/audio/dsound.h delete mode 100644 src/ui/input/dinput.cpp delete mode 100644 src/ui/input/dinput.h delete mode 100644 src/ui/input/input.cpp delete mode 100644 src/ui/input/input.h delete mode 100644 src/ui/input/xinput.cpp delete mode 100644 src/ui/input/xinput.h delete mode 100644 src/ui/lui/loader/ui_bsxloader.cpp delete mode 100644 src/ui/lui/loader/ui_bsxloader.h delete mode 100644 src/ui/lui/loader/ui_stloader.cpp delete mode 100644 src/ui/lui/loader/ui_stloader.h delete mode 100644 src/ui/lui/settings/ui_advanced.cpp delete mode 100644 src/ui/lui/settings/ui_advanced.h delete mode 100644 src/ui/lui/settings/ui_cheateditor.cpp delete mode 100644 src/ui/lui/settings/ui_cheateditor.h delete mode 100644 src/ui/lui/settings/ui_inputconfig.cpp delete mode 100644 src/ui/lui/settings/ui_inputconfig.h delete mode 100644 src/ui/lui/settings/ui_rastersettings.cpp delete mode 100644 src/ui/lui/settings/ui_rastersettings.h delete mode 100644 src/ui/lui/settings/ui_settings.cpp delete mode 100644 src/ui/lui/settings/ui_settings.h delete mode 100644 src/ui/lui/settings/ui_videosettings.cpp delete mode 100644 src/ui/lui/settings/ui_videosettings.h delete mode 100644 src/ui/lui/ui.cpp delete mode 100644 src/ui/lui/ui_about.h delete mode 100644 src/ui/lui/ui_main.cpp delete mode 100644 src/ui/lui/ui_main.h delete mode 100644 src/ui/main.h rename src/ui/{lui => miu}/event.cpp (67%) rename src/ui/{lui => miu}/event.h (90%) create mode 100644 src/ui/miu/loader/ui_bsxloader.cpp create mode 100644 src/ui/miu/loader/ui_bsxloader.h create mode 100644 src/ui/miu/loader/ui_stloader.cpp create mode 100644 src/ui/miu/loader/ui_stloader.h rename src/ui/{lui => miu}/main.cpp (82%) create mode 100644 src/ui/miu/settings/ui_advanced.cpp create mode 100644 src/ui/miu/settings/ui_advanced.h create mode 100644 src/ui/miu/settings/ui_cheateditor.cpp create mode 100644 src/ui/miu/settings/ui_cheateditor.h create mode 100644 src/ui/miu/settings/ui_inputconfig.cpp create mode 100644 src/ui/miu/settings/ui_inputconfig.h create mode 100644 src/ui/miu/settings/ui_rastersettings.cpp create mode 100644 src/ui/miu/settings/ui_rastersettings.h create mode 100644 src/ui/miu/settings/ui_settings.cpp create mode 100644 src/ui/miu/settings/ui_settings.h create mode 100644 src/ui/miu/ui.cpp rename src/ui/{lui => miu}/ui.h (85%) rename src/ui/{lui => miu}/ui_about.cpp (53%) create mode 100644 src/ui/miu/ui_about.h create mode 100644 src/ui/miu/ui_main.cpp create mode 100644 src/ui/miu/ui_main.h delete mode 100644 src/ui/sdl/bsnes.cpp delete mode 100644 src/ui/sdl/bsnes.h delete mode 100644 src/ui/sdl/main.cpp delete mode 100644 src/ui/sdl/main.h delete mode 100644 src/ui/sdl/render.cpp create mode 100644 src/ui/vai/audio.h create mode 100644 src/ui/vai/audio/audio.ao.cpp create mode 100644 src/ui/vai/audio/audio.ao.h create mode 100644 src/ui/vai/audio/audio.directsound.cpp create mode 100644 src/ui/vai/audio/audio.directsound.h create mode 100644 src/ui/vai/input.h create mode 100644 src/ui/vai/input/input.directinput.cpp create mode 100644 src/ui/vai/input/input.directinput.h create mode 100644 src/ui/vai/input/input.x.cpp create mode 100644 src/ui/vai/input/input.x.h create mode 100644 src/ui/vai/video.h create mode 100644 src/ui/vai/video/video.direct3d.cpp create mode 100644 src/ui/vai/video/video.direct3d.h create mode 100644 src/ui/vai/video/video.directdraw.cpp create mode 100644 src/ui/vai/video/video.directdraw.h create mode 100644 src/ui/vai/video/video.gdi.cpp rename src/ui/{video/gdi.h => vai/video/video.gdi.h} (53%) create mode 100644 src/ui/vai/video/video.gtk.cpp create mode 100644 src/ui/vai/video/video.gtk.h create mode 100644 src/ui/vai/video/video.xv.cpp create mode 100644 src/ui/vai/video/video.xv.h delete mode 100644 src/ui/video/d3d.cpp delete mode 100644 src/ui/video/d3d.h delete mode 100644 src/ui/video/ddraw.cpp delete mode 100644 src/ui/video/ddraw.h delete mode 100644 src/ui/video/gdi.cpp delete mode 100644 src/ui/video/gtk.cpp delete mode 100644 src/ui/video/gtk.h delete mode 100644 src/ui/video/video.cpp delete mode 100644 src/ui/video/video.h delete mode 100644 src/ui/video/xv.cpp delete mode 100644 src/ui/video/xv.h diff --git a/license.txt b/license.txt index e1edb2fb..18995f5d 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -bsnes (TM) Open Source Reference License +bsnes (TM) Reference License Copyright (C) 2004 - 2007 byuu All rights reserved diff --git a/readme.txt b/readme.txt index 1bf51298..e2398abd 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,5 @@ bsnes -Version 0.026 +Version 0.027 Author: byuu -------- diff --git a/src/Makefile b/src/Makefile index b8a47930..0ada8639 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,321 +1,333 @@ -###################### -### bsnes makefile ### -###################### - -ifeq ($(PLATFORM),) -_null_: help -endif - -################################## -### platform-specific settings ### -################################## - -ifeq ($(PLATFORM),x-gcc-lui) -OS = unix -CC = gcc -CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI `pkg-config --cflags gtk+-2.0` -AS = nasm -ASFLAGS = -f elf -LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao -LIBCO = libco_x86 -LIBUI = libui_gtk -endif - -ifeq ($(PLATFORM),x-gcc-lui-x64) -OS = unix -CC = gcc -CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_LUI `pkg-config --cflags gtk+-2.0` -AS = yasm -ASFLAGS = -f elf64 -LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao -LIBCO = libco_x86_64 -LIBUI = libui_gtk -endif - -ifeq ($(PLATFORM),win-visualc-lui) -OS = win -CC = cl -CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI -AS = nasm -ASFLAGS = -f win32 -DWIN32 -LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib -LIBCO = libco_x86 -LIBUI = libui_win -endif - -ifeq ($(PLATFORM),win-visualc-lui-pgi) -OS = win -CC = cl -CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI -AS = nasm -ASFLAGS = -f win32 -DWIN32 -LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib -LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT -LIBCO = libco_x86 -LIBUI = libui_win -endif - -ifeq ($(PLATFORM),win-visualc-lui-pgo) -OS = win -CC = cl -CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI -AS = nasm -ASFLAGS = -f win32 -DWIN32 -LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib -LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE -LIBCO = libco_x86 -LIBUI = libui_win -endif - -ifeq ($(PLATFORM),win-mingw-lui) -OS = win -CC = mingw32-gcc -CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI -AS = nasm -ASFLAGS = -f win32 -DWIN32 -LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32 -LIBCO = libco_x86 -LIBUI = libui_win -endif - -##################################### -### compiler / assembler switches ### -##################################### - -ifeq ($(CC),gcc) -OUT = -obsnes -CPP = g++ -OBJ = o -CARGS = -c $< -o $@ -DEFINE = -D -endif - -ifeq ($(CC),mingw32-gcc) -OUT = -obsnes -CPP = mingw32-g++ -OBJ = o -CARGS = -c $< -o $@ -DEFINE = -D -endif - -ifeq ($(CC),cl) -OUT = /Febsnes -CPP = cl -OBJ = obj -CARGS = /c $< /Fo$@ -DEFINE = /D -endif - -ifeq ($(AS),nasm) -ASARGS = $< -o $@ -endif - -ifeq ($(AS),yasm) -ASARGS = $< -o $@ -endif - -################### -### OS switches ### -################### - -ifeq ($(OS),unix) -RM = rm -f -endif - -ifeq ($(OS),win) -OUT := $(OUT).exe -RM = del -endif - -#################################### -### main target and dependencies ### -#################################### - -OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(LIBUI).$(OBJ) \ - libstring.$(OBJ) \ - reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \ - cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \ - bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \ - sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \ - obc1.$(OBJ) st010.$(OBJ) - -ifeq ($(GZIP_SUPPORT),true) - OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \ - gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \ - trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ) - CFLAGS += $(DEFINE)GZIP_SUPPORT -endif - -ifeq ($(JMA_SUPPORT),true) - OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \ - iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ) - CFLAGS += $(DEFINE)JMA_SUPPORT -endif - -ifeq ($(OS),win) - ifeq ($(CC),cl) - OBJECTS += bsnes.res - endif - ifeq ($(CC),mingw32-gcc) - OBJECTS += bsnesrc.o - endif -endif - -all: $(OBJECTS) - $(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK) - -install: - cp bsnes /usr/local/bin/bsnes - cp data/bsnes.png /usr/local/share/icons/bsnes.png - chmod 775 /usr/local/bin/bsnes /usr/local/share/icons/bsnes.png - -###################### -### implicit rules ### -###################### - -%.$(OBJ): $< - $(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS)) - $(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS)) - $(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS)) - -######################### -### platform-specific ### -######################### -main.$(OBJ): ui/main.cpp config/* ui/* ui/video/* ui/audio/* ui/input/* \ -ui/lui/* ui/lui/loader/* ui/lui/settings/* \ -ui/win/* ui/win/settings/* ui/win/debugger/* - -bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc -bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o - -############# -### libco ### -############# -libco_x86.$(OBJ) : lib/libco_x86.asm lib/* -libco_x86_64.$(OBJ): lib/libco_x86_64.asm lib/* - -############# -### libui ### -############# -libui_gtk.$(OBJ): lib/libui_gtk.cpp lib/* -libui_win.$(OBJ): lib/libui_win.cpp lib/* - -################# -### libraries ### -################# -libstring.$(OBJ): lib/libstring.cpp lib/* - -################# -### utilities ### -################# -reader.$(OBJ): reader/reader.cpp reader/* -cart.$(OBJ) : cart/cart.cpp cart/* -cheat.$(OBJ) : cheat/cheat.cpp cheat/* - -############## -### memory ### -############## -memory.$(OBJ) : memory/memory.cpp memory/* -bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/* -smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/* - -########### -### cpu ### -########### -cpu.$(OBJ) : cpu/cpu.cpp cpu/* -scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/* - -########### -### smp ### -########### -smp.$(OBJ) : smp/smp.cpp smp/* -ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/* - -########### -### dsp ### -########### -adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/* -bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/* - -########### -### ppu ### -########### -ppu.$(OBJ) : ppu/ppu.cpp ppu/* -bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/* - -############ -### snes ### -############ -snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/* - -##################### -### special chips ### -##################### -bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/* -superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/* -srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/* -sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/* -cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/* -dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/* -dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/* -dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/* -dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/* -obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/* -st010.$(OBJ) : chip/st010/st010.cpp chip/st010/* - -############ -### zlib ### -############ -adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/* -compress.$(OBJ): reader/zlib/compress.c reader/zlib/* -crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/* -deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/* -gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/* -inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/* -inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/* -inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/* -ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/* -trees.$(OBJ) : reader/zlib/trees.c reader/zlib/* -unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/* -zip.$(OBJ) : reader/zlib/zip.c reader/zlib/* -zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/* - -########### -### jma ### -########### -jma.$(OBJ) : reader/jma/jma.cpp reader/jma/* -jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/* -lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/* -7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/* -iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/* -inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/* -lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/* -winout.$(OBJ) : reader/jma/winout.cpp reader/jma/* - -#################### -### misc targets ### -#################### -clean: - -@$(RM) *.$(OBJ) - -@$(RM) *.res - -@$(RM) *.pgd - -@$(RM) *.pgc - -@$(RM) *.ilk - -@$(RM) *.pdb - -@$(RM) *.manifest - -help: - @echo "Usage: $(MAKE) PLATFORM=platform [options]" - @echo "" - @echo "Available platform targets:" - @echo " x-gcc-lui - Linux / BSD (i386) (requires nasm)" - @echo " x-gcc-lui-x64 - Linux / BSD (amd64) (requires yasm)" - @echo " win-mingw-lui - Windows (i386) (requires nasm)" - @echo " win-visualc-lui - Windows (i386) (requires nasm)" - @echo "" - @echo "Available options:" - @echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)" - @echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)" - @echo "" - @echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true" - @echo "" +###################### +### bsnes makefile ### +###################### + +ifeq ($(PLATFORM),) +null_: help +endif + +################################## +### platform-specific settings ### +################################## + +PREFIX = /usr/local + +ifeq ($(PLATFORM),x-gcc-x86) +OS = unix +CC = gcc +CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU `pkg-config --cflags gtk+-2.0` +AS = yasm +ASFLAGS = -f elf +LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao +LIBCO = libco.x86 +MIU = miu.gtk +VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ) +endif + +ifeq ($(PLATFORM),x-gcc-x86-64) +OS = unix +CC = gcc +CFLAGS = -O3 -fomit-frame-pointer -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86_64 -DUI_MIU `pkg-config --cflags gtk+-2.0` +AS = yasm +ASFLAGS = -f elf64 +LIBS = `pkg-config --libs gtk+-2.0` -lXv -lao +LIBCO = libco.x86-64 +MIU = miu.gtk +VAI = video.xv.$(OBJ) video.gtk.$(OBJ) audio.ao.$(OBJ) input.x.$(OBJ) +endif + +ifeq ($(PLATFORM),win-mingw-x86) +OS = win +CC = mingw32-gcc +CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_MIU +AS = nasm +ASFLAGS = -f win32 -DWIN +LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32 +LIBCO = libco.x86 +MIU = miu.win +VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ) +endif + +ifeq ($(PLATFORM),win-visualc-x86) +OS = win +CC = cl +CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_MIU +AS = nasm +ASFLAGS = -f win32 -DWIN +LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib +LIBCO = libco.x86 +MIU = miu.win +VAI = video.direct3d.$(OBJ) video.directdraw.$(OBJ) video.gdi.$(OBJ) audio.directsound.$(OBJ) input.directinput.$(OBJ) +endif + +##################################### +### compiler / assembler switches ### +##################################### + +ifeq ($(CC),gcc) +OUT = -obsnes +CPP = g++ +OBJ = o +CARGS = -c $< -o $@ +DEFINE = -D +endif + +ifeq ($(CC),mingw32-gcc) +OUT = -obsnes +CPP = mingw32-g++ +OBJ = o +CARGS = -c $< -o $@ +DEFINE = -D +endif + +ifeq ($(CC),cl) +OUT = /Febsnes +CPP = cl +OBJ = obj +CARGS = /c $< /Fo$@ +DEFINE = /D +endif + +ifeq ($(AS),nasm) +ASARGS = $< -o $@ +endif + +ifeq ($(AS),yasm) +ASARGS = $< -o $@ +endif + +################### +### OS switches ### +################### + +ifeq ($(OS),unix) +RM = rm -f +endif + +ifeq ($(OS),win) +OUT := $(OUT).exe +RM = del +endif + +#################################### +### main target and dependencies ### +#################################### + +OBJECTS = main.$(OBJ) $(LIBCO).$(OBJ) $(MIU).$(OBJ) $(VAI) bstring.$(OBJ) \ + reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) memory.$(OBJ) smemory.$(OBJ) \ + cpu.$(OBJ) scpu.$(OBJ) smp.$(OBJ) ssmp.$(OBJ) bdsp.$(OBJ) ppu.$(OBJ) \ + bppu.$(OBJ) snes.$(OBJ) bsx.$(OBJ) superfx.$(OBJ) srtc.$(OBJ) \ + sdd1.$(OBJ) cx4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) dsp3.$(OBJ) dsp4.$(OBJ) \ + obc1.$(OBJ) st010.$(OBJ) + +ifeq ($(GZIP_SUPPORT),true) + OBJECTS += adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) \ + gzio.$(OBJ) inffast.$(OBJ) inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) \ + trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ) + CFLAGS += $(DEFINE)GZIP_SUPPORT +endif + +ifeq ($(JMA_SUPPORT),true) + OBJECTS += jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) \ + iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ) + CFLAGS += $(DEFINE)JMA_SUPPORT +endif + +ifeq ($(OS),win) + ifeq ($(CC),cl) + OBJECTS += bsnes.res + endif + ifeq ($(CC),mingw32-gcc) + OBJECTS += bsnesrc.o + endif +endif + +all: $(OBJECTS) + $(CPP) $(OUT) $(CFLAGS) $(OBJECTS) $(LIBS) $(LINK) + +###################### +### implicit rules ### +###################### + +%.$(OBJ): $< + $(if $(filter %.asm,$<),$(AS) $(ASFLAGS) $(ASARGS)) + $(if $(filter %.s,$<),$(AS) $(ASFLAGS) $(ASARGS)) + $(if $(filter %.c,$<),$(CC) $(CFLAGS) $(CARGS)) + $(if $(filter %.cpp,$<),$(CPP) $(CFLAGS) $(CARGS)) + +############ +### main ### +############ + +main.$(OBJ): ui/main.cpp config/* \ +ui/* ui/vai/* \ +ui/miu/* ui/miu/loader/* ui/miu/settings/* + +bsnes.res: ui/bsnes.rc ; rc /r /fobsnes.res ui/bsnes.rc +bsnesrc.o: ui/bsnes.rc ; windres -I data ui/bsnes.rc bsnesrc.o + +########## +### ui ### +########## + +video.direct3d.$(OBJ) : ui/vai/video/video.direct3d.cpp ui/vai/video/* +video.directdraw.$(OBJ) : ui/vai/video/video.directdraw.cpp ui/vai/video/* +video.gdi.$(OBJ) : ui/vai/video/video.gdi.cpp ui/vai/video/* +video.gtk.$(OBJ) : ui/vai/video/video.gtk.cpp ui/vai/video/* +video.xv.$(OBJ) : ui/vai/video/video.xv.cpp ui/vai/video/* +audio.ao.$(OBJ) : ui/vai/audio/audio.ao.cpp ui/vai/audio/* +audio.directsound.$(OBJ): ui/vai/audio/audio.directsound.cpp ui/vai/audio/* +input.directinput.$(OBJ): ui/vai/input/input.directinput.cpp ui/vai/input/* +input.x.$(OBJ) : ui/vai/input/input.x.cpp ui/vai/input/* + +############# +### libco ### +############# + +libco.x86.$(OBJ) : lib/libco/libco.x86.asm lib/libco/* +libco.x86-64.$(OBJ): lib/libco/libco.x86-64.asm lib/libco/* +libco.pcc.$(OBJ) : lib/libco/libco.ppc.s lib/libco/* +libco.ppc64.$(OBJ) : lib/libco/libco.ppc64.s lib/libco/* + +########### +### miu ### +########### + +miu.gtk.$(OBJ): lib/miu.gtk/miu.gtk.cpp lib/miu.gtk/* +miu.win.$(OBJ): lib/miu.win/miu.win.cpp lib/miu.win/* + +################# +### libraries ### +################# + +bstring.$(OBJ): lib/bstring.cpp lib/* + +################# +### utilities ### +################# + +reader.$(OBJ): reader/reader.cpp reader/* +cart.$(OBJ) : cart/cart.cpp cart/* +cheat.$(OBJ) : cheat/cheat.cpp cheat/* + +############## +### memory ### +############## + +memory.$(OBJ) : memory/memory.cpp memory/* +bmemory.$(OBJ): memory/bmemory/bmemory.cpp memory/bmemory/* memory/bmemory/mapper/* +smemory.$(OBJ): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/* + +########### +### cpu ### +########### + +cpu.$(OBJ) : cpu/cpu.cpp cpu/* +scpu.$(OBJ): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/* + +########### +### smp ### +########### + +smp.$(OBJ) : smp/smp.cpp smp/* +ssmp.$(OBJ): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/* + +########### +### dsp ### +########### + +adsp.$(OBJ): dsp/adsp/adsp.cpp dsp/adsp/* +bdsp.$(OBJ): dsp/bdsp/bdsp.cpp dsp/bdsp/* + +########### +### ppu ### +########### + +ppu.$(OBJ) : ppu/ppu.cpp ppu/* +bppu.$(OBJ): ppu/bppu/bppu.cpp ppu/bppu/* + +############ +### snes ### +############ + +snes.$(OBJ): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/* + +##################### +### special chips ### +##################### + +bsx.$(OBJ) : chip/bsx/bsx.cpp chip/bsx/* +superfx.$(OBJ): chip/superfx/superfx.cpp chip/superfx/* chip/superfx/core/* chip/superfx/memory/* +srtc.$(OBJ) : chip/srtc/srtc.cpp chip/srtc/* +sdd1.$(OBJ) : chip/sdd1/sdd1.cpp chip/sdd1/* +cx4.$(OBJ) : chip/cx4/cx4.cpp chip/cx4/* +dsp1.$(OBJ) : chip/dsp1/dsp1.cpp chip/dsp1/* +dsp2.$(OBJ) : chip/dsp2/dsp2.cpp chip/dsp2/* +dsp3.$(OBJ) : chip/dsp3/dsp3.cpp chip/dsp3/* +dsp4.$(OBJ) : chip/dsp4/dsp4.cpp chip/dsp4/* +obc1.$(OBJ) : chip/obc1/obc1.cpp chip/obc1/* +st010.$(OBJ) : chip/st010/st010.cpp chip/st010/* + +############ +### zlib ### +############ + +adler32.$(OBJ) : reader/zlib/adler32.c reader/zlib/* +compress.$(OBJ): reader/zlib/compress.c reader/zlib/* +crc32.$(OBJ) : reader/zlib/crc32.c reader/zlib/* +deflate.$(OBJ) : reader/zlib/deflate.c reader/zlib/* +gzio.$(OBJ) : reader/zlib/gzio.c reader/zlib/* +inffast.$(OBJ) : reader/zlib/inffast.c reader/zlib/* +inflate.$(OBJ) : reader/zlib/inflate.c reader/zlib/* +inftrees.$(OBJ): reader/zlib/inftrees.c reader/zlib/* +ioapi.$(OBJ) : reader/zlib/ioapi.c reader/zlib/* +trees.$(OBJ) : reader/zlib/trees.c reader/zlib/* +unzip.$(OBJ) : reader/zlib/unzip.c reader/zlib/* +zip.$(OBJ) : reader/zlib/zip.c reader/zlib/* +zutil.$(OBJ) : reader/zlib/zutil.c reader/zlib/* + +########### +### jma ### +########### + +jma.$(OBJ) : reader/jma/jma.cpp reader/jma/* +jcrc32.$(OBJ) : reader/jma/jcrc32.cpp reader/jma/* +lzmadec.$(OBJ): reader/jma/lzmadec.cpp reader/jma/* +7zlzma.$(OBJ) : reader/jma/7zlzma.cpp reader/jma/* +iiostrm.$(OBJ): reader/jma/iiostrm.cpp reader/jma/* +inbyte.$(OBJ) : reader/jma/inbyte.cpp reader/jma/* +lzma.$(OBJ) : reader/jma/lzma.cpp reader/jma/* +winout.$(OBJ) : reader/jma/winout.cpp reader/jma/* + +#################### +### misc targets ### +#################### + +install: + install -m 775 bsnes $(PREFIX)/bin/bsnes + install -m 775 data/bsnes.png $(PREFIX)/share/icons/bsnes.png + +clean: + -@$(RM) *.$(OBJ) + -@$(RM) *.res + -@$(RM) *.pgd + -@$(RM) *.pgc + -@$(RM) *.ilk + -@$(RM) *.pdb + -@$(RM) *.manifest + +help: + @echo "Usage: $(MAKE) PLATFORM=platform [options]" + @echo "" + @echo "Available platform targets:" + @echo " x-gcc-x86 - Linux / BSD (x86) (requires yasm)" + @echo " x-gcc-x86-64 - Linux / BSD (x86-64) (requires yasm)" + @echo " win-mingw-x86 - Windows (x86) (requires nasm)" + @echo " win-visualc-x86 - Windows (x86) (requires nasm)" + @echo "" + @echo "Available options:" + @echo " GZIP_SUPPORT=[true|false] - Enable ZIP / GZ support (default=false)" + @echo " JMA_SUPPORT=[true|false] - Enable JMA support (default=false)" + @echo "" + @echo "Example: $(MAKE) PLATFORM=x-gcc-lui GZIP_SUPPORT=true" + @echo "" diff --git a/src/base.h b/src/base.h index 75ba8073..0d5bf36f 100644 --- a/src/base.h +++ b/src/base.h @@ -1,53 +1,54 @@ -#define BSNES_VERSION "0.026" -#define BSNES_TITLE "bsnes v" BSNES_VERSION - -#define BUSCORE sBus -#define CPUCORE sCPU -#define SMPCORE sSMP -#define DSPCORE bDSP -#define PPUCORE bPPU - -//#define FAVOR_ACCURACY -#define FAVOR_SPEED - -//game genie + pro action replay code support (~1-3% speed hit) -#define CHEAT_SYSTEM - -#if defined(PROCESSOR_X86) - #define ARCH_LSB - #include "lib/libco_x86.h" -#elif defined(PROCESSOR_X86_64) - #define ARCH_LSB - #include "lib/libco_x86_64.h" -#elif defined(PROCESSOR_G5) - #define ARCH_MSB -#else - #error "unsupported processor" -#endif - -#include "lib/libbase.h" -#include "lib/libfunction.h" -#include "lib/libarray.h" -#include "lib/libvector.h" -#include "lib/libstring.h" -#include "lib/libconfig.h" - -//platform-specific global functions -void alert(const char*, ...); -void dprintf(const char*, ...); -void dprintf(uint, const char*, ...); - -namespace source { - enum { - none = 0, - debug, - cpu, - ppu, - smp, - dsp, - bus, - }; -}; - -//various class interfaces -#include "interface.h" +#define BSNES_VERSION "0.027" +#define BSNES_TITLE "bsnes v" BSNES_VERSION + +#define BUSCORE sBus +#define CPUCORE sCPU +#define SMPCORE sSMP +#define DSPCORE bDSP +#define PPUCORE bPPU + +//FAVOR_ACCURACY calculates RTO during frameskip, whereas FAVOR_SPEED does not +//frameskip offers near-zero speedup if RTO is calculated +//accuracy is not affected by this define when frameskipping is off + +//#define FAVOR_ACCURACY +#define FAVOR_SPEED + +//game genie + pro action replay code support (~1-3% speed hit) +#define CHEAT_SYSTEM + +#if defined(PROCESSOR_X86) || defined(PROCESSOR_X86_64) + #define ARCH_LSB +#elif defined(PROCESSOR_PPC) || defined(PROCESSOR_PPC64) + #define ARCH_MSB +#else //guess + #define ARCH_LSB +#endif + +#include "lib/libco.h" +#include "lib/bbase.h" +#include "lib/bfunction.h" +#include "lib/barray.h" +#include "lib/bvector.h" +#include "lib/bkeymap.h" +#include "lib/bstring.h" +#include "lib/bconfig.h" + +//platform-specific global functions +void alert(const char*, ...); +void dprintf(const char*, ...); +void dprintf(uint, const char*, ...); + +namespace source { + enum { + none = 0, + debug, + cpu, + ppu, + smp, + dsp, + bus, + }; +}; + +#include "interface.h" diff --git a/src/cart/cart.cpp b/src/cart/cart.cpp index 0898bb79..8ad84b62 100644 --- a/src/cart/cart.cpp +++ b/src/cart/cart.cpp @@ -82,6 +82,14 @@ void Cartridge::load_end() { memory::stBrom.write_protect(true); memory::stBram.write_protect(false); +char fn[PATH_MAX]; + strcpy(fn, cart.fn); + modify_extension(fn, "cht"); + if(fexists(fn)) { + cheat.clear(); + cheat.load(fn); + } + cart.loaded = true; bus.load_cart(); } @@ -106,6 +114,14 @@ bool Cartridge::unload() { safe_free(stB.rom); safe_free(stB.ram); +char fn[PATH_MAX]; + strcpy(fn, cart.fn); + modify_extension(fn, "cht"); + if(cheat.count() > 0 || fexists(fn)) { + cheat.save(fn); + cheat.clear(); + } + cart.loaded = false; return true; } diff --git a/src/cart/cart_file.cpp b/src/cart/cart_file.cpp index e637e9a1..ac1158ce 100644 --- a/src/cart/cart_file.cpp +++ b/src/cart/cart_file.cpp @@ -29,7 +29,7 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) { //override path with user-specified folder, if one was defined if(config::path.save != "") { - stringarray part; + lstring part; split(part, "/", savefn); string fn = config::path.save(); if(strend(fn, "/") == false) strcat(fn, "/"); @@ -38,7 +38,7 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) { //resolve relative path, if found if(strbegin(fn, "./") == true) { - strltrim(fn, "./"); + ltrim(fn, "./"); strcpy(savefn, config::path.base); strcat(savefn, fn); } @@ -50,53 +50,50 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) { bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) { dprintf("* Loading \"%s\"...", fn); - if(fexists(fn) == false) { - return false; - } + if(fexists(fn) == false) return false; switch(Reader::detect(fn)) { + default: + case Reader::RF_NORMAL: { + FileReader ff(fn); + if(!ff.ready()) { + alert("Error loading image file (%s)!", fn); + return false; + } + size = ff.size(); + data = ff.read(); + } break; - case Reader::RF_NORMAL: { - FileReader ff(fn); - if(!ff.ready()) { - alert("Error loading image file (%s)!", fn); - return false; - } - size = ff.size(); - data = ff.read(); - } break; + #ifdef GZIP_SUPPORT + case Reader::RF_GZ: { + GZReader gf(fn); + if(!gf.ready()) { + alert("Error loading image file (%s)!", fn); + return false; + } + size = gf.size(); + data = gf.read(); + } break; -#ifdef GZIP_SUPPORT - case Reader::RF_GZ: { - GZReader gf(fn); - if(!gf.ready()) { - alert("Error loading image file (%s)!", fn); - return false; - } - size = gf.size(); - data = gf.read(); - } break; - - case Reader::RF_ZIP: { - ZipReader zf(fn); - size = zf.size(); - data = zf.read(); - } break; -#endif - -#ifdef JMA_SUPPORT - case Reader::RF_JMA: { - try { - JMAReader jf(fn); - size = jf.size(); - data = jf.read(); - } catch(JMA::jma_errors jma_error) { - alert("Error loading image file (%s)!", fn); - return false; - } - } break; -#endif + case Reader::RF_ZIP: { + ZipReader zf(fn); + size = zf.size(); + data = zf.read(); + } break; + #endif + #ifdef JMA_SUPPORT + case Reader::RF_JMA: { + try { + JMAReader jf(fn); + size = jf.size(); + data = jf.read(); + } catch(JMA::jma_errors jma_error) { + alert("Error loading image file (%s)!", fn); + return false; + } + } break; + #endif } return true; diff --git a/src/cc.bat b/src/cc.bat index a1dc3907..19a5664a 100644 --- a/src/cc.bat +++ b/src/cc.bat @@ -1,6 +1,6 @@ -@make -r PLATFORM=win-mingw-lui -::@make -r PLATFORM=win-mingw-lui GZIP_SUPPORT=true JMA_SUPPORT=true -::@make -r PLATFORM=win-visualc-lui -::@make -r PLATFORM=win-visualc-lui GZIP_SUPPORT=true JMA_SUPPORT=true +@make -r PLATFORM=win-mingw-x86 +::@make -r PLATFORM=win-mingw-x86 GZIP_SUPPORT=true JMA_SUPPORT=true +::@make -r PLATFORM=win-visualc-x86 +::@make -r PLATFORM=win-visualc-x86 GZIP_SUPPORT=true JMA_SUPPORT=true @move bsnes.exe ../bsnes.exe>nul @pause \ No newline at end of file diff --git a/src/cc.sh b/src/cc.sh index b38b88fc..02258c8d 100644 --- a/src/cc.sh +++ b/src/cc.sh @@ -1,3 +1 @@ -#!/bin/sh -make PLATFORM=x-gcc-lui -#make PLATFORM=x-gcc-lui GZIP_SUPPORT=true JMA_SUPPORT=true +make PLATFORM=x-gcc-x86 diff --git a/src/cheat/cheat.cpp b/src/cheat/cheat.cpp index 8726c684..a177b38e 100644 --- a/src/cheat/cheat.cpp +++ b/src/cheat/cheat.cpp @@ -10,17 +10,17 @@ Cheat cheat; *****/ bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) { -stringarray t, part; +string t, part; strcpy(t, str); - strlower(t); - if(strlen(t) == 8 || (strlen(t) == 9 && strptr(t)[6] == ':')) { + strlower(t()); + if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) { type = CT_PRO_ACTION_REPLAY; replace(t, ":", ""); uint32 r = strhex(t); addr = r >> 8; data = r & 0xff; return true; - } else if(strlen(t) == 9 && strptr(t)[4] == '-') { + } else if(strlen(t) == 9 && t()[4] == '-') { type = CT_GAME_GENIE; replace(t, "-", ""); strtr(t, "df4709156bc8a23e", "0123456789abcdef"); @@ -269,51 +269,40 @@ void Cheat::disable(uint32 n) { * cheat file manipulation routines *****/ +/* file format: */ +/* nnnn-nnnn = status, "description" \r\n */ +/* ... */ + bool Cheat::load(const char *fn) { -FileReader rf(fn); - if(!rf.ready())return false; - -uint8 *raw_data = rf.read(); -stringarray data, line; - raw_data[rf.size()] = 0; - strcpy(data, (char*)raw_data); - safe_free(raw_data); +string data; + if(!fread(data, fn)) return false; replace(data, "\r\n", "\n"); + qreplace(data, "=", ","); + qreplace(data, " ", ""); +lstring line; split(line, "\n", data); for(int i = 0; i < ::count(line); i++) { - stringarray part; - uint8 en = *(strptr(line[i])); - if(en == '+') { - strltrim(line[i], "+"); - } else if(en == '-') { - strltrim(line[i], "-"); - } else { - continue; - } - qreplace(line[i], " ", ""); - qsplit(part, ",", line[i]); - if(::count(part) != 2)continue; - strunquote(part[1]); - add(en == '+', strptr(part[0]), strptr(part[1])); + lstring part; + split(part, ",", line[i]); + if(::count(part) != 3) continue; + trim(part[2], "\""); + add(part[1] == "enabled", part[0](), part[2]()); } return true; } bool Cheat::save(const char *fn) { -FileWriter wf(fn); - if(!wf.ready())return false; - -string data; -char t[4096]; - strcpy(data, ""); +FILE *fp = fopen(fn, "wb"); + if(!fp) return false; for(int i = 0; i < cheat_count; i++) { - sprintf(t, "%c%s, \"%s\"\r\n", index[i].enabled ? '+' : '-', index[i].code, index[i].desc); - strcat(data, t); + fprintf(fp, "%9s = %8s, \"%s\"\r\n", + index[i].code, + index[i].enabled ? "enabled" : "disabled", + index[i].desc); } - - wf.write((uint8*)strptr(data), strlen(data)); + fclose(fp); return true; } @@ -323,12 +312,12 @@ char t[4096]; void Cheat::clear() { cheat_enabled = false; - cheat_count = 0; + cheat_count = 0; memset(mask, 0, 0x200000); - for(int i = 0; i < CHEAT_LIMIT + 1; i++) { + for(int i = 0; i <= CHEAT_LIMIT; i++) { index[i].enabled = false; - index[i].addr = 0x000000; - index[i].data = 0x00; + index[i].addr = 0x000000; + index[i].data = 0x00; strcpy(index[i].code, ""); strcpy(index[i].desc, ""); } diff --git a/src/clean.bat b/src/clean.bat index 83ce6cfa..80cc34cc 100644 --- a/src/clean.bat +++ b/src/clean.bat @@ -1,2 +1,2 @@ -@make PLATFORM=win-mingw-lui clean -::@make PLATFORM=win-visualc-lui clean +@make PLATFORM=win-mingw-x86 clean +::@make PLATFORM=win-visualc-x86 clean diff --git a/src/clean.sh b/src/clean.sh index 0b82ddb6..0709a319 100644 --- a/src/clean.sh +++ b/src/clean.sh @@ -1,2 +1 @@ -#!/bin/sh -make PLATFORM=x-gcc-lui clean \ No newline at end of file +make PLATFORM=x-gcc-x86 clean diff --git a/src/config/config.cpp b/src/config/config.cpp index d322d2e7..dea6cd8b 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -15,14 +15,14 @@ string path(req_path); if(!strend(path, "/")) { strcat(path, "/"); } if(strbegin(path, "./")) { - strltrim(path, "./"); + ltrim(path(), "./"); string temp; strcpy(temp, config::path.base); strcat(temp, path); strcpy(path, temp); } -stringarray part; +lstring part; split(part, "/", file); strcat(path, part[count(part) - 1]); return path; diff --git a/src/configure b/src/configure deleted file mode 100644 index d3b8d0c4..00000000 --- a/src/configure +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -echo "Warning: bsnes does not use a configure script" -echo "To compile bsnes, use make ..." -echo "" -make #prints make usage instructions diff --git a/src/interface.h b/src/interface.h index a1ffaf81..8041270a 100644 --- a/src/interface.h +++ b/src/interface.h @@ -1,36 +1,37 @@ -#include "memory/memory.h" -#include "memory/smemory/smemory.h" - -#include "cpu/cpu.h" -#include "cpu/scpu/scpu.h" - -#include "smp/smp.h" -#include "smp/ssmp/ssmp.h" - -#include "dsp/dsp.h" -//#include "dsp/adsp/adsp.h" -#include "dsp/bdsp/bdsp.h" - -#include "ppu/ppu.h" -#include "ppu/bppu/bppu.h" - -#include "snes/snes.h" -#include "chip/chip.h" - -#include "reader/reader.h" -#include "cart/cart.h" -#include "cheat/cheat.h" -#include "config/config.h" - -#ifdef INTERFACE_MAIN - #include "config/config.cpp" - #define extern -#endif - -extern BUSCORE bus; -extern CPUCORE cpu; -extern SMPCORE smp; -extern DSPCORE dsp; -extern PPUCORE ppu; - -#undef extern +#include "reader/reader.h" +#include "cheat/cheat.h" +#include "config/config.h" + +#include "memory/memory.h" +#include "memory/smemory/smemory.h" + +#include "cart/cart.h" + +#include "cpu/cpu.h" +#include "cpu/scpu/scpu.h" + +#include "smp/smp.h" +#include "smp/ssmp/ssmp.h" + +#include "dsp/dsp.h" +//#include "dsp/adsp/adsp.h" +#include "dsp/bdsp/bdsp.h" + +#include "ppu/ppu.h" +#include "ppu/bppu/bppu.h" + +#include "snes/snes.h" +#include "chip/chip.h" + +#ifdef INTERFACE_MAIN + #include "config/config.cpp" + #define extern +#endif + +extern BUSCORE bus; +extern CPUCORE cpu; +extern SMPCORE smp; +extern DSPCORE dsp; +extern PPUCORE ppu; + +#undef extern diff --git a/src/lib/barray.h b/src/lib/barray.h new file mode 100644 index 00000000..62cf32ad --- /dev/null +++ b/src/lib/barray.h @@ -0,0 +1,87 @@ +/* + barray : version 0.10 ~byuu (2007-11-29) + license: public domain +*/ + +#ifndef BARRAY_H +#define BARRAY_H + +template class array { +protected: + T *pool; + uint poolsize, buffersize; + + uint findsize(uint size) { + if(size <= 0x100) return 0x100; + if(size <= 0x400) return 0x400; + if(size <= 0x1000) return 0x1000; + if(size <= 0x4000) return 0x4000; + if(size <= 0x10000) return 0x10000; + if(size <= 0x40000) return 0x40000; + if(size <= 0x100000) return 0x100000; + + return (size + 0x100000) & ~0xfffff; + } + +public: + uint size() { return buffersize; } + uint capacity() { return poolsize; } + + void reset() { + safe_free(pool); + poolsize = 0; + buffersize = 0; + } + + void reserve(uint size) { + if(size == poolsize) return; + if(size < poolsize) buffersize = size; + + pool = (T*)realloc(pool, sizeof(T) * size); + poolsize = size; + } + + T* get(uint size = 0) { + if(size > buffersize) resize(size); + if(size > buffersize) throw "array[] out of bounds"; + return pool; + } + + void add(T data) { + operator[](buffersize) = data; + } + + void clear() { + memset(pool, 0, sizeof(T) * buffersize); + } + + void resize(uint size) { + reserve(findsize(size)); + buffersize = size; + } + + array() { + pool = 0; + poolsize = 0; + buffersize = 0; + } + + ~array() { reset(); } + + array& operator=(array &source) { + safe_free(pool); + buffersize = source.buffersize; + poolsize = source.poolsize; + pool = (T*)realloc(pool, sizeof(T) * poolsize); //allocate entire pool size ... + memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects + return *this; + } + + inline T& operator[](int index) { + if(index >= buffersize) resize(index + 1); + if(index >= buffersize) throw "array[] out of bounds"; + return pool[index]; + } +}; + +#endif //ifndef BARRAY_H diff --git a/src/lib/libbase.h b/src/lib/bbase.h similarity index 92% rename from src/lib/libbase.h rename to src/lib/bbase.h index 163e68dd..5908a98b 100644 --- a/src/lib/libbase.h +++ b/src/lib/bbase.h @@ -1,10 +1,10 @@ /* - libbase : version 0.11a ~byuu (2007-10-14) + bbase : version 0.12 ~byuu (2007-12-12) license: public domain */ -#ifndef LIBBASE_H -#define LIBBASE_H +#ifndef BBASE_H +#define BBASE_H #include #include @@ -109,7 +109,27 @@ struct passwd *userinfo = getpwuid(getuid()); #endif /***** - * templates + * template classes + *****/ + +class noncopyable { +protected: + noncopyable() {} + ~noncopyable() {} + +private: + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); +}; + +template +struct base_from_member { + T value; + base_from_member(T value_) : value(value_) {} +}; + +/***** + * template functions *****/ template inline void safe_free(T &handle) { @@ -324,4 +344,4 @@ uint32 crc32 = ~0; return ~crc32; } -#endif +#endif //ifndef BBASE_H diff --git a/src/lib/libconfig.h b/src/lib/bconfig.h similarity index 64% rename from src/lib/libconfig.h rename to src/lib/bconfig.h index 52ba1b64..926c25b6 100644 --- a/src/lib/libconfig.h +++ b/src/lib/bconfig.h @@ -1,54 +1,52 @@ /* - libconfig : version 0.15 ~byuu (2007-11-01) + bconfig : version 0.16 ~byuu (2007-11-28) license: public domain */ -#ifndef LIBCONFIG_H -#define LIBCONFIG_H +#ifndef BCONFIG_H +#define BCONFIG_H -#include "libbase.h" -#include "libarray.h" -#include "libstring.h" +#include "bbase.h" +#include "barray.h" +#include "bstring.h" class Setting; -class Config { public: -array list; -uint list_count; +class Config { +public: + array list; + uint list_count; -string data; -stringarray line, part, subpart; + string data; + lstring line, part, subpart; bool load(const char *fn); bool save(const char *fn); - bool load(const string &fn) { return load(strptr(fn)); } - bool save(const string &fn) { return save(strptr(fn)); } void add(Setting *setting) { list[list_count++] = setting; } Config() : list_count(0) {} }; -class Setting { public: -uint type; -char *name, *desc, *def; - -enum Type { - Integer, - String, -}; +class Setting { +public: + enum Type { + Integer, + String, + } type; + char *name, *desc, *def; virtual void set(const char *input) = 0; virtual void get(string &output) = 0; }; -class IntegerSetting : public Setting { public: -uint ifmt, data, idef; - -enum Format { - Boolean, - Decimal, - Hex, -}; +class IntegerSetting : public Setting { +public: + enum Format { + Boolean, + Decimal, + Hex, + } ifmt; + uint data, idef; void set(const char *input) { if(ifmt == Boolean) { data = !strcmp(input, "true"); } @@ -57,9 +55,10 @@ enum Format { } void get(string &output) { - if(ifmt == Boolean) { sprintf(output, "%s", data ? "true" : "false"); } - if(ifmt == Decimal) { sprintf(output, "%d", data); } - if(ifmt == Hex) { sprintf(output, "0x%x", data); } + output.reserve(64); + if(ifmt == Boolean) { sprintf(output(), "%s", data ? "true" : "false"); } + if(ifmt == Decimal) { sprintf(output(), "%d", data); } + if(ifmt == Hex) { sprintf(output(), "0x%x", data); } } uint operator()() { return data; } @@ -72,7 +71,7 @@ enum Format { template bool operator<=(T x) { return (T(data) <= x); } template bool operator< (T x) { return (T(data) < x); } - IntegerSetting(Config *parent, const char *r_name, const char *r_desc, uint r_format, uint r_data) { + IntegerSetting(Config *parent, const char *r_name, const char *r_desc, Format r_format, uint r_data) { type = Setting::Integer; name = strdup(r_name); desc = strdup(r_desc); @@ -80,25 +79,26 @@ enum Format { data = idef = r_data; string t; get(t); - def = strdup(strptr(t)); + def = strdup(t); if(parent) { parent->add(this); } } ~IntegerSetting() { - free(name); - free(desc); - free(def); + safe_free(name); + safe_free(desc); + safe_free(def); } }; -class StringSetting : public Setting { public: -string data; - void set(const char *input) { data = input; strunquote(data); } - void get(string &output) { output = data; strquote(output); } +class StringSetting : public Setting { +public: + string data; + void set(const char *input) { data = input; trim(data(), "\""); } + void get(string &output) { output = string() << "\"" << data << "\""; } - const char* operator()() { return strptr(data); } - operator const char*() { return strptr(data); } + char* operator()() { return data(); } + operator const char*() { return data; } StringSetting &operator=(const char *x) { data = x; return *this; } bool operator==(const char *x) { return !strcmp(data, x); } bool operator!=(const char *x) { return strcmp(data, x); } @@ -110,15 +110,15 @@ string data; data = r_data; string t; get(t); - def = strdup(strptr(t)); + def = strdup(t); if(parent) { parent->add(this); } } ~StringSetting() { - free(name); - free(desc); - free(def); + safe_free(name); + safe_free(desc); + safe_free(def); } }; @@ -145,12 +145,12 @@ char *buffer = (char*)malloc(fsize + 1); for(int i = 0; i < count(line); i++) { if(strlen(line[i]) == 0)continue; - if(*strptr(line[i]) == '#')continue; + if(*line[i] == '#')continue; qsplit(part, "=", line[i]); for(int l = 0; l < list_count; l++) { if(!strcmp(list[l]->name, part[0])) { - list[l]->set(strptr(part[1])); + list[l]->set(part[1]); break; } } @@ -170,16 +170,16 @@ string t; replace(data, "\r\n", "\n"); split(line, "\n", data); for(int l = 0; l < count(line); l++) { - if(line[l] != "") { fprintf(fp, "# %s\r\n", strptr(line[l])); } + if(line[l] != "") { fprintf(fp, "# %s\r\n", line[l]()); } } fprintf(fp, "# (default = %s)\r\n", list[i]->def); list[i]->get(t); - fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, strptr(t)); + fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, t()); } fclose(fp); return true; } -#endif +#endif //ifndef BCONFIG_H diff --git a/src/lib/libfunction.h b/src/lib/bfunction.h similarity index 86% rename from src/lib/libfunction.h rename to src/lib/bfunction.h index 068ce597..ce602a8d 100644 --- a/src/lib/libfunction.h +++ b/src/lib/bfunction.h @@ -1,10 +1,10 @@ /* - libfunction : version 0.06 ~byuu (2007-10-14) + bfunction : version 0.06 ~byuu (2007-10-14) license: public domain */ -#ifndef LIBFUNCTION_H -#define LIBFUNCTION_H +#ifndef BFUNCTION_H +#define BFUNCTION_H //prologue @@ -19,7 +19,7 @@ template class function; #define PL #define CL -#include "libfunction.h" +#include "bfunction.h" //parameters = 1 @@ -28,7 +28,7 @@ template class function; #define PL P1 p1 #define CL p1 -#include "libfunction.h" +#include "bfunction.h" //parameters = 2 @@ -37,7 +37,7 @@ template class function; #define PL P1 p1, P2 p2 #define CL p1, p2 -#include "libfunction.h" +#include "bfunction.h" //parameters = 3 @@ -46,7 +46,7 @@ template class function; #define PL P1 p1, P2 p2, P3 p3 #define CL p1, p2, p3 -#include "libfunction.h" +#include "bfunction.h" //parameters = 4 @@ -55,7 +55,7 @@ template class function; #define PL P1 p1, P2 p2, P3 p3, P4 p4 #define CL p1, p2, p3, p4 -#include "libfunction.h" +#include "bfunction.h" //parameters = 5 @@ -64,7 +64,7 @@ template class function; #define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 #define CL p1, p2, p3, p4, p5 -#include "libfunction.h" +#include "bfunction.h" //parameters = 6 @@ -73,7 +73,7 @@ template class function; #define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 #define CL p1, p2, p3, p4, p5, p6 -#include "libfunction.h" +#include "bfunction.h" //parameters = 7 @@ -82,7 +82,7 @@ template class function; #define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 #define CL p1, p2, p3, p4, p5, p6, p7 -#include "libfunction.h" +#include "bfunction.h" //parameters = 8 @@ -91,13 +91,14 @@ template class function; #define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8 #define CL p1, p2, p3, p4, p5, p6, p7, p8 -#include "libfunction.h" +#include "bfunction.h" //epilogue #undef TN +#define BFUNCTION_TH -#else //defined(LIBFUNCTION_H) +#elif !defined(BFUNCTION_TH) //function implementation template class diff --git a/src/lib/libkeymap.h b/src/lib/bkeymap.h similarity index 94% rename from src/lib/libkeymap.h rename to src/lib/bkeymap.h index a0e0109c..b11af5a5 100644 --- a/src/lib/libkeymap.h +++ b/src/lib/bkeymap.h @@ -1,9 +1,10 @@ /* - libkeymap : version 0.02 ~byuu (2007-05-28) + bkeymap : version 0.02 ~byuu (2007-05-28) + license: public domain */ -#ifndef LIBKEYMAP_H -#define LIBKEYMAP_H +#ifndef BKEYMAP_H +#define BKEYMAP_H namespace keymap { @@ -306,4 +307,4 @@ static const char *find(uint16 key) { }; -#endif +#endif //ifndef BKEYMAP_H diff --git a/src/lib/bstring.cpp b/src/lib/bstring.cpp new file mode 100644 index 00000000..65fc66f8 --- /dev/null +++ b/src/lib/bstring.cpp @@ -0,0 +1,95 @@ +#include "bstring.h" + +#include "bstring/bstring.list.cpp" +#include "bstring/bstring.strl.cpp" +#include "bstring/bstring.math.cpp" +#include "bstring/bstring.misc.cpp" +#include "bstring/bstring.replace.cpp" +#include "bstring/bstring.split.cpp" +#include "bstring/bstring.trim.cpp" + +void string::reserve(uint size_) { + if(size_ > size) { + size = size_; + data = (char*)realloc(data, size + 1); + data[size] = 0; + } +} + +//implicit-conversion, read-only +string::operator const char*() const { + return data; +} + +//explicit-coversion, read-write +char* string::operator()() { + return data; +} + +//index, read-write +char& string::operator[](const uint index) { + reserve(index); + return data[index]; +} + +string& string::operator=(const int num) { + itoa(*this, num); + return *this; +} + +string& string::operator=(const char *str) { + strcpy(*this, str); + return *this; +} + +string& string::operator=(const string &str) { + strcpy(*this, str); + return *this; +} + +string& string::operator<<(const int num) { +string temp(num); + strcat(*this, temp); + return *this; +} + +string& string::operator<<(const char *str) { + strcat(*this, str); + return *this; +} + +bool string::operator==(const char *str) { return strcmp(data, str) == 0; } +bool string::operator!=(const char *str) { return strcmp(data, str) != 0; } +bool string::operator< (const char *str) { return strcmp(data, str) < 0; } +bool string::operator<=(const char *str) { return strcmp(data, str) <= 0; } +bool string::operator> (const char *str) { return strcmp(data, str) > 0; } +bool string::operator>=(const char *str) { return strcmp(data, str) >= 0; } + +string::string() { + size = 64; + data = (char*)malloc(size + 1); + *data = 0; +} + +string::string(const int source) { + size = 64; + data = (char*)malloc(size + 1); + *data = 0; + itoa(*this, source); +} + +string::string(const char *source) { + size = strlen(source); + data = (char*)malloc(size + 1); + strcpy(data, source); +} + +string::string(const string &source) { + size = strlen(source); + data = (char*)malloc(size + 1); + strcpy(data, source); +} + +string::~string() { + safe_free(data); +} diff --git a/src/lib/bstring.h b/src/lib/bstring.h new file mode 100644 index 00000000..64602e4d --- /dev/null +++ b/src/lib/bstring.h @@ -0,0 +1,99 @@ +/* + bstring : version 0.01a ~byuu (2007-12-12) + license: public domain +*/ + +#ifndef BSTRING_H +#define BSTRING_H + +#include "bbase.h" +#include "bvector.h" + +class string; +typedef linear_vector lstring; + +uint count(lstring&); +int find(lstring &str, const char *key); + +uint strlcpy(char *dest, const char *src, uint length); +uint strlcat(char *dest, const char *src, uint length); +uint strlcpy(string &dest, const char *src, uint length); +uint strlcat(string &dest, const char *src, uint length); + +int strmath(const char *str); + +char chrlower(char c); +char chrupper(char c); +int stricmp(const char *dest, const char *src); +void strcpy(string &dest, const char *src); +void strcat(string &dest, const char *src); +string substr(string &dest, const char *src, uint start = 0, uint length = 0); +char* strlower(char *str); +char* strupper(char *str); +string& strlower(string &str); +string& strupper(string &str); +int strpos(const char *str, const char *key); +int qstrpos(const char *str, const char *key); +char* strtr(char *dest, const char *before, const char *after); +string& strtr(string &dest, const char *before, const char *after); +bool strbegin(const char *str, const char *key); +bool stribegin(const char *str, const char *key); +bool strend(const char *str, const char *key); +bool striend(const char *str, const char *key); + +uint strhex(const char *str); +uint strdec(const char *str); +uint strbin(const char *str); + +string& utoa(string &str, uint num); +string& itoa(string &str, uint num); +string& htoa(string &str, uint num); +string& btoa(string &str, uint num); + +bool fread(string &str, const char *filename); + +string& replace(string &str, const char *key, const char *token); +string& qreplace(string &str, const char *key, const char *token); + +void split(lstring &dest, const char *key, const char *src); +void qsplit(lstring &dest, const char *key, const char *src); + +char* ltrim(char *str, const char *key = " "); +char* rtrim(char *str, const char *key = " "); +char* trim(char *str, const char *key = " "); +string& ltrim(string &str, const char *key = " "); +string& rtrim(string &str, const char *key = " "); +string& trim(string &str, const char *key = " "); + +class string { +public: + char *data; + uint size; + + void reserve(uint size_); + + operator const char*() const; + char* operator()(); + char& operator[](const uint); + + string& operator=(const int num); + string& operator=(const char *str); + string& operator=(const string &str); + string& operator<<(const int num); + string& operator<<(const char *str); + + bool operator==(const char *str); + bool operator!=(const char *str); + bool operator< (const char *str); + bool operator<=(const char *str); + bool operator> (const char *str); + bool operator>=(const char *str); + + string(); + string(const int num); + string(const char *source); + string(const string &source); + ~string(); +}; + +#endif //ifndef BSTRING_H diff --git a/src/lib/bstring/bstring.list.cpp b/src/lib/bstring/bstring.list.cpp new file mode 100644 index 00000000..c924ead0 --- /dev/null +++ b/src/lib/bstring/bstring.list.cpp @@ -0,0 +1,14 @@ +#ifdef BSTRING_H + +uint count(lstring &str) { + return str.size(); +} + +int find(lstring &str, const char *key) { + for(uint i = 0; i < count(str); i++) { + if(str[i] == key) return i; + } + return -1; +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/libstring_math.cpp b/src/lib/bstring/bstring.math.cpp similarity index 64% rename from src/lib/libstring_math.cpp rename to src/lib/bstring/bstring.math.cpp index a641d7f0..8f08c5f1 100644 --- a/src/lib/libstring_math.cpp +++ b/src/lib/bstring/bstring.math.cpp @@ -1,121 +1,194 @@ -/* - c-style Math Evaluator v1.0 (07/03/2006) - Algorithm: Recursive Descent Processor - Written by: gladius - Optimized by: gladius and byuu - Public Domain -*/ - -#define maxlevel 12 -int strmath_rdp(const char *&s, int level = 0) { - if(level == maxlevel) { - if(*s == '(') { - int result = strmath_rdp(++s, 0); - s++; - return result; - } else if(*s == '+') { - return +strmath_rdp(++s, maxlevel); - } else if(*s == '-') { - return -strmath_rdp(++s, maxlevel); - } else if(*s == '!') { - return !strmath_rdp(++s, maxlevel); - } else if(*s == '~') { - return ~strmath_rdp(++s, maxlevel); - } else if(*s >= '0' && *s <= '9') { - int num, len; - sscanf(s, "%d%n", &num, &len); - s += len; - return num; - } - } - -int lhs = strmath_rdp(s, level + 1); - while(*s) { - int a = *s; - int b = *s ? *(s + 1) : 0; - switch(level) { - case 0: - if(a == '?')break; - return lhs; - case 1: - if(a == '|' && b == '|') { s++; break; } - return lhs; - case 2: - if(a == '^' && b == '^') { s++; break; } - return lhs; - case 3: - if(a == '&' && b == '&') { s++; break; } - return lhs; - case 4: - if(a == '|' && b != '|')break; - return lhs; - case 5: - if(a == '^' && b != '^')break; - return lhs; - case 6: - if(a == '&' && b != '&')break; - return lhs; - case 7: - if(a == '=' && b == '=') { s++; break; } - if(a == '!' && b == '=') { s++; break; } - return lhs; - case 8: - if(a == '<' && b == '=') { s++; break; } - if(a == '>' && b == '=') { s++; break; } - if(a == '<')break; - if(a == '>')break; - return lhs; - case 9: - if(a == '<' && b == '<') { s++; break; } - if(a == '>' && b == '>') { s++; break; } - return lhs; - case 10: - if(a == '+')break; - if(a == '-')break; - return lhs; - case 11: - if(a == '*')break; - if(a == '/')break; - if(a == '%')break; - return lhs; - } - if(a == '?') { - int tr = strmath_rdp(++s, level); - int fr = strmath_rdp(++s, level); - lhs = (lhs) ? tr : fr; - } else { - int rhs = strmath_rdp(++s, level + 1); - if (a == '|' && b == '|') lhs = (lhs || rhs); - else if(a == '^' && b == '^') lhs = (!lhs != !rhs); - else if(a == '&' && b == '&') lhs = (lhs && rhs); - else if(a == '|' && b != '|') lhs |= rhs; - else if(a == '^' && b != '^') lhs ^= rhs; - else if(a == '&' && b != '&') lhs &= rhs; - else if(a == '=' && b == '=') lhs = (lhs == rhs); - else if(a == '!' && b == '=') lhs = (lhs != rhs); - else if(a == '<' && b == '=') lhs = (lhs <= rhs); - else if(a == '>' && b == '=') lhs = (lhs >= rhs); - else if(a == '<' && b != '<') lhs = (lhs < rhs); - else if(a == '>' && b != '>') lhs = (lhs > rhs); - else if(a == '<' && b == '<') lhs <<= rhs; - else if(a == '>' && b == '>') lhs >>= rhs; - else if(a == '+') lhs += rhs; - else if(a == '-') lhs -= rhs; - else if(a == '*') lhs *= rhs; - else if(a == '/') lhs /= rhs; - else if(a == '%') lhs %= rhs; - } - } - return lhs; -} -#undef maxlevel - -int strmath(const char *str) { - return strmath_rdp(str); -} - -#ifdef __LIBSTRING -int strmath(const string &str) { - return strmath(strptr(str)); -} -#endif +#ifdef BSTRING_H + +/* + recursive descent math processor v0.02 (2007-11-28) + authors: gladius, byuu + license: public domain +*/ + +void strmath_space(const char *&s) { + while(*s == ' ' || *s == '\t')s++; +} + +int strmath_number(const char *&s) { +int result = 0; +enum type { dec, hex, bin, oct }; +type t = dec; + if(*s == '0') { + s++; + if(*s == 'x' || *s == 'X') { s++; t = hex; } + else if(*s == 'b' || *s == 'B') { s++; t = bin; } + else { t = oct; } + } else if(*s == '$') { + s++; + t = hex; + } else if(*s == '%') { + s++; + t = bin; + } + + switch(t) { + + case dec: { + while(true) { + char x = *s; + if(x >= '0' && x <= '9')x = x - '0'; + else break; + result = result * 10 + x; + s++; + } + } break; + + case hex: { + while(true) { + char x = *s; + if(x >= '0' && x <= '9')x = x - '0'; + else if(x >= 'a' && x <= 'f')x = x - 'a' + 0x0a; + else if(x >= 'A' && x <= 'F')x = x - 'A' + 0x0a; + else break; + result = result * 16 + x; + s++; + } + } break; + + case bin: { + while(true) { + char x = *s; + if(x >= '0' && x <= '1')x = x - '0'; + else break; + result = result * 2 + x; + s++; + } + } break; + + case oct: { + while(true) { + char x = *s; + if(x >= '0' && x <= '7')x = x - '0'; + else break; + result = result * 8 + x; + s++; + } + } break; + + } + + return result; + +int num, len; + sscanf(s, "%d%n", &num, &len); + s += len; + return num; +} + +#define maxlevel 12 +int strmath_rdp(const char *&s, int level = 0) { + strmath_space(s); + + if(level == maxlevel) { + if(*s == '(') { + int result = strmath_rdp(++s, 0); + s++; + return result; + } else if(*s == '+') { + return +strmath_rdp(++s, maxlevel); + } else if(*s == '-') { + return -strmath_rdp(++s, maxlevel); + } else if(*s == '!') { + return !strmath_rdp(++s, maxlevel); + } else if(*s == '~') { + return ~strmath_rdp(++s, maxlevel); + } else if((*s >= '0' && *s <= '9') || *s == '$' || *s == '%') { + return strmath_number(s); + } else { + return 0; //error + } + } + +int lhs = strmath_rdp(s, level + 1); + strmath_space(s); + while(*s) { + int a = *s; + int b = *s ? *(s + 1) : 0; + switch(level) { + case 0: + if(a == '?')break; + return lhs; + case 1: + if(a == '|' && b == '|') { s++; break; } + return lhs; + case 2: + if(a == '^' && b == '^') { s++; break; } + return lhs; + case 3: + if(a == '&' && b == '&') { s++; break; } + return lhs; + case 4: + if(a == '|' && b != '|')break; + return lhs; + case 5: + if(a == '^' && b != '^')break; + return lhs; + case 6: + if(a == '&' && b != '&')break; + return lhs; + case 7: + if(a == '=' && b == '=') { s++; break; } + if(a == '!' && b == '=') { s++; break; } + return lhs; + case 8: + if(a == '<' && b == '=') { s++; break; } + if(a == '>' && b == '=') { s++; break; } + if(a == '<')break; + if(a == '>')break; + return lhs; + case 9: + if(a == '<' && b == '<') { s++; break; } + if(a == '>' && b == '>') { s++; break; } + return lhs; + case 10: + if(a == '+')break; + if(a == '-')break; + return lhs; + case 11: + if(a == '*')break; + if(a == '/')break; + if(a == '%')break; + return lhs; + } + if(a == '?') { + int tr = strmath_rdp(++s, level); + int fr = strmath_rdp(++s, level); + lhs = (lhs) ? tr : fr; + } else { + int rhs = strmath_rdp(++s, level + 1); + if (a == '|' && b == '|') lhs = (lhs || rhs); + else if(a == '^' && b == '^') lhs = (!lhs != !rhs); + else if(a == '&' && b == '&') lhs = (lhs && rhs); + else if(a == '|' && b != '|') lhs |= rhs; + else if(a == '^' && b != '^') lhs ^= rhs; + else if(a == '&' && b != '&') lhs &= rhs; + else if(a == '=' && b == '=') lhs = (lhs == rhs); + else if(a == '!' && b == '=') lhs = (lhs != rhs); + else if(a == '<' && b == '=') lhs = (lhs <= rhs); + else if(a == '>' && b == '=') lhs = (lhs >= rhs); + else if(a == '<' && b != '<') lhs = (lhs < rhs); + else if(a == '>' && b != '>') lhs = (lhs > rhs); + else if(a == '<' && b == '<') lhs <<= rhs; + else if(a == '>' && b == '>') lhs >>= rhs; + else if(a == '+') lhs += rhs; + else if(a == '-') lhs -= rhs; + else if(a == '*') lhs *= rhs; + else if(a == '/') lhs /= rhs; + else if(a == '%') lhs %= rhs; + } + } + return lhs; +} +#undef maxlevel + +int strmath(const char *str) { + return strmath_rdp(str); +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/bstring/bstring.misc.cpp b/src/lib/bstring/bstring.misc.cpp new file mode 100644 index 00000000..8bf85fad --- /dev/null +++ b/src/lib/bstring/bstring.misc.cpp @@ -0,0 +1,277 @@ +#ifdef BSTRING_H + +char chrlower(char c) { + return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; +} + +char chrupper(char c) { + return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; +} + +int stricmp(const char *dest, const char *src) { + while(*dest) { + if(chrlower(*dest) != chrlower(*src)) break; + dest++; + src++; + } + + return (int)chrlower(*dest) - (int)chrlower(*src); +} + +void strcpy(string &dest, const char *src) { +int srclen = strlen(src); + dest.reserve(srclen); + strcpy(dest(), src); +} + +void strcat(string &dest, const char *src) { +int srclen = strlen(src); +int destlen = strlen(dest); + dest.reserve(srclen + destlen); + strcat(dest(), src); +} + +string substr(const char *src, uint start, uint length) { +string dest; + if(length == 0) { + //copy entire string + strcpy(dest, src + start); + } else { + //copy partial string + strlcpy(dest, src + start, length + 1); + } + return dest; +} + +char* strlower(char *str) { +uint i = 0; + while(str[i]) { + str[i] = chrlower(str[i]); + i++; + } + return str; +} + +char* strupper(char *str) { +uint i = 0; + while(str[i]) { + str[i] = chrupper(str[i]); + i++; + } + return str; +} + +string& strlower(string &str) { + strlower(str()); + return str; +} + +string& strupper(string &str) { + strupper(str()); + return str; +} + +int strpos(const char *str, const char *key) { +int ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl) return -1; + for(int i = 0; i <= ssl - ksl; i++) { + if(!memcmp(str + i, key, ksl)) { + return i; + } + } + return -1; +} + +int qstrpos(const char *str, const char *key) { +int ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl) return -1; + for(int i = 0; i <= ssl - ksl;) { + uint8 x = str[i]; + if(x == '\"' || x == '\'') { + uint8 z = i++; + while(str[i] != x && i < ssl) i++; + if(i >= ssl) i = z; + } + if(!memcmp(str + i, key, ksl)) { + return i; + } else { + i++; + } + } + return -1; +} + +char* strtr(char *dest, const char *before, const char *after) { +int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); + if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace + for(int i = 0; i < sl; i++) { + for(int l = 0; l < bsl; l++) { + if(dest[i] == before[l]) { + dest[i] = after[l]; + break; + } + } + } + return dest; +} + +string& strtr(string &dest, const char *before, const char *after) { + strtr(dest(), before, after); + return dest; +} + +bool strbegin(const char *str, const char *key) { +int i, ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return false; + return (!memcmp(str, key, ksl)); +} + +bool stribegin(const char *str, const char *key) { +int ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return false; + for(int i = 0; i < ksl; i++) { + if(str[i] >= 'A' && str[i] <= 'Z') { + if(str[i] != key[i] && str[i]+0x20 != key[i])return false; + } else if(str[i] >= 'a' && str[i] <= 'z') { + if(str[i] != key[i] && str[i]-0x20 != key[i])return false; + } else { + if(str[i] != key[i])return false; + } + } + return true; +} + +bool strend(const char *str, const char *key) { +int ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return false; + return (!memcmp(str + ssl - ksl, key, ksl)); +} + +bool striend(const char *str, const char *key) { +int ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl)return false; + for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { + if(str[i] >= 'A' && str[i] <= 'Z') { + if(str[i] != key[z] && str[i]+0x20 != key[z])return false; + } else if(str[i] >= 'a' && str[i] <= 'z') { + if(str[i] != key[z] && str[i]-0x20 != key[z])return false; + } else { + if(str[i] != key[z])return false; + } + } + return true; +} + +uint strhex(const char *str) { +uint r = 0, m = 0; +int i = 0, ssl = strlen(str); +uint8 x; +bool negate = (str[0] == '-'); + if(negate)i++; + for(; i < ssl; i++) { + if(str[i] >= '0' && str[i] <= '9'); + else if(str[i] >= 'A' && str[i] <= 'F'); + else if(str[i] >= 'a' && str[i] <= 'f'); + else break; + } + for(--i; i >= 0; i--, m += 4) { + x = str[i]; + if(x >= '0' && x <= '9')x -= '0'; + else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a; + else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a; + else break; + r |= x << m; + } + return !negate ? r : (uint)-r; +} + +uint strdec(const char *str) { +uint m = 1; +int i = 0, r = 0, ssl = strlen(str); +uint8 x; +bool negate = (str[0] == '-'); + if(negate)i++; + for(; i < ssl; i++) { + if(str[i] >= '0' && str[i] <= '9'); + else break; + } + for(--i; i >= 0; i--, m *= 10) { + x = str[i]; + if(x >= '0' && x <= '9')x -= '0'; + else break; + r += x * m; + } + return !negate ? r : (uint)-r; +} + +uint strbin(const char *str) { +uint r = 0, m = 0; +int i = 0, ssl = strlen(str); +uint8 x; +bool negate = (str[0] == '-'); + if(negate)i++; + for(; i < ssl; i++) { + if(str[i] == '0' || str[i] == '1'); + else break; + } + for(--i; i >= 0; i--, m++) { + x = str[i]; + if(str[i] == '0' || str[i] == '1')x -= '0'; + else break; + r |= x << m; + } + return !negate ? r : (uint)-r; +} + +string &utoa(string &str, uint num) { + str.reserve(16); + sprintf(str(), "%u", num); + return str; +} + +string &itoa(string &str, uint num) { + str.reserve(16); + sprintf(str(), "%d", num); + return str; +} + +string &htoa(string &str, uint num) { + str.reserve(16); + sprintf(str(), "%x", num); + return str; +} + +string &btoa(string &str, uint num) { + str.reserve(64); + +char *pstr = str(); +uint mask = 0x80000000; + while(mask && (num & mask) == 0)mask >>= 1; + while(mask > 1) { + *pstr++ = (num & mask) ? '1' : '0'; + mask >>= 1; + } + *pstr++ = (num & mask) ? '1' : '0'; + *pstr = 0; + + return str; +} + +bool fread(string &str, const char *filename) { + strcpy(str, ""); + +FILE *fp = fopen(filename, "rb"); + if(!fp)return false; + +uint size = fsize(fp); +char *fdata = (char*)malloc(size + 1); + fread(fdata, 1, size, fp); + fclose(fp); + fdata[size] = 0; + strcpy(str, fdata); + free(fdata); + + return true; +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/libstring_replace.cpp b/src/lib/bstring/bstring.replace.cpp similarity index 68% rename from src/lib/libstring_replace.cpp rename to src/lib/bstring/bstring.replace.cpp index f5a3c032..3c35c78c 100644 --- a/src/lib/libstring_replace.cpp +++ b/src/lib/bstring/bstring.replace.cpp @@ -1,86 +1,88 @@ -string &replace(string &str, const char *key, const char *token) { -int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); -uint replace_count = 0, size = ssl; -char *data; - if(ksl > ssl)return str; - if(tsl > ksl) { //the new string may be longer than the old string... - for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... - if(!memcmp(str.s + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - str.reserve(size); - } - data = (char*)malloc(size + 1); - for(i = z = 0; i < ssl;) { - if(i <= ssl - ksl) { - if(!memcmp(str.s + i, key, ksl)) { - memcpy(data + z, token, tsl); - z += tsl; - i += ksl; - } else data[z++] = str.s[i++]; - } else data[z++] = str.s[i++]; - } - data[z] = 0; - strcpy(str, data); - free(data); - return str; -} -string &replace(string &str, const char *key, const string &token) { return replace(str, key, strptr(token)); } - -string &qreplace(string &str, const char *key, const char *token) { -int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); -uint replace_count = 0, size = ssl; -uint8 x; -char *data; - if(ksl > ssl)return str; - if(tsl > ksl) { - for(i = 0; i <= ssl - ksl;) { - x = str.s[i]; - if(x == '\"' || x == '\'') { - l = i; - i++; - while(str.s[i++] != x) { - if(i == ssl) { - i = l; - break; - } - } - } - if(!memcmp(str.s + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - str.reserve(size); - } - data = (char*)malloc(size + 1); - for(i = z = 0; i < ssl;) { - x = str.s[i]; - if(x == '\"' || x == '\'') { - l = i++; - while(str.s[i] != x && i < ssl)i++; - if(i >= ssl)i = l; - else { - memcpy(data + z, str.s + l, i - l); - z += i - l; - } - } - if(i <= ssl - ksl) { - if(!memcmp(str.s + i, key, ksl)) { - memcpy(data + z, token, tsl); - z += tsl; - i += ksl; - replace_count++; - } else data[z++] = str.s[i++]; - } else data[z++] = str.s[i++]; - } - data[z] = 0; - strcpy(str, data); - free(data); - return str; -} -string &qreplace(string &str, const char *key, const string &token) { return qreplace(str, key, strptr(token)); } +#ifdef BSTRING_H + +string &replace(string &str, const char *key, const char *token) { +int i, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); +uint replace_count = 0, size = ssl; +char *data; + if(ksl > ssl)return str; + if(tsl > ksl) { //the new string may be longer than the old string... + for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... + if(!memcmp(str() + i, key, ksl)) { + replace_count++; + i += ksl; + } else i++; + } + size = ssl + ((tsl - ksl) * replace_count); + str.reserve(size); + } + data = (char*)malloc(size + 1); + for(i = z = 0; i < ssl;) { + if(i <= ssl - ksl) { + if(!memcmp(str() + i, key, ksl)) { + memcpy(data + z, token, tsl); + z += tsl; + i += ksl; + } else data[z++] = str()[i++]; + } else data[z++] = str()[i++]; + } + data[z] = 0; + strcpy(str, data); + free(data); + return str; +} + +string &qreplace(string &str, const char *key, const char *token) { +int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = strlen(str); +uint replace_count = 0, size = ssl; +uint8 x; +char *data; + if(ksl > ssl)return str; + if(tsl > ksl) { + for(i = 0; i <= ssl - ksl;) { + x = str()[i]; + if(x == '\"' || x == '\'') { + l = i; + i++; + while(str()[i++] != x) { + if(i == ssl) { + i = l; + break; + } + } + } + if(!memcmp(str() + i, key, ksl)) { + replace_count++; + i += ksl; + } else i++; + } + size = ssl + ((tsl - ksl) * replace_count); + str.reserve(size); + } + data = (char*)malloc(size + 1); + for(i = z = 0; i < ssl;) { + x = str()[i]; + if(x == '\"' || x == '\'') { + l = i++; + while(str()[i] != x && i < ssl)i++; + if(i >= ssl)i = l; + else { + memcpy(data + z, str() + l, i - l); + z += i - l; + } + } + if(i <= ssl - ksl) { + if(!memcmp(str() + i, key, ksl)) { + memcpy(data + z, token, tsl); + z += tsl; + i += ksl; + replace_count++; + } else data[z++] = str()[i++]; + } else data[z++] = str()[i++]; + } + data[z] = 0; + strcpy(str, data); + free(data); + return str; +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/libstring_split.cpp b/src/lib/bstring/bstring.split.cpp similarity index 67% rename from src/lib/libstring_split.cpp rename to src/lib/bstring/bstring.split.cpp index 8fb29dc7..24436f77 100644 --- a/src/lib/libstring_split.cpp +++ b/src/lib/bstring/bstring.split.cpp @@ -1,37 +1,39 @@ -void split(stringarray &dest, const char *key, const char *src) { - dest.reset(); - -int ssl = strlen(src), ksl = strlen(key); -int lp = 0, split_count = 0; - for(int i = 0; i <= ssl - ksl;) { - if(!memcmp(src + i, key, ksl)) { - strlcpy(dest[split_count++], src + lp, i - lp + 1); - i += ksl; - lp = i; - } else i++; - } - strcpy(dest[split_count++], src + lp); -} -void split(stringarray &dest, const char *key, const string &src) { split(dest, key, strptr(src)); } - -void qsplit(stringarray &dest, const char *key, const char *src) { - dest.reset(); - -int z, ssl = strlen(src), ksl = strlen(key); -int lp = 0, split_count = 0; - for(int i = 0; i <= ssl - ksl;) { - uint8 x = src[i]; - if(x == '\"' || x == '\'') { - z = i++; - while(src[i] != x && i < ssl)i++; - if(i >= ssl)i = z; - } - if(!memcmp(src + i, key, ksl)) { - strlcpy(dest[split_count++], src + lp, i - lp + 1); - i += ksl; - lp = i; - } else i++; - } - strcpy(dest[split_count++], src + lp); -} -void qsplit(stringarray &dest, const char *key, const string &src) { qsplit(dest, key, strptr(src)); } +#ifdef BSTRING_H + +void split(lstring &dest, const char *key, const char *src) { + dest.reset(); + +int ssl = strlen(src), ksl = strlen(key); +int lp = 0, split_count = 0; + for(int i = 0; i <= ssl - ksl;) { + if(!memcmp(src + i, key, ksl)) { + strlcpy(dest[split_count++], src + lp, i - lp + 1); + i += ksl; + lp = i; + } else i++; + } + strcpy(dest[split_count++], src + lp); +} + +void qsplit(lstring &dest, const char *key, const char *src) { + dest.reset(); + +int z, ssl = strlen(src), ksl = strlen(key); +int lp = 0, split_count = 0; + for(int i = 0; i <= ssl - ksl;) { + uint8 x = src[i]; + if(x == '\"' || x == '\'') { + z = i++; + while(src[i] != x && i < ssl)i++; + if(i >= ssl)i = z; + } + if(!memcmp(src + i, key, ksl)) { + strlcpy(dest[split_count++], src + lp, i - lp + 1); + i += ksl; + lp = i; + } else i++; + } + strcpy(dest[split_count++], src + lp); +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/bstring/bstring.strl.cpp b/src/lib/bstring/bstring.strl.cpp new file mode 100644 index 00000000..33c4e1f8 --- /dev/null +++ b/src/lib/bstring/bstring.strl.cpp @@ -0,0 +1,31 @@ +#ifdef BSTRING_H + +uint strlcpy(char *dest, const char *src, uint length) { +uint srclen = strlen(src); + length--; + if(length > srclen) length = srclen; + memcpy(dest, src, length); + dest[length] = 0; + return srclen; +} + +uint strlcat(char *dest, const char *src, uint length) { +uint destlen = strlen(dest), srclen = strlen(src); + length--; + if(length > destlen + srclen) length = destlen + srclen; + memcpy(dest + destlen, src, length - destlen); + dest[length] = 0; + return destlen + srclen; +} + +uint strlcpy(string &dest, const char *src, uint length) { + dest.reserve(length); + return strlcpy(dest(), src, length); +} + +uint strlcat(string &dest, const char *src, uint length) { + dest.reserve(length); + return strlcat(dest(), src, length); +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/bstring/bstring.trim.cpp b/src/lib/bstring/bstring.trim.cpp new file mode 100644 index 00000000..59ba3c1a --- /dev/null +++ b/src/lib/bstring/bstring.trim.cpp @@ -0,0 +1,39 @@ +#ifdef BSTRING_H + +char* ltrim(char *str, const char *key) { + if(!key || !*key) return str; + while(strbegin(str, key)) { + string temp = str; + strcpy(str, temp() + strlen(key)); + } + return str; +} + +char* rtrim(char *str, const char *key) { + if(!key || !*key) return str; + while(strend(str, key)) { + str[strlen(str) - strlen(key)] = 0; + } + return str; +} + +char* trim(char *str, const char *key) { + return ltrim(rtrim(str, key), key); +} + +string& ltrim(string &str, const char *key) { + ltrim(str(), key); + return str; +} + +string& rtrim(string &str, const char *key) { + rtrim(str(), key); + return str; +} + +string& trim(string &str, const char *key) { + trim(str(), key); + return str; +} + +#endif //ifdef BSTRING_H diff --git a/src/lib/libvector.h b/src/lib/bvector.h similarity index 94% rename from src/lib/libvector.h rename to src/lib/bvector.h index d4ac97c6..c4a67ba2 100644 --- a/src/lib/libvector.h +++ b/src/lib/bvector.h @@ -1,5 +1,6 @@ /* - libvector : version 0.05 ~byuu (2006-12-16) + bvector : version 0.05 ~byuu (2006-12-16) + license: public domain */ /***** @@ -64,8 +65,8 @@ * and speed is less critical. *****/ -#ifndef LIBVECTOR_H -#define LIBVECTOR_H +#ifndef BVECTOR_H +#define BVECTOR_H template class linear_vector { protected: @@ -204,4 +205,4 @@ public: } }; -#endif +#endif //ifndef BVECTOR_H diff --git a/src/lib/libarray.h b/src/lib/libarray.h deleted file mode 100644 index 790a0e80..00000000 --- a/src/lib/libarray.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - libarray : version 0.09 ~byuu (2007-03-06) -*/ - -#ifndef LIBARRAY_H -#define LIBARRAY_H - -template class array { -protected: -T *pool; -uint poolsize, buffersize; - -protected: - uint findsize(uint size) { - if(size <= 0x100) { return 0x100; } - if(size <= 0x400) { return 0x400; } - if(size <= 0x1000) { return 0x1000; } - if(size <= 0x4000) { return 0x4000; } - if(size <= 0x10000) { return 0x10000; } - if(size <= 0x40000) { return 0x40000; } - if(size <= 0x100000) { return 0x100000; } - - return (size + 0x100000) & ~0xfffff; - } - -public: - uint size() { return buffersize; } - uint capacity() { return poolsize; } - - void reset() { - safe_free(pool); - poolsize = 0; - buffersize = 0; - } - - void reserve(uint size) { - if(size == poolsize)return; - - if(size < poolsize) { - buffersize = size; - } - - pool = (T*)realloc(pool, sizeof(T) * size); - poolsize = size; - } - - T *get(uint size = 0) { - if(size > buffersize)resize(size); - if(size > buffersize)throw "array[] out of bounds"; - return pool; - } - - void clear() { memset(pool, 0, sizeof(T) * buffersize); } - - void resize(uint size) { - reserve(findsize(size)); - buffersize = size; - } - - array() { - pool = 0; - poolsize = 0; - buffersize = 0; - } - - ~array() { reset(); } - - array &operator=(array &source) { - safe_free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - //allocate entire pool size ... - pool = (T*)realloc(pool, sizeof(T) * poolsize); - //... but only copy used pool objects - memcpy(pool, source.pool, sizeof(T) * buffersize); - return *this; - } - - inline T &operator[](int index) { - if(index >= buffersize)resize(index + 1); - if(index >= buffersize)throw "array[] out of bounds"; - return pool[index]; - } -}; - -#endif diff --git a/src/lib/libco.h b/src/lib/libco.h new file mode 100644 index 00000000..74cf8bc6 --- /dev/null +++ b/src/lib/libco.h @@ -0,0 +1,37 @@ +/* + libco + version: 0.11 (2007-12-11) + license: public domain +*/ + +#ifndef LIBCO_H +#define LIBCO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__i386__) + #if defined(__GNUC__) + #define calltype __attribute__((fastcall)) + #elif defined(_MSC_VER) + #define calltype __fastcall + #endif +#else + #define calltype +#endif + +typedef void* cothread_t; + +cothread_t calltype co_active(); +cothread_t calltype co_create(unsigned int heapsize, void (*coentry)()); +void calltype co_delete(cothread_t cothread); +void calltype co_switch(cothread_t cothread); + +#undef calltype + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //ifndef LIBCO_H diff --git a/src/lib/libco/libco.ppc.s b/src/lib/libco/libco.ppc.s new file mode 100644 index 00000000..d7f6b758 --- /dev/null +++ b/src/lib/libco/libco.ppc.s @@ -0,0 +1,478 @@ +;***** +;libco.ppc (2007-11-29) +;author: Vas Crabb +;license: public domain +; +;cross-platform PowerPC implementation of libco +;special thanks to byuu for writing the original version +; +;[ABI compatibility] +;- gcc; mac os x; ppc +; +;[nonvolatile registers] +;- GPR1, GPR13 - GPR31 +;- FPR14 - FPR31 +;- V20 - V31 +;- VRSAVE, CR2 - CR4 +; +;[volatile registers] +;- GPR0, GPR2 - GPR12 +;- FPR0 - FPR13 +;- V0 - V19 +;- LR, CTR, XER, CR0, CR1, CR5 - CR7 +;***** + + +;Declare some target-specific stuff + + .section __TEXT,__text,regular,pure_instructions + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .machine ppc + + +;Constants + + .cstring + .align 2 + +_sysctl_altivec: + .ascii "hw.optional.altivec\0" + + +;Declare space for variables + +.lcomm _co_environ,4,2 ;bit 0 = initialised, bit 1 = have Altivec/VMX +.lcomm _co_primary_buffer,1024,2 ;buffer (will be zeroed by loader) + + .data + .align 2 + +_co_active_context: + .long _co_primary_buffer + + + .text + .align 2 + + +;Declare exported names + +.globl _co_active +.globl _co_create +.globl _co_delete +.globl _co_switch + + +;***** +;extern "C" cothread_t co_active(); +;return = GPR3 +;***** + +_co_active: + mflr r0 ;GPR0 = return address + bcl 20,31,L_co_active$spb +L_co_active$spb: + mflr r2 ;GPR2 set for position-independance + addis r3,r2,ha16(_co_active_context-L_co_active$spb) ;get value in GPR3 + lwz r3,lo16(_co_active_context-L_co_active$spb)(r3) + mtlr r0 ;LR = return address + blr ;return + + +;***** +;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)()); +;GPR3 = heapsize +;GPR4 = coentry +;return = GPR3 +;***** + +_co_create: + mflr r0 ;GPR0 = return address + stmw r30,-8(r1) ;save GPR30 and GPR31 + stw r0,8(r1) ;save return address + stwu r1,-(2*4+16+24)(r1) ;allocate 16 bytes for locals/parameters + +;create heap space (stack + register storage) + addi r31,r3,1024-24 ;subtract space for linkage + mr r30,r4 ;GPR30 = coentry + addi r3,r3,1024 ;allocate extra memory for contextual info + bl L_malloc$stub ;GPR3 = malloc(heapsize + 1024) + add r4,r3,r31 ;GPR4 points to top-of-stack + rlwinm r5,r4,0,0,27 ;force 16-byte alignment + +;store thread entry point + registers, so that first call to co_switch will execute coentry + stw r30,8(r5) ;store entry point + addi r6,0,2+19+18*2+12*4+1 ;clear for CR, old GPR1, 19 GPRs, 18 FPRs, 12 VRs, VRSAVE + addi r0,0,0 + addi r7,0,4 ;start at 4(GPR5) + mtctr r6 +L_co_create$clear_loop: + stwx r0,r5,r7 ;clear a word + addi r7,r7,-4 ;increment pointer + bdnz L_co_create$clear_loop ;loop + stwu r5,-448(r5) ;store top of stack + +;initialize context memory heap and return + stw r5,0(r3) ;*cothread_t = stack heap pointer (GPR1) + lwz r1,0(r1) ;deallocate stack frame + lwz r8,8(r1) ;fetch return address + lmw r30,-8(r1) ;restore GPR30 and GPR31 + mtlr r8 ;return address in LR + blr ;return + + +;***** +;extern "C" void co_delete(cothread_t cothread); +;GPR3 = cothread +;***** + +_co_delete: + b L_free$stub ;free(GPR3) + + +;***** +;extern "C" void co_switch(cothread_t cothread); +;GPR3 = cothread +;***** +; +;Frame looks like: +; +;Old New Value +; 8(r1) 456(r1) Saved LR +; 4(r1) 452(r1) Saved CR +; 0(r1) 448(r1) Old GPR1 +; -4(r1) 444(r1) Saved GPR31 +; -8(r1) 440(r1) Saved GPR30 +;... ... ... +; -72(r1) 376(r1) Saved GPR14 +; -76(r1) 372(r1) Saved GPR13 +; -80(r1) 368(r1) Saved VRSAVE +; -84(r1) 364(r1) +++ +; -88(r1) 360(r1) Saved FPR31 +; -92(r1) 356(r1) +++ +; -96(r1) 352(r1) Saved FPR30 +;... ... ... +;-212(r1) 236(r1) +++ +;-216(r1) 232(r1) Saved FPR15 +;-220(r1) 228(r1) +++ +;-224(r1) 224(r1) Saved FPR14 +;-228(r1) 220(r1) +++ value +;-232(r1) 216(r1) +++ len +;-236(r1) 212(r1) +++ +;-240(r1) 208(r1) Saved VR31 +;-244(r1) 204(r1) +++ +;-248(r1) 200(r1) +++ +;-252(r1) 196(r1) +++ +;-256(r1) 192(r1) Saved VR30 +;... ... ... +;-388(r1) 60(r1) +++ +;-392(r1) 56(r1) +++ +;-396(r1) 52(r1) +++ +;-400(r1) 48(r1) Saved VR21 +;-404(r1) 44(r1) +++ +;-408(r1) 40(r1) +++ Param 5 (GPR7) +;-412(r1) 36(r1) +++ Param 4 (GPR6) +;-416(r1) 32(r1) Saved VR20 Param 3 (GPR5) +;-420(r1) 28(r1) - Param 2 (GPR4) +;-424(r1) 24(r1) - Param 1 (GPR3) +;-428(r1) 20(r1) - Reserved +;-432(r1) 16(r1) - Reserved +;-436(r1) 12(r1) - Reserved +;-440(r1) 8(r1) - New LR +;-444(r1) 4(r1) - New CR +;-448(r1) 0(r1) Saved GPR1 + + +_co_switch: + stmw r13,-76(r1) ;save preserved GPRs + stfd f14,-224(r1) ;save preserved FPRs + stfd f15,-216(r1) + stfd f16,-208(r1) + stfd f17,-200(r1) + stfd f18,-192(r1) + stfd f19,-184(r1) + stfd f20,-176(r1) + stfd f21,-168(r1) + stfd f22,-160(r1) + stfd f23,-152(r1) + stfd f24,-144(r1) + stfd f25,-136(r1) + stfd f26,-128(r1) + stfd f27,-120(r1) + stfd f28,-112(r1) + stfd f29,-104(r1) + stfd f30,-96(r1) + stfd f31,-88(r1) + mflr r0 ;save return address + stw r0,8(r1) + mfcr r2 ;save condition codes + stw r2,4(r1) + stwu r1,-448(r1) ;create stack frame (save 19 GPRs, 18 FRPs, 12 VRs, VRSAVE) + + mr r30,r3 ;save new context pointer + bcl 20,31,L_co_switch$spb ;get address of co_active_context +L_co_switch$spb: + mflr r31 + + addis r29,r31,ha16(_co_environ-L_co_switch$spb) ;get environment flags + lwz r8,lo16(_co_environ-L_co_switch$spb)(r29) + andis. r9,r8,0x8000 ;is it initialised? + bne+ L_co_switch$initialised + + addi r0,0,4 ;len = sizeof(int) + stw r0,216(r1) + addis r3,r31,ha16(_sysctl_altivec-L_co_switch$spb) ;GPR3 = "hw.optional.altivec" + addi r3,r3,lo16(_sysctl_altivec-L_co_switch$spb) + addi r4,r1,220 ;GPR4 = &value + addi r5,r1,216 ;GPR5 = &len + addi r6,0,0 ;newp = 0 + addi r7,0,0 ;newlen = 0 + bl L_sysctlbyname$stub ;call sysctlbyname + lwz r2,220(r1) ;fetch result + addis r8,0,0x8000 ;set initialised bit + cmpwi cr5,r3,0 ;assume error means not present + cmpwi cr6,r2,0 ;test result + blt- cr5,L_co_switch$store_environ + beq cr6,L_co_switch$store_environ + oris r8,r8,0x4000 ;set the flag to say we have it! +L_co_switch$store_environ: + stw r8,lo16(_co_environ-L_co_switch$spb)(r29) ;store environment flags +L_co_switch$initialised: + + andis. r10,r8,0x4000 ;do we have Altivec/VMX? + beq L_co_switch$save_no_vmx + mfspr r11,256 ;save VRSAVE + andi. r0,r11,0x0FFF ;short-circuit if it's zero + stw r11,368(r1) + beq L_co_switch$save_no_vmx + andi. r0,r11,0x0800 ;check bit 20 + addi r2,0,32 ;starting index + beq L_co_switch$save_skip_vr20 + stvx v20,r1,r2 ;save VR20 +L_co_switch$save_skip_vr20: + addi r2,r2,16 ;stride + andi. r0,r11,0x0400 ;check bit 21 + beq L_co_switch$save_skip_vr21 + stvx v21,r1,r2 ;save VR21 +L_co_switch$save_skip_vr21: + addi r2,r2,16 ;stride + andi. r0,r11,0x0200 ;check bit 22 + beq L_co_switch$save_skip_vr22 + stvx v22,r1,r2 ;save VR22 +L_co_switch$save_skip_vr22: + addi r2,r2,16 ;stride + andi. r0,r11,0x0100 ;check bit 23 + beq L_co_switch$save_skip_vr23 + stvx v23,r1,r2 ;save VR23 +L_co_switch$save_skip_vr23: + addi r2,r2,16 ;stride + andi. r0,r11,0x0080 ;check bit 24 + beq L_co_switch$save_skip_vr24 + stvx v24,r1,r2 ;save VR24 +L_co_switch$save_skip_vr24: + addi r2,r2,16 ;stride + andi. r0,r11,0x0040 ;check bit 25 + beq L_co_switch$save_skip_vr25 + stvx v25,r1,r2 ;save VR25 +L_co_switch$save_skip_vr25: + addi r2,r2,16 ;stride + andi. r0,r11,0x0020 ;check bit 26 + beq L_co_switch$save_skip_vr26 + stvx v26,r1,r2 ;save VR26 +L_co_switch$save_skip_vr26: + addi r2,r2,16 ;stride + andi. r0,r11,0x0010 ;check bit 27 + beq L_co_switch$save_skip_vr27 + stvx v27,r1,r2 ;save VR27 +L_co_switch$save_skip_vr27: + addi r2,r2,16 ;stride + andi. r0,r11,0x0008 ;check bit 28 + beq L_co_switch$save_skip_vr28 + stvx v28,r1,r2 ;save VR28 +L_co_switch$save_skip_vr28: + addi r2,r2,16 ;stride + andi. r0,r11,0x0004 ;check bit 29 + beq L_co_switch$save_skip_vr29 + stvx v29,r1,r2 ;save VR29 +L_co_switch$save_skip_vr29: + addi r2,r2,16 ;stride + andi. r0,r11,0x0002 ;check bit 30 + beq L_co_switch$save_skip_vr30 + stvx v30,r1,r2 ;save VR30 +L_co_switch$save_skip_vr30: + addi r2,r2,16 ;stride + andi. r0,r11,0x0001 ;check bit 31 + beq L_co_switch$save_skip_vr31 + stvx v31,r1,r2 ;save VR31 +L_co_switch$save_skip_vr31: +L_co_switch$save_no_vmx: + + addis r4,r31,ha16(_co_active_context-L_co_switch$spb) ;save current context + lwz r5,lo16(_co_active_context-L_co_switch$spb)(r4) + stw r30,lo16(_co_active_context-L_co_switch$spb)(r4);set new context + stw r1,0(r5) ;save current stack pointer + lwz r1,0(r30) ;get new stack pointer + + andis. r10,r8,0x4000 ;do we have Altivec/VMX? + beq L_co_switch$restore_no_vmx + lwz r11,368(r1) ;restore VRSAVE + andi. r0,r11,0x0FFF ;short-circuit if it's zero + mtspr 256,r11 + beq L_co_switch$restore_no_vmx + andi. r0,r11,0x0800 ;check bit 20 + addi r2,0,32 ;starting index + beq L_co_switch$restore_skip_vr20 + lvx v20,r1,r2 ;restore VR20 +L_co_switch$restore_skip_vr20: + addi r2,r2,16 ;stride + andi. r0,r11,0x0400 ;check bit 21 + beq L_co_switch$restore_skip_vr21 + lvx v21,r1,r2 ;restore VR21 +L_co_switch$restore_skip_vr21: + addi r2,r2,16 ;stride + andi. r0,r11,0x0200 ;check bit 22 + beq L_co_switch$restore_skip_vr22 + lvx v22,r1,r2 ;restore VR22 +L_co_switch$restore_skip_vr22: + addi r2,r2,16 ;stride + andi. r0,r11,0x0100 ;check bit 23 + beq L_co_switch$restore_skip_vr23 + lvx v23,r1,r2 ;restore VR23 +L_co_switch$restore_skip_vr23: + addi r2,r2,16 ;stride + andi. r0,r11,0x0080 ;check bit 24 + beq L_co_switch$restore_skip_vr24 + lvx v24,r1,r2 ;restore VR24 +L_co_switch$restore_skip_vr24: + addi r2,r2,16 ;stride + andi. r0,r11,0x0040 ;check bit 25 + beq L_co_switch$restore_skip_vr25 + lvx v25,r1,r2 ;restore VR25 +L_co_switch$restore_skip_vr25: + addi r2,r2,16 ;stride + andi. r0,r11,0x0020 ;check bit 26 + beq L_co_switch$restore_skip_vr26 + lvx v26,r1,r2 ;restore VR26 +L_co_switch$restore_skip_vr26: + addi r2,r2,16 ;stride + andi. r0,r11,0x0010 ;check bit 27 + beq L_co_switch$restore_skip_vr27 + lvx v27,r1,r2 ;restore VR27 +L_co_switch$restore_skip_vr27: + addi r2,r2,16 ;stride + andi. r0,r11,0x0008 ;check bit 28 + beq L_co_switch$restore_skip_vr28 + lvx v28,r1,r2 ;restore VR28 +L_co_switch$restore_skip_vr28: + addi r2,r2,16 ;stride + andi. r0,r11,0x0004 ;check bit 29 + beq L_co_switch$restore_skip_vr29 + lvx v29,r1,r2 ;restore VR29 +L_co_switch$restore_skip_vr29: + addi r2,r2,16 ;stride + andi. r0,r11,0x0002 ;check bit 30 + beq L_co_switch$restore_skip_vr30 + lvx v30,r1,r2 ;restore VR30 +L_co_switch$restore_skip_vr30: + addi r2,r2,16 ;stride + andi. r0,r11,0x0001 ;check bit 31 + beq L_co_switch$restore_skip_vr31 + lvx v31,r1,r2 ;restore VR31 +L_co_switch$restore_skip_vr31: +L_co_switch$restore_no_vmx: + + lwz r1,0(r1) ;deallocate stack frame + lwz r6,8(r1) ;return address in GPR6 + lwz r7,4(r1) ;condition codes in GPR7 + addi r0,0,0 ;make thread main crash if it returns + lmw r13,-76(r1) ;restore preserved GPRs + lfd f14,-224(r1) ;restore preserved FPRs + lfd f15,-216(r1) + lfd f16,-208(r1) + lfd f17,-200(r1) + lfd f18,-192(r1) + lfd f19,-184(r1) + lfd f20,-176(r1) + lfd f21,-168(r1) + lfd f22,-160(r1) + lfd f23,-152(r1) + lfd f24,-144(r1) + lfd f25,-136(r1) + lfd f26,-128(r1) + lfd f27,-120(r1) + lfd f28,-112(r1) + lfd f29,-104(r1) + lfd f30,-96(r1) + lfd f31,-88(r1) + mtlr r0 + mtctr r6 ;restore return address + mtcrf 32,r7 ;restore preserved condition codes + mtcrf 16,r7 + mtcrf 8,r7 + bctr ;return + + + +;Import external functions + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 5 +L_malloc$stub: + .indirect_symbol _malloc + mflr r0 + bcl 20,31,L_malloc$spb +L_malloc$spb: + mflr r11 + addis r11,r11,ha16(L_malloc$lazy_ptr-L_malloc$spb) + mtlr r0 + lwzu r12,lo16(L_malloc$lazy_ptr-L_malloc$spb)(r11) + mtctr r12 + bctr + .lazy_symbol_pointer +L_malloc$lazy_ptr: + .indirect_symbol _malloc + .long dyld_stub_binding_helper + + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 5 +L_free$stub: + .indirect_symbol _free + mflr r0 + bcl 20,31,L_free$spb +L_free$spb: + mflr r11 + addis r11,r11,ha16(L_free$lazy_ptr-L_free$spb) + mtlr r0 + lwzu r12,lo16(L_free$lazy_ptr-L_free$spb)(r11) + mtctr r12 + bctr + .lazy_symbol_pointer +L_free$lazy_ptr: + .indirect_symbol _free + .long dyld_stub_binding_helper + + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 5 +L_sysctlbyname$stub: + .indirect_symbol _sysctlbyname + mflr r0 + bcl 20,31,L_sysctlbyname$spb +L_sysctlbyname$spb: + mflr r11 + addis r11,r11,ha16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb) + mtlr r0 + lwzu r12,lo16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)(r11) + mtctr r12 + bctr + .lazy_symbol_pointer +L_sysctlbyname$lazy_ptr: + .indirect_symbol _sysctlbyname + .long dyld_stub_binding_helper + + +;This needs to be here! + + .subsections_via_symbols + diff --git a/src/lib/libco/libco.ppc64.s b/src/lib/libco/libco.ppc64.s new file mode 100644 index 00000000..2fb048d7 --- /dev/null +++ b/src/lib/libco/libco.ppc64.s @@ -0,0 +1,513 @@ +;***** +;libco.ppc64 (2007-12-05) +;author: Vas Crabb +;license: public domain +; +;cross-platform 64-bit PowerPC implementation of libco +;special thanks to byuu for writing the original version +; +;[ABI compatibility] +;- gcc; mac os x; ppc64 +; +;[nonvolatile registers] +;- GPR1, GPR13 - GPR31 +;- FPR14 - FPR31 +;- V20 - V31 +;- VRSAVE, CR2 - CR4 +; +;[volatile registers] +;- GPR0, GPR2 - GPR12 +;- FPR0 - FPR13 +;- V0 - V19 +;- LR, CTR, XER, CR0, CR1, CR5 - CR7 +;***** + + +;Declare some target-specific stuff + + .section __TEXT,__text,regular,pure_instructions + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .machine ppc64 + + +;Constants + + .cstring + .align 3 + +_sysctl_altivec: + .ascii "hw.optional.altivec\0" + + +;Declare space for variables + +.lcomm _co_environ,4,2 ;bit 0 = initialised, bit 1 = have Altivec/VMX +.lcomm _co_primary_buffer,1024,3 ;buffer (will be zeroed by loader) + + .data + .align 3 + +_co_active_context: + .quad _co_primary_buffer + + + .text + .align 2 + + +;Declare exported names + +.globl _co_active +.globl _co_create +.globl _co_delete +.globl _co_switch + + +;***** +;extern "C" cothread_t co_active(); +;return = GPR3 +;***** + +_co_active: + mflr r0 ;GPR0 = return address + bcl 20,31,L_co_active$spb +L_co_active$spb: + mflr r2 ;GPR2 set for position-independance + addis r3,r2,ha16(_co_active_context-L_co_active$spb) ;get value in GPR3 + ld r3,lo16(_co_active_context-L_co_active$spb)(r3) + mtlr r0 ;LR = return address + blr ;return + + +;***** +;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)()); +;GPR3 = heapsize +;GPR4 = coentry +;return = GPR3 +;***** + +_co_create: + mflr r0 ;GPR0 = return address + std r30,-16(r1) ;save GPR30 and GPR31 + std r31,-8(r1) + std r0,16(r1) ;save return address + stdu r1,-(2*8+16+48)(r1) ;allocate 16 bytes for locals/parameters + +;create heap space (stack + register storage) + addi r31,r3,1024-48 ;subtract space for linkage + mr r30,r4 ;GPR30 = coentry + addi r3,r3,1024 ;allocate extra memory for contextual info + bl L_malloc$stub ;GPR3 = malloc(heapsize + 1024) + add r4,r3,r31 ;GPR4 points to top-of-stack + rldicr r5,r4,0,59 ;force 16-byte alignment + +;store thread entry point + registers, so that first call to co_switch will execute coentry + std r30,16(r5) ;store entry point + addi r6,0,2+19+18+12*2+1 ;clear for CR, old GPR1, 19 GPRs, 18 FPRs, 12 VRs, VRSAVE + addi r0,0,0 + addi r7,0,8 ;start at 8(GPR5) + mtctr r6 +L_co_create$clear_loop: + stdx r0,r5,r7 ;clear a double + addi r7,r7,-8 ;increment pointer + bdnz L_co_create$clear_loop ;loop + stdu r5,-544(r5) ;store top of stack + +;initialize context memory heap and return + addis r9,0,0x8000 ;GPR13 not set (system TLS) + std r5,0(r3) ;*cothread_t = stack heap pointer (GPR1) + stw r9,8(r3) ;this is a flag word + ld r1,0(r1) ;deallocate stack frame + ld r8,16(r1) ;fetch return address + ld r30,-16(r1) ;restore GPR30 and GPR31 + ld r31,-8(r1) + mtlr r8 ;return address in LR + blr ;return + + +;***** +;extern "C" void co_delete(cothread_t cothread); +;GPR3 = cothread +;***** + +_co_delete: + b L_free$stub ;free(GPR3) + + +;***** +;extern "C" void co_switch(cothread_t cothread); +;GPR3 = cothread +;***** +; +;Frame looks like: +; +;Old New Value +; 16(r1) 560(r1) Saved LR +; 8(r1) 552(r1) Saved CR +; 0(r1) 544(r1) Old GPR1 +; -8(r1) 536(r1) Saved GPR31 +; -16(r1) 528(r1) Saved GPR30 +;... ... ... +;-144(r1) 400(r1) Saved GPR14 +;-152(r1) 392(r1) Saved GPR13 +;-160(r1) 384(r1) Saved FPR31 +;-168(r1) 376(r1) Saved FPR30 +;... ... ... +;-288(r1) 256(r1) Saved FPR15 +;-296(r1) 248(r1) Saved FPR14 +;-304(r1) 240(r1) Saved VRSAVE +;-312(r1) 232(r1) +++ value +;-320(r1) 224(r1) Saved VR31 len +;-328(r1) 216(r1) +++ +;-336(r1) 208(r1) Saved VR30 +;... ... ... +;-456(r1) 88(r1) +++ +;-464(r1) 80(r1) Saved VR22 Param 5 (GPR7) +;-472(r1) 72(r1) +++ Param 4 (GPR6) +;-480(r1) 64(r1) Saved VR21 Param 3 (GPR5) +;-488(r1) 56(r1) +++ Param 2 (GPR4) +;-496(r1) 48(r1) Saved VR20 Param 1 (GPR3) +;-504(r1) 40(r1) - Reserved +;-512(r1) 32(r1) - Reserved +;-520(r1) 24(r1) - Reserved +;-528(r1) 16(r1) - New LR +;-536(r1) 8(r1) - New CR +;-544(r1) 0(r1) Saved GPR1 + + +_co_switch: + std r13,-152(r1) ;save preserved GPRs + std r14,-144(r1) + std r15,-136(r1) + std r16,-128(r1) + std r17,-120(r1) + std r18,-112(r1) + std r19,-104(r1) + std r20,-96(r1) + std r21,-88(r1) + std r22,-80(r1) + std r23,-72(r1) + std r24,-64(r1) + std r25,-56(r1) + std r26,-48(r1) + std r27,-40(r1) + std r28,-32(r1) + std r29,-24(r1) + std r30,-16(r1) + std r31,-8(r1) + mflr r0 ;save return address + std r0,16(r1) + mfcr r2 ;save condition codes + stw r2,8(r1) + stdu r1,-544(r1) ;create stack frame (save 19 GPRs, 18 FRPs, 12 VRs, VRSAVE) + stfd f14,248(r1) ;save preserved FPRs + stfd f15,256(r1) + stfd f16,264(r1) + stfd f17,272(r1) + stfd f18,280(r1) + stfd f19,288(r1) + stfd f20,296(r1) + stfd f21,304(r1) + stfd f22,312(r1) + stfd f23,320(r1) + stfd f24,328(r1) + stfd f25,336(r1) + stfd f26,344(r1) + stfd f27,352(r1) + stfd f28,360(r1) + stfd f29,368(r1) + stfd f30,376(r1) + stfd f31,384(r1) + + mr r30,r3 ;save new context pointer + bcl 20,31,L_co_switch$spb ;get address of co_active_context +L_co_switch$spb: + mflr r31 + + addis r29,r31,ha16(_co_environ-L_co_switch$spb) ;get environment flags + lwz r8,lo16(_co_environ-L_co_switch$spb)(r29) + andis. r9,r8,0x8000 ;is it initialised? + bne+ L_co_switch$initialised + + addi r0,0,4 ;len = sizeof(int) + std r0,224(r1) + addis r3,r31,ha16(_sysctl_altivec-L_co_switch$spb) ;GPR3 = "hw.optional.altivec" + addi r3,r3,lo16(_sysctl_altivec-L_co_switch$spb) + addi r4,r1,232 ;GPR4 = &value + addi r5,r1,224 ;GPR5 = &len + addi r6,0,0 ;newp = 0 + addi r7,0,0 ;newlen = 0 + bl L_sysctlbyname$stub ;call sysctlbyname + lwz r2,232(r1) ;fetch result + addis r8,0,0x8000 ;set initialised bit + cmpdi cr5,r3,0 ;assume error means not present + cmpwi cr6,r2,0 ;test result + blt- cr5,L_co_switch$store_environ + beq cr6,L_co_switch$store_environ + oris r8,r8,0x4000 ;set the flag to say we have it! +L_co_switch$store_environ: + stw r8,lo16(_co_environ-L_co_switch$spb)(r29) ;store environment flags +L_co_switch$initialised: + + andis. r10,r8,0x4000 ;do we have Altivec/VMX? + beq L_co_switch$save_no_vmx + mfspr r11,256 ;save VRSAVE + andi. r0,r11,0x0FFF ;short-circuit if it's zero + stw r11,240(r1) + beq L_co_switch$save_no_vmx + andi. r0,r11,0x0800 ;check bit 20 + addi r2,0,48 ;starting index + beq L_co_switch$save_skip_vr20 + stvx v20,r1,r2 ;save VR20 +L_co_switch$save_skip_vr20: + addi r2,r2,16 ;stride + andi. r0,r11,0x0400 ;check bit 21 + beq L_co_switch$save_skip_vr21 + stvx v21,r1,r2 ;save VR21 +L_co_switch$save_skip_vr21: + addi r2,r2,16 ;stride + andi. r0,r11,0x0200 ;check bit 22 + beq L_co_switch$save_skip_vr22 + stvx v22,r1,r2 ;save VR22 +L_co_switch$save_skip_vr22: + addi r2,r2,16 ;stride + andi. r0,r11,0x0100 ;check bit 23 + beq L_co_switch$save_skip_vr23 + stvx v23,r1,r2 ;save VR23 +L_co_switch$save_skip_vr23: + addi r2,r2,16 ;stride + andi. r0,r11,0x0080 ;check bit 24 + beq L_co_switch$save_skip_vr24 + stvx v24,r1,r2 ;save VR24 +L_co_switch$save_skip_vr24: + addi r2,r2,16 ;stride + andi. r0,r11,0x0040 ;check bit 25 + beq L_co_switch$save_skip_vr25 + stvx v25,r1,r2 ;save VR25 +L_co_switch$save_skip_vr25: + addi r2,r2,16 ;stride + andi. r0,r11,0x0020 ;check bit 26 + beq L_co_switch$save_skip_vr26 + stvx v26,r1,r2 ;save VR26 +L_co_switch$save_skip_vr26: + addi r2,r2,16 ;stride + andi. r0,r11,0x0010 ;check bit 27 + beq L_co_switch$save_skip_vr27 + stvx v27,r1,r2 ;save VR27 +L_co_switch$save_skip_vr27: + addi r2,r2,16 ;stride + andi. r0,r11,0x0008 ;check bit 28 + beq L_co_switch$save_skip_vr28 + stvx v28,r1,r2 ;save VR28 +L_co_switch$save_skip_vr28: + addi r2,r2,16 ;stride + andi. r0,r11,0x0004 ;check bit 29 + beq L_co_switch$save_skip_vr29 + stvx v29,r1,r2 ;save VR29 +L_co_switch$save_skip_vr29: + addi r2,r2,16 ;stride + andi. r0,r11,0x0002 ;check bit 30 + beq L_co_switch$save_skip_vr30 + stvx v30,r1,r2 ;save VR30 +L_co_switch$save_skip_vr30: + addi r2,r2,16 ;stride + andi. r0,r11,0x0001 ;check bit 31 + beq L_co_switch$save_skip_vr31 + stvx v31,r1,r2 ;save VR31 +L_co_switch$save_skip_vr31: +L_co_switch$save_no_vmx: + + addis r4,r31,ha16(_co_active_context-L_co_switch$spb) ;save current context + ld r5,lo16(_co_active_context-L_co_switch$spb)(r4) + std r30,lo16(_co_active_context-L_co_switch$spb)(r4);set new context + std r1,0(r5) ;save current stack pointer + ld r1,0(r30) ;get new stack pointer + lwz r12,8(r30) ;have we already set GPR13 (system TLS)? + andis. r0,r12,0x8000 + beq+ L_co_switch$gpr13_set + std r13,392(r1) + xoris r12,r12,0x8000 + stw r12,8(r30) +L_co_switch$gpr13_set: + + andis. r10,r8,0x4000 ;do we have Altivec/VMX? + beq L_co_switch$restore_no_vmx + lwz r11,240(r1) ;restore VRSAVE + andi. r0,r11,0x0FFF ;short-circuit if it's zero + mtspr 256,r11 + beq L_co_switch$restore_no_vmx + andi. r0,r11,0x0800 ;check bit 20 + addi r2,0,48 ;starting index + beq L_co_switch$restore_skip_vr20 + lvx v20,r1,r2 ;restore VR20 +L_co_switch$restore_skip_vr20: + addi r2,r2,16 ;stride + andi. r0,r11,0x0400 ;check bit 21 + beq L_co_switch$restore_skip_vr21 + lvx v21,r1,r2 ;restore VR21 +L_co_switch$restore_skip_vr21: + addi r2,r2,16 ;stride + andi. r0,r11,0x0200 ;check bit 22 + beq L_co_switch$restore_skip_vr22 + lvx v22,r1,r2 ;restore VR22 +L_co_switch$restore_skip_vr22: + addi r2,r2,16 ;stride + andi. r0,r11,0x0100 ;check bit 23 + beq L_co_switch$restore_skip_vr23 + lvx v23,r1,r2 ;restore VR23 +L_co_switch$restore_skip_vr23: + addi r2,r2,16 ;stride + andi. r0,r11,0x0080 ;check bit 24 + beq L_co_switch$restore_skip_vr24 + lvx v24,r1,r2 ;restore VR24 +L_co_switch$restore_skip_vr24: + addi r2,r2,16 ;stride + andi. r0,r11,0x0040 ;check bit 25 + beq L_co_switch$restore_skip_vr25 + lvx v25,r1,r2 ;restore VR25 +L_co_switch$restore_skip_vr25: + addi r2,r2,16 ;stride + andi. r0,r11,0x0020 ;check bit 26 + beq L_co_switch$restore_skip_vr26 + lvx v26,r1,r2 ;restore VR26 +L_co_switch$restore_skip_vr26: + addi r2,r2,16 ;stride + andi. r0,r11,0x0010 ;check bit 27 + beq L_co_switch$restore_skip_vr27 + lvx v27,r1,r2 ;restore VR27 +L_co_switch$restore_skip_vr27: + addi r2,r2,16 ;stride + andi. r0,r11,0x0008 ;check bit 28 + beq L_co_switch$restore_skip_vr28 + lvx v28,r1,r2 ;restore VR28 +L_co_switch$restore_skip_vr28: + addi r2,r2,16 ;stride + andi. r0,r11,0x0004 ;check bit 29 + beq L_co_switch$restore_skip_vr29 + lvx v29,r1,r2 ;restore VR29 +L_co_switch$restore_skip_vr29: + addi r2,r2,16 ;stride + andi. r0,r11,0x0002 ;check bit 30 + beq L_co_switch$restore_skip_vr30 + lvx v30,r1,r2 ;restore VR30 +L_co_switch$restore_skip_vr30: + addi r2,r2,16 ;stride + andi. r0,r11,0x0001 ;check bit 31 + beq L_co_switch$restore_skip_vr31 + lvx v31,r1,r2 ;restore VR31 +L_co_switch$restore_skip_vr31: +L_co_switch$restore_no_vmx: + + lfd f14,248(r1) ;restore preserved FPRs + lfd f15,256(r1) + lfd f16,264(r1) + lfd f17,272(r1) + lfd f18,280(r1) + lfd f19,288(r1) + lfd f20,296(r1) + lfd f21,304(r1) + lfd f22,312(r1) + lfd f23,320(r1) + lfd f24,328(r1) + lfd f25,336(r1) + lfd f26,344(r1) + lfd f27,352(r1) + lfd f28,360(r1) + lfd f29,368(r1) + lfd f30,376(r1) + lfd f31,384(r1) + addi r0,0,0 ;make thread main crash if it returns + ld r1,0(r1) ;deallocate stack frame + ld r6,16(r1) ;return address in GPR6 + lwz r7,8(r1) ;condition codes in GPR7 + ld r13,-152(r1) ;restore preserved GPRs + ld r14,-144(r1) + ld r15,-136(r1) + ld r16,-128(r1) + ld r17,-120(r1) + ld r18,-112(r1) + ld r19,-104(r1) + ld r20,-96(r1) + ld r21,-88(r1) + ld r22,-80(r1) + ld r23,-72(r1) + ld r24,-64(r1) + ld r25,-56(r1) + ld r26,-48(r1) + ld r27,-40(r1) + ld r28,-32(r1) + ld r29,-24(r1) + ld r30,-16(r1) + ld r31,-8(r1) + mtlr r0 + mtctr r6 ;restore return address + mtcrf 32,r7 ;restore preserved condition codes + mtcrf 16,r7 + mtcrf 8,r7 + bctr ;return + + + +;Import external functions + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 5 +L_malloc$stub: + .indirect_symbol _malloc + mflr r0 + bcl 20,31,L_malloc$spb +L_malloc$spb: + mflr r11 + addis r11,r11,ha16(L_malloc$lazy_ptr-L_malloc$spb) + mtlr r0 + ldu r12,lo16(L_malloc$lazy_ptr-L_malloc$spb)(r11) + mtctr r12 + bctr + .lazy_symbol_pointer +L_malloc$lazy_ptr: + .indirect_symbol _malloc + .quad dyld_stub_binding_helper + + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 5 +L_free$stub: + .indirect_symbol _free + mflr r0 + bcl 20,31,L_free$spb +L_free$spb: + mflr r11 + addis r11,r11,ha16(L_free$lazy_ptr-L_free$spb) + mtlr r0 + ldu r12,lo16(L_free$lazy_ptr-L_free$spb)(r11) + mtctr r12 + bctr + .lazy_symbol_pointer +L_free$lazy_ptr: + .indirect_symbol _free + .quad dyld_stub_binding_helper + + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 5 +L_sysctlbyname$stub: + .indirect_symbol _sysctlbyname + mflr r0 + bcl 20,31,L_sysctlbyname$spb +L_sysctlbyname$spb: + mflr r11 + addis r11,r11,ha16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb) + mtlr r0 + ldu r12,lo16(L_sysctlbyname$lazy_ptr-L_sysctlbyname$spb)(r11) + mtctr r12 + bctr + .lazy_symbol_pointer +L_sysctlbyname$lazy_ptr: + .indirect_symbol _sysctlbyname + .quad dyld_stub_binding_helper + + +;This needs to be here! + + .subsections_via_symbols + diff --git a/src/lib/libco/libco.ucontext.cpp b/src/lib/libco/libco.ucontext.cpp new file mode 100644 index 00000000..da236326 --- /dev/null +++ b/src/lib/libco/libco.ucontext.cpp @@ -0,0 +1,80 @@ +/* + libco.ucontext (2007-09-08) + author: byuu + license: public domain +*/ + +#include +#include +#include "../libco.h" + +//WARNING: the overhead of POSIX ucontext is very high, +//averaging ~450x that of standard subroutine calls. +//(tested on FreeBSD 6.2-RELEASE) +//By contrast, on the same system, libco_x86's overhead +//is ~7.25x standard subroutine calls; or fifty times faster. +// +//This library only exists for two reasons: +//1 - as an initial test for the viability of a ucontext implementation +//2 - to demonstrate the power and speed of libco over existing implementations, +// such as pth (which defaults to wrapping ucontext on unix targets) +// +//Use this library only as a *last resort* + +struct cothread_struct { + ucontext_t cohandle; + void (*coentry)(); +}; + +cothread_t __co_active = 0, __co_primary = 0; +void co_entrypoint(cothread_t cothread); +void co_init(); + +/***** + * library functions + *****/ + +cothread_t co_active() { + if(__co_primary == 0)co_init(); + return __co_active; +} + +cothread_t co_create(unsigned int heapsize, void (*coentry)()) { + if(__co_primary == 0)co_init(); +cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct)); + thread->coentry = coentry; + getcontext(&thread->cohandle); + heapsize += 512; + thread->cohandle.uc_stack.ss_sp = (char*)malloc(heapsize); + thread->cohandle.uc_stack.ss_size = heapsize; + makecontext(&thread->cohandle, (void (*)())co_entrypoint, 1, thread); + return (cothread_t)thread; +} + +void co_delete(cothread_t cothread) { +cothread_struct *thread = (cothread_struct*)cothread; + free(thread->cohandle.uc_stack.ss_sp); + free(thread); +} + +void co_switch(cothread_t cothread) { +cothread_struct *active = (cothread_struct*)__co_active; +cothread_struct *swap = (cothread_struct*)cothread; + __co_active = cothread; + swapcontext(&active->cohandle, &swap->cohandle); +} + +/***** + * internal functions + *****/ + +void co_entrypoint(cothread_t cothread) { + ((cothread_struct*)cothread)->coentry(); +} + +void co_init() { +cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct)); + thread->coentry = 0; + getcontext(&thread->cohandle); + __co_active = __co_primary = (cothread_t)thread; +} diff --git a/src/lib/libco/libco.win.cpp b/src/lib/libco/libco.win.cpp new file mode 100644 index 00000000..f0d16626 --- /dev/null +++ b/src/lib/libco/libco.win.cpp @@ -0,0 +1,66 @@ +/* + libco.win (2007-09-08) + author: byuu + license: public domain +*/ + +#define WINVER 0x0400 +#define _WIN32_WINNT 0x0400 +#include +#include "../libco.h" + +struct cothread_struct { + void *cohandle; + void (*coentry)(); +}; + +cothread_t __co_active = 0, __co_primary = 0; + +void __stdcall co_entryproc(void*); +cothread_t co_init(); + +/***** + * library functions + *****/ + +cothread_t co_active() { + if(__co_primary == 0)co_init(); + return __co_active; +} + +cothread_t co_create(unsigned int heapsize, void (*coentry)()) { + if(__co_primary == 0)co_init(); +cothread_struct *s = (cothread_struct*)malloc(sizeof(cothread_struct)); + s->coentry = coentry; + s->cohandle = CreateFiber(heapsize + 512, co_entryproc, (void*)s); + return (cothread_t)s; +} + +void co_delete(cothread_t cothread) { +cothread_struct *s = (cothread_struct*)cothread; + DeleteFiber(s->cohandle); + free(cothread); +} + +void co_switch(cothread_t cothread) { + __co_active = cothread; +cothread_struct *s = (cothread_struct*)cothread; + SwitchToFiber(s->cohandle); +} + +/***** + * internal functions + *****/ + +void __stdcall co_entryproc(void *cothread) { + ((cothread_struct*)cothread)->coentry(); +} + +cothread_t co_init() { + ConvertThreadToFiber(0); +cothread_struct *s = (cothread_struct*)malloc(sizeof(cothread_struct)); + s->coentry = 0; + s->cohandle = GetCurrentFiber(); + __co_active = __co_primary = (cothread_t)s; + return __co_active; +} diff --git a/src/lib/libco_x86_64.asm b/src/lib/libco/libco.x86-64.asm similarity index 61% rename from src/lib/libco_x86_64.asm rename to src/lib/libco/libco.x86-64.asm index 224a7c0a..051987f0 100644 --- a/src/lib/libco_x86_64.asm +++ b/src/lib/libco/libco.x86-64.asm @@ -1,123 +1,146 @@ -;***** -;libco_x86_64 : version 0.10 ~byuu (2007-09-08) -;cross-platform x86-64 implementation of libco -;special thanks to Aaron Giles and Joel Yliluoma for various optimizations -; -;[ABI compatibility] -;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf ) -;- gcc; linux; x86-64 -;- gcc; freebsd; x86-64 -; -;[nonvolatile registers] -;- rsp, rbp, rbx, r12, r13, r14, r15 -; -;[volatile registers] -;- rax, rcx, rdx, r8, r9, r10, r11, rdi, rsi -;- st0 - st7 -;- xmm0 - xmm15 -;***** - -bits 64 - -section .bss - -align 8 -co_primary_buffer resb 512 - -section .data - -align 8 -co_active_context dq co_primary_buffer - -section .text - -extern malloc -extern free - -global co_active -global co_create -global co_delete -global co_switch - -;***** -;extern "C" cothread_t co_active(); -;return = rax -;***** - -align 16 -co_active: - mov rax,[co_active_context wrt rip] - ret - -;***** -;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)()); -;rdi = heapsize -;rsi = coentry -;return = rax -;***** - -align 16 -co_create: -;create heap space (stack + register storage) - add rdi,512 ;allocate extra memory for contextual info - push rdi - push rsi - - call malloc ;rax = malloc(rdi) - - pop rsi - pop rdi - - add rdi,rax ;set rsi to point to top of stack heap - and rdi,-16 ;force 16-byte alignment of stack heap - -;store thread entry point + registers, so that first call to co_switch will execute coentry - mov qword[rdi-8],rsi ;entry point - mov qword[rdi-16],0 ;r15 - mov qword[rdi-24],0 ;r14 - mov qword[rdi-32],0 ;r13 - mov qword[rdi-40],0 ;r12 - mov qword[rdi-48],0 ;rbx - mov qword[rdi-56],0 ;rbp - sub rdi,56 - -;initialize context memory heap and return - mov [rax],rdi ;*cothread_t = stack heap pointer (rsp) - ret ;return allocated memory block as thread handle - -;***** -;extern "C" void co_delete(cothread_t cothread); -;rdi = cothread -;***** - -align 16 -co_delete: - jmp free ;free(rdi) - -;***** -;extern "C" void co_switch(cothread_t cothread); -;rdi = cothread -;***** - -align 16 -co_switch: - mov rax,[co_active_context wrt rip] ;backup current context - mov [co_active_context wrt rip],rdi ;set new active context - - push rbp - push rbx - push r12 - push r13 - push r14 - push r15 - mov [rax],rsp - - mov rsp,[rdi] - pop r15 - pop r14 - pop r13 - pop r12 - pop rbx - pop rbp - - ret +;***** +;libco.x86-64 (2007-12-11) +;author: byuu +;license: public domain +; +;cross-platform x86-64 implementation of libco +;thanks to Aaron Giles and Joel Yliluoma for various optimizations +;thanks to Lucas Newman and Vas Crabb for assistance with OS X support +; +;[ABI compatibility] +;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf ) +;- gcc; mac os x; x86-64 +;- gcc; linux; x86-64 +;- gcc; freebsd; x86-64 +; +;[nonvolatile registers] +;- rsp, rbp, rbx, r12, r13, r14, r15 +; +;[volatile registers] +;- rax, rcx, rdx, r8, r9, r10, r11, rdi, rsi +;- st0 - st7 +;- xmm0 - xmm15 +;***** + +;***** +;linker-specific name decorations +;***** + +%ifdef OSX +%define malloc _malloc +%define free _free + +%define co_active _co_active +%define co_create _co_create +%define co_delete _co_delete +%define co_switch _co_switch +%endif + +bits 64 + +section .bss + +align 8 +co_primary_buffer resb 512 + +section .data + +align 8 +co_active_context dq co_primary_buffer + +section .text + +extern malloc +extern free + +global co_active +global co_create +global co_delete +global co_switch + +;***** +;extern "C" cothread_t co_active(); +;return = rax +;***** + +align 16 +co_active: + mov rax,[co_active_context wrt rip] + ret + +;***** +;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)()); +;rdi = heapsize +;rsi = coentry +;return = rax +;***** + +align 16 +co_create: +;create heap space (stack + context) + add rdi,512 ;allocate extra memory for contextual info + + push rdi ;backup volatile registers before malloc call + push rsi + + sub rsp,8 ;SSE 16-byte stack alignment + call malloc ;rax = malloc(rdi) + add rsp,8 + + pop rsi ;restore volatile registers + pop rdi + + add rdi,rax ;set rdi to point to top of stack heap + and rdi,-16 ;force 16-byte alignment of stack heap + +;store thread entry point + registers, so that first call to co_switch will execute coentry + mov qword[rdi-8],0 ;crash if entry point returns + mov qword[rdi-16],rsi ;entry point + mov qword[rdi-24],0 ;r15 + mov qword[rdi-32],0 ;r14 + mov qword[rdi-40],0 ;r13 + mov qword[rdi-48],0 ;r12 + mov qword[rdi-56],0 ;rbx + mov qword[rdi-64],0 ;rbp + sub rdi,64 + +;initialize context memory heap and return + mov [rax],rdi ;*cothread_t = stack heap pointer (rsp) + ret ;return allocated memory block as thread handle + +;***** +;extern "C" void co_delete(cothread_t cothread); +;rdi = cothread +;***** + +align 16 +co_delete: + jmp free ;free(rdi) + +;***** +;extern "C" void co_switch(cothread_t cothread); +;rdi = cothread +;***** + +align 16 +co_switch: + mov rax,[co_active_context wrt rip] ;backup current context + mov [co_active_context wrt rip],rdi ;set new active context + + push rbp + push rbx + push r12 + push r13 + push r14 + push r15 + mov [rax],rsp + + mov rsp,[rdi] + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rbp + + ret diff --git a/src/lib/libco_x86.asm b/src/lib/libco/libco.x86.asm similarity index 72% rename from src/lib/libco_x86.asm rename to src/lib/libco/libco.x86.asm index c243a537..f151c4a8 100644 --- a/src/lib/libco_x86.asm +++ b/src/lib/libco/libco.x86.asm @@ -1,148 +1,155 @@ -;***** -;libco_x86 : version 0.10 ~byuu (2007-09-08) -;cross-platform x86 implementation of libco -;special thanks to Aaron Giles and Joel Yliluoma for various optimizations -; -;[ABI compatibility] -;- visual c++; windows; x86 -;- mingw; windows; x86 -;- gcc; mac os x; x86 -;- gcc; linux; x86 -;- gcc; freebsd; x86 -; -;[nonvolatile registers] -;- esp, ebp, edi, esi, ebx -; -;[volatile registers] -;- eax, ecx, edx -;- st0 - st7 -;- xmm0 - xmm15 -;***** - -;***** -;linker-specific name decorations -;***** - -%ifdef WIN32 -%define malloc _malloc -%define free _free - -%define co_active @co_active@0 -%define co_create @co_create@8 -%define co_delete @co_delete@4 -%define co_switch @co_switch@4 -%endif - -%ifdef OSX86 -%define malloc _malloc -%define free _free - -%define co_active _co_active -%define co_create _co_create -%define co_delete _co_delete -%define co_switch _co_switch -%endif - -bits 32 - -section .bss - -align 4 -co_primary_buffer resb 512 - -section .data - -align 4 -co_active_context dd co_primary_buffer - -section .text - -extern malloc -extern free - -global co_active -global co_create -global co_delete -global co_switch - -;***** -;extern "C" cothread_t fastcall co_active(); -;return = eax -;***** - -align 16 -co_active: - mov eax,[co_active_context] - ret - -;***** -;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)()); -;ecx = heapsize -;edx = coentry -;return = eax -;***** - -align 16 -co_create: -;create heap space (stack + register storage) - add ecx,512 ;allocate extra memory for contextual info - push ecx - push edx - - push ecx - call malloc ;eax = malloc(edx) - add esp,4 - - pop edx - pop ecx - - add ecx,eax ;set edx to point to top of stack heap - and ecx,-16 ;force 16-byte alignment of stack heap - -;store thread entry point + registers, so that first call to co_switch will execute coentry - mov dword[ecx-4],edx ;entry point - mov dword[ecx-8],0 ;ebp - mov dword[ecx-12],0 ;esi - mov dword[ecx-16],0 ;edi - mov dword[ecx-20],0 ;ebx - sub ecx,20 - -;initialize context memory heap and return - mov [eax],ecx ;*cothread_t = stack heap pointer (esp) - ret ;return allocated memory block as thread handle - -;***** -;extern "C" void fastcall co_delete(cothread_t cothread); -;ecx = cothread -;***** - -align 16 -co_delete: - push ecx - call free ;free(ecx) - add esp,4 - ret - -;***** -;extern "C" void fastcall co_switch(cothread_t cothread); -;ecx = cothread -;***** - -align 16 -co_switch: - mov eax,[co_active_context] ;backup current context - mov [co_active_context],ecx ;set new active context - - push ebp - push esi - push edi - push ebx - mov [eax],esp - - mov esp,[ecx] - pop ebx - pop edi - pop esi - pop ebp - - ret +;***** +;libco.x86 (2007-12-11) +;author: byuu +;license: public domain +; +;cross-platform x86 implementation of libco +;thanks to Aaron Giles and Joel Yliluoma for various optimizations +;thanks to Lucas Newman and Vas Crabb for assistance with OS X support +; +;[ABI compatibility] +;- visual c++; windows; x86 +;- mingw; windows; x86 +;- gcc; mac os x; x86 +;- gcc; linux; x86 +;- gcc; freebsd; x86 +; +;[nonvolatile registers] +;- esp, ebp, edi, esi, ebx +; +;[volatile registers] +;- eax, ecx, edx +;- st0 - st7 +;- xmm0 - xmm15 +;***** + +;***** +;linker-specific name decorations +;***** + +%ifdef WIN +%define malloc _malloc +%define free _free + +%define co_active @co_active@0 +%define co_create @co_create@8 +%define co_delete @co_delete@4 +%define co_switch @co_switch@4 +%endif + +%ifdef OSX +%define malloc _malloc +%define free _free + +%define co_active _co_active +%define co_create _co_create +%define co_delete _co_delete +%define co_switch _co_switch +%endif + +bits 32 + +section .bss + +align 4 +co_primary_buffer resb 512 + +section .data + +align 4 +co_active_context dd co_primary_buffer + +section .text + +extern malloc +extern free + +global co_active +global co_create +global co_delete +global co_switch + +;***** +;extern "C" cothread_t fastcall co_active(); +;return = eax +;***** + +align 16 +co_active: + mov eax,[co_active_context] + ret + +;***** +;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)()); +;ecx = heapsize +;edx = coentry +;return = eax +;***** + +align 16 +co_create: +;create heap space (stack + context) + add ecx,512 ;allocate extra memory for contextual info + + push ecx ;backup volatile registers before malloc call + push edx + + push ecx + call malloc ;eax = malloc(ecx) + add esp,4 + + pop edx ;restore volatile registers + pop ecx + + add ecx,eax ;set edx to point to top of stack heap + and ecx,-16 ;force 16-byte alignment of stack heap + +;store thread entry point + registers, so that first call to co_switch will execute coentry + mov dword[ecx-4],0 ;crash if entry point returns + mov dword[ecx-8],edx ;entry point + mov dword[ecx-12],0 ;ebp + mov dword[ecx-16],0 ;esi + mov dword[ecx-20],0 ;edi + mov dword[ecx-24],0 ;ebx + sub ecx,24 + +;initialize context memory heap and return + mov [eax],ecx ;*cothread_t = stack heap pointer (esp) + ret ;return allocated memory block as thread handle + +;***** +;extern "C" void fastcall co_delete(cothread_t cothread); +;ecx = cothread +;***** + +align 16 +co_delete: + sub esp,8 ;SSE 16-byte stack alignment + push ecx + call free ;free(ecx) + add esp,4+8 + ret + +;***** +;extern "C" void fastcall co_switch(cothread_t cothread); +;ecx = cothread +;***** + +align 16 +co_switch: + mov eax,[co_active_context] ;backup current context + mov [co_active_context],ecx ;set new active context + + push ebp + push esi + push edi + push ebx + mov [eax],esp + + mov esp,[ecx] + pop ebx + pop edi + pop esi + pop ebp + + ret diff --git a/src/lib/libco_x86.h b/src/lib/libco_x86.h deleted file mode 100644 index 96744c68..00000000 --- a/src/lib/libco_x86.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - libco_x86 : version 0.10 ~byuu (2007-09-08) - license: public domain -*/ - -#ifndef LIBCO_H -#define LIBCO_H - -#if !defined(fastcall) - #if defined(_MSC_VER) - #define fastcall __fastcall - #elif defined(__GNUC__) - #define fastcall __attribute__((fastcall)) - #else - #error "fastcall undefined" - #endif -#endif - -typedef void *cothread_t; - -extern "C" cothread_t fastcall co_active(); -extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)()); -extern "C" void fastcall co_delete(cothread_t cothread); -extern "C" void fastcall co_switch(cothread_t cothread); - -#endif diff --git a/src/lib/libco_x86_64.h b/src/lib/libco_x86_64.h deleted file mode 100644 index e7d2c98a..00000000 --- a/src/lib/libco_x86_64.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - libco_x86_64 : version 0.10 ~byuu (2007-09-08) - license: public domain -*/ - -#ifndef LIBCO_H -#define LIBCO_H - -typedef void *cothread_t; - -extern "C" cothread_t co_active(); -extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)()); -extern "C" void co_delete(cothread_t cothread); -extern "C" void co_switch(cothread_t cothread); - -#endif diff --git a/src/lib/libstring.cpp b/src/lib/libstring.cpp deleted file mode 100644 index c841598f..00000000 --- a/src/lib/libstring.cpp +++ /dev/null @@ -1,456 +0,0 @@ -#include "libbase.h" -#include "libstring.h" -#include "libstring_oo.cpp" - -#include "libstring_array.cpp" - -char chrlower(char c) { - if(c >= 'A' && c <= 'Z')return c + ('a' - 'A'); - return c; -} - -char chrupper(char c) { - if(c >= 'a' && c <= 'z')return c - ('a' - 'A'); - return c; -} - -char *strptr(const string &str) { return str.s; } -uint strlen(const string &str) { return strlen(strptr(str)); } - -int strcmp(const string &dest, const char *src) { return strcmp(strptr(dest), src); } -int strcmp(const char *dest, const string &src) { return strcmp(dest, strptr(src)); } -int strcmp(const string &dest, const string &src) { return strcmp(strptr(dest), strptr(src)); } - -int __stricmp(const char *dest, const char *src) { - while(*dest) { - if(chrlower(*dest) != chrlower(*src))break; - dest++; - src++; - } - return (int)chrlower(*dest) - (int)chrlower(*src); -} -int stricmp(const string &dest, const char *src) { return __stricmp(strptr(dest), src); } -int stricmp(const char *dest, const string &src) { return __stricmp(dest, strptr(src)); } -int stricmp(const string &dest, const string &src) { return __stricmp(strptr(dest), strptr(src)); } - -void strcpy(string &dest, const char *src) { -int srclen = strlen(src); - dest.reserve(srclen); - strcpy(dest.s, src); -} -void strcpy(string &dest, const string &src) { strcpy(dest, strptr(src)); } - -uint strlcpy(char *dest, const char *src, uint length) { -uint srclen = strlen(src); - length--; - if(length > srclen)length = srclen; - memcpy(dest, src, length); - dest[length] = 0; - return srclen; -} - -uint strlcpy(string &dest, const char *src, uint length) { - dest.reserve(length); - return strlcpy(strptr(dest), src, length); -} - -uint strlcpy(string &dest, const string &src, uint length) { - dest.reserve(length); - return strlcpy(strptr(dest), strptr(src), length); -} - -void strcat(string &dest, const char *src) { -int srclen = strlen(src); -int destlen = strlen(dest); - dest.reserve(srclen + destlen); - strcat(dest.s, src); -} -void strcat(string &dest, const string &src) { strcat(dest, strptr(src)); } - -uint strlcat(char *dest, const char *src, uint length) { -uint destlen = strlen(dest), srclen = strlen(src); - length--; - if(length > destlen + srclen)length = destlen + srclen; - memcpy(dest + destlen, src, length - destlen); - dest[length] = 0; - return destlen + srclen; -} - -uint strlcat(string &dest, const char *src, uint length) { - dest.reserve(length); - return strlcat(strptr(dest), src, length); -} - -uint strlcat(string &dest, const string &src, uint length) { - dest.reserve(length); - return strlcat(strptr(dest), strptr(src), length); -} - -string substr(string &dest, const char *src, uint start, uint length) { -string temp; - if(length == 0) { - //copy entire string - strcpy(temp, src + start); - } else { - //copy partial string - strlcpy(temp, src + start, length + 1); - } - return temp; -} -string substr(string &dest, const string &src, uint start, uint length) { return substr(dest, strptr(src), start, length); } - -void strinsert(string &dest, const char *src, uint pos) { -string temp; - strcpy(temp, strptr(dest) + pos); - dest[pos] = 0; - strcat(dest, src); - strcat(dest, temp); -} -void strinsert(string &dest, const string &src, uint pos) { strinsert(dest, strptr(src), pos); } - -void strremove(string &dest, uint start, uint length) { -int i, destlen = strlen(dest); - dest.reserve(start); - if(!length) { - dest[start] = 0; - return; - } - for(i = start; i < destlen; i++) { dest.s[i] = dest.s[i + length]; } - dest.s[i] = 0; -} - -char *strlower(char *str) { -uint i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} -string &strlower(string &str) { strlower(strptr(str)); return str; } - -char *strupper(char *str) { -uint i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} -string &strupper(string &str) { strupper(strptr(str)); return str; } - -int strpos(const char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return -1; - for(int i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) { - return i; - } - } - return -1; -} -int strpos(const string &str, const char *key) { return strpos(strptr(str), key); } -int strpos(const char *str, const string &key) { return strpos(str, strptr(key)); } -int strpos(const string &str, const string &key) { return strpos(strptr(str), strptr(key)); } - -int qstrpos(const char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return -1; - for(int i = 0; i <= ssl - ksl;) { - uint8 x = str[i]; - if(x == '\"' || x == '\'') { - uint8 z = i++; - while(str[i] != x && i < ssl)i++; - if(i >= ssl)i = z; - } - if(!memcmp(str + i, key, ksl)) { - return i; - } else { - i++; - } - } - return -1; -} -int qstrpos(const string &str, const char *key) { return qstrpos(strptr(str), key); } -int qstrpos(const char *str, const string &key) { return qstrpos(str, strptr(key)); } -int qstrpos(const string &str, const string &key) { return qstrpos(strptr(str), strptr(key)); } - -void strtr(char *dest, const char *before, const char *after) { -int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - if(bsl != asl || bsl == 0)return; - for(int i = 0; i < sl; i++) { - for(int l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } -} -void strtr(string &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); } - -bool strbegin(const char *str, const char *key) { -int i, ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return false; - return (!memcmp(str, key, ksl)); -} -bool strbegin(const string &str, const char *key) { return strbegin(strptr(str), key); } - -bool stribegin(const char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} -bool stribegin(const string &str, const char *key) { return stribegin(strptr(str), key); } - -bool strend(const char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} -bool strend(const string &str, const char *key) { return strend(strptr(str), key); } - -bool striend(const char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} -bool striend(const string &str, const char *key) { return striend(strptr(str), key); } - -void strltrim(char *str, const char *key) { -int i, ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return; - if(strbegin(str, key)) { - for(i = 0; i < (ssl - ksl); i++)str[i] = str[i + ksl]; - str[i] = 0; - } -} -void strltrim(string &str, const char *key) { strltrim(strptr(str), key); } - -void striltrim(char *str, const char *key) { -int i, ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return; - if(stribegin(str, key)) { - for(i = 0; i < (ssl-ksl); i++)str[i] = str[i + ksl]; - str[i] = 0; - } -} -void striltrim(string &str, const char *key) { striltrim(strptr(str), key); } - -void strrtrim(char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return; - if(strend(str, key)) { - str[ssl - ksl] = 0; - } -} -void strrtrim(string &str, const char *key) { strrtrim(strptr(str), key); } - -void strirtrim(char *str, const char *key) { -int ssl = strlen(str), ksl = strlen(key); - if(ksl > ssl)return; - if(striend(str, key)) { - str[ssl - ksl] = 0; - } -} -void strirtrim(string &str, const char *key) { strirtrim(strptr(str), key); } - -void strtrim(char *str, const char *key) { - strltrim(str, key); - strrtrim(str, key); -} -void strtrim(string &str, const char *key) { strtrim(strptr(str), key); } - -void stritrim(char *str, const char *key) { - striltrim(str, key); - strirtrim(str, key); -} -void stritrim(string &str, const char *key) { stritrim(strptr(str), key); } - -//does not support char* type because function increases string length -void strquote(string &str) { -string t; - strcpy(t, "\""); - strcat(t, str); - strcat(t, "\""); - strcpy(str, t); -} - -bool strunquote(char *str) { -int i, ssl = strlen(str); -//make sure string is long enough to have quotes - if(ssl < 2)return false; - -//make sure string actually has quotes - if(str[0] == '\"' && str[ssl - 1] == '\"'); - else if(str[0] == '\'' && str[ssl - 1] == '\''); - else return false; - -//now remove them - for(i = 0; i < ssl; i++) { - str[i] = str[i + 1]; - } - str[i - 2] = 0; - - return true; -} -bool strunquote(string &str) { return strunquote(strptr(str)); } - -uint strhex(const char *str) { -uint r = 0, m = 0; -int i = 0, ssl = strlen(str); -uint8 x; -bool negate = (str[0] == '-'); - if(negate)i++; - for(; i < ssl; i++) { - if(str[i] >= '0' && str[i] <= '9'); - else if(str[i] >= 'A' && str[i] <= 'F'); - else if(str[i] >= 'a' && str[i] <= 'f'); - else break; - } - for(--i; i >= 0; i--, m += 4) { - x = str[i]; - if(x >= '0' && x <= '9')x -= '0'; - else if(x >= 'A' && x <= 'F')x -= 'A' - 0x0a; - else if(x >= 'a' && x <= 'f')x -= 'a' - 0x0a; - else break; - r |= x << m; - } - return !negate ? r : (uint)-r; -} -uint strhex(const string &str) { return strhex(strptr(str)); } - -uint strdec(const char *str) { -uint m = 1; -int i = 0, r = 0, ssl = strlen(str); -uint8 x; -bool negate = (str[0] == '-'); - if(negate)i++; - for(; i < ssl; i++) { - if(str[i] >= '0' && str[i] <= '9'); - else break; - } - for(--i; i >= 0; i--, m *= 10) { - x = str[i]; - if(x >= '0' && x <= '9')x -= '0'; - else break; - r += x * m; - } - return !negate ? r : (uint)-r; -} -uint strdec(const string &str) { return strdec(strptr(str)); } - -uint strbin(const char *str) { -uint r = 0, m = 0; -int i = 0, ssl = strlen(str); -uint8 x; -bool negate = (str[0] == '-'); - if(negate)i++; - for(; i < ssl; i++) { - if(str[i] == '0' || str[i] == '1'); - else break; - } - for(--i; i >= 0; i--, m++) { - x = str[i]; - if(str[i] == '0' || str[i] == '1')x -= '0'; - else break; - r |= x << m; - } - return !negate ? r : (uint)-r; -} -uint strbin(const string &str) { return strbin(strptr(str)); } - -char *utoa(char *str, uint num) { - sprintf(str, "%u", num); - return str; -} - -string &utoa(string &str, uint num) { - str.reserve(16); - utoa(strptr(str), num); - return str; -} - -char *itoa(char *str, uint num) { - sprintf(str, "%d", num); - return str; -} - -string &itoa(string &str, uint num) { - str.reserve(16); - itoa(strptr(str), num); - return str; -} - -char *htoa(char *str, uint num) { - sprintf(str, "%x", num); - return str; -} - -string &htoa(string &str, uint num) { - str.reserve(16); - htoa(strptr(str), num); - return str; -} - -char *btoa(char *str, uint num) { -char *pstr = str; -uint mask = 0x80000000; - while(mask && (num & mask) == 0)mask >>= 1; - while(mask > 1) { - str[0] = (num & mask) ? '1' : '0'; - str++; - mask >>= 1; - } - str[0] = (num & mask) ? '1' : '0'; - str++; - str[0] = 0; - return pstr; -} - -string &btoa(string &str, uint num) { - str.reserve(64); - btoa(strptr(str), num); - return str; -} - -bool strfread(string &str, const char *filename) { - strcpy(str, ""); - -FILE *fp = fopen(filename, "rb"); - if(!fp)return false; - -uint size = fsize(fp); -char *fdata = (char*)malloc(size + 1); - fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - strcpy(str, fdata); - free(fdata); - - return true; -} - -#include "libstring_int.cpp" -#include "libstring_math.cpp" -#include "libstring_split.cpp" -#include "libstring_replace.cpp" -#include "libstring_sprintf.cpp" diff --git a/src/lib/libstring.h b/src/lib/libstring.h deleted file mode 100644 index 8c7ad831..00000000 --- a/src/lib/libstring.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - libstring : version 0.18 ~byuu (2007-06-06) -*/ - -#ifndef LIBSTRING_H -#define LIBSTRING_H - -#include "libbase.h" -#include "libvector.h" - -class string; -typedef linear_vector stringarray; - -char chrlower(char c); -char chrupper(char c); - -uint count(stringarray &str); - -int find(stringarray &str, const char *key); -int find(stringarray &str, const string &key); - -char *strptr(const string &str); -uint strlen(const string &str); - -int strcmp(const string &dest, const char *src); -int strcmp(const char *dest, const string &src); -int strcmp(const string &dest, const string &src); - -//vc6/win32 and gcc/dos only support stricmp, whereas -//gcc/unix only supports strcasecmp. this is an attempt -//to avoid platform-specific defines... -#define stricmp __stricmp -int __stricmp(const char *dest, const char *src); -int stricmp(const string &dest, const char *src); -int stricmp(const char *dest, const string &src); -int stricmp(const string &dest, const string &src); - -void strcpy(string &dest, const char *src); -void strcpy(string &dest, const string &src); -uint strlcpy(char *dest, const char *src, uint length); -uint strlcpy(string &dest, const char *src, uint length); -uint strlcpy(string &dest, const string &src, uint length); - -void strcat(string &dest, const char *src); -void strcat(string &dest, const string &src); -uint strlcat(char *dest, const char *src, uint length); -uint strlcat(string &dest, const char *src, uint length); -uint strlcat(string &dest, const string &src, uint length); - -string substr(string &dest, const char *src, uint start = 0, uint length = 0); -string substr(string &dest, const string &src, uint start = 0, uint length = 0); - -void strinsert(string &dest, const char *src, uint pos); -void strinsert(string &dest, const string &src, uint pos); - -void strremove(string &dest, uint start, uint length = 0); - -char *strlower(char *str); -string &strlower(string &str); - -char *strupper(char *str); -string &strupper(string &str); - -int strpos(const char *str, const char *key); -int strpos(const string &str, const char *key); -int strpos(const char *str, const string &key); -int strpos(const string &str, const string &key); - -int qstrpos(const char *str, const char *key); -int qstrpos(const string &str, const char *key); -int qstrpos(const char *str, const string &key); -int qstrpos(const string &str, const string &key); - -void strtr(char *dest, const char *before, const char *after); -void strtr(string &dest, const char *before, const char *after); - -bool strbegin(const char *str, const char *key); -bool strbegin(const string &str, const char *key); - -bool stribegin(const char *str, const char *key); -bool stribegin(const string &str, const char *key); - -bool strend(const char *str, const char *key); -bool strend(const string &str, const char *key); - -bool striend(const char *str, const char *key); -bool striend(const string &str, const char *key); - -void strltrim(char *str, const char *key); -void strltrim(string &str, const char *key); - -void striltrim(char *str, const char *key); -void striltrim(string &str, const char *key); - -void strrtrim(char *str, const char *key); -void strrtrim(string &str, const char *key); - -void strirtrim(char *str, const char *key); -void strirtrim(string &str, const char *key); - -void strtrim(char *str, const char *key); -void strtrim(string &str, const char *key); - -void stritrim(char *str, const char *key); -void stritrim(string &str, const char *key); - -void strquote(string &str); - -bool strunquote(char *str); -bool strunquote(string &str); - -uint strhex(const char *str); -uint strhex(const string &str); - -uint strdec(const char *str); -uint strdec(const string &str); - -uint strbin(const char *str); -uint strbin(const string &str); - -char *utoa(char *str, uint num); -string &utoa(string &str, uint num); - -char *itoa(char *str, uint num); -string &itoa(string &str, uint num); - -char *htoa(char *str, uint num); -string &htoa(string &str, uint num); - -char *btoa(char *str, uint num); -string &btoa(string &str, uint num); - -bool strfread(string &str, const char *filename); - -string strfmt(const char *fmt, int num); - -int strmath(const char *str); -int strmath(const string &str); - -string &replace(string &str, const char *key, const char *token); -string &replace(string &str, const char *key, const string &token); - -string &qreplace(string &str, const char *key, const char *token); -string &qreplace(string &str, const char *key, const string &token); - -void split(stringarray &dest, const char *key, const char *src); -void split(stringarray &dest, const char *key, const string &src); - -void qsplit(stringarray &dest, const char *key, const char *src); -void qsplit(stringarray &dest, const char *key, const string &src); - -uint vsprintf(string &str, const char *s, va_list args); -uint sprintf(string &str, const char *s, ...); - -class string { -public: -char *s; -uint size; - void reserve(uint reqsize) { - if(reqsize > size) { - size = reqsize; - s = (char*)realloc(s, size + 1); - s[size] = 0; - } - } - - void swap(string &str) { - ::swap(s, str.s); - ::swap(size, str.size); - } - - string() { - size = 16; - s = (char*)malloc(size + 1); - s[0] = 0; - } - - string(const char *str) { - size = strlen(str); - s = (char*)malloc(size + 1); - strcpy(s, str); - } - - string(const string &str) { - size = strlen(str); - s = (char*)malloc(size + 1); - strcpy(s, strptr(str)); - } - - ~string() { safe_free(s); } - - operator const char*() const { return s; } - const char* operator()() const { return s; } - char& operator[](const uint); - - string& operator=(const int); - string& operator=(const char*); - string& operator=(const string&); - - string& operator<<(const int); - string& operator<<(const char*); - string& operator<<(const string&); - - bool operator==(const char*); - bool operator==(const string&); - bool operator!=(const char*); - bool operator!=(const string&); - bool operator< (const char*); - bool operator< (const string&); - bool operator<=(const char*); - bool operator<=(const string&); - bool operator> (const char*); - bool operator> (const string&); - bool operator>=(const char*); - bool operator>=(const string&); -}; - -inline void swap(string &x, string &y) { x.swap(y); } - -#endif //LIBSTRING_H diff --git a/src/lib/libstring_array.cpp b/src/lib/libstring_array.cpp deleted file mode 100644 index 7c731fbd..00000000 --- a/src/lib/libstring_array.cpp +++ /dev/null @@ -1,11 +0,0 @@ -uint count(stringarray &str) { - return str.size(); -} - -int find(stringarray &str, const char *key) { - for(uint i = 0; i < count(str); i++) { - if(str[i] == key) { return i; } - } - return -1; -} -int find(stringarray &str, const string &key) { return find(str, strptr(key)); } diff --git a/src/lib/libstring_int.cpp b/src/lib/libstring_int.cpp deleted file mode 100644 index 9c4c7ae4..00000000 --- a/src/lib/libstring_int.cpp +++ /dev/null @@ -1,5 +0,0 @@ -string strfmt(const char *fmt, int num) { -string temp; - sprintf(temp, fmt, num); - return temp; -} diff --git a/src/lib/libstring_oo.cpp b/src/lib/libstring_oo.cpp deleted file mode 100644 index 01dc8f48..00000000 --- a/src/lib/libstring_oo.cpp +++ /dev/null @@ -1,47 +0,0 @@ -char &string::operator[](const uint index) { - reserve(index); - return s[index]; -} - -string &string::operator=(const int num) { - strcpy(*this, strfmt("%d", num)); - return *this; -} - -string &string::operator=(const char *str) { - strcpy(*this, str); - return *this; -} - -string &string::operator=(const string &str) { - strcpy(*this, str); - return *this; -} - -string& string::operator<<(const int num) { - strcat(*this, strfmt("%d", num)); - return *this; -} - -string& string::operator<<(const char* str) { - strcat(*this, str); - return *this; -} - -string& string::operator<<(const string& str) { - strcat(*this, str); - return *this; -} - -bool string::operator==(const char *str) { return strcmp(strptr(*this), str) == 0; } -bool string::operator==(const string &str) { return strcmp(strptr(*this), strptr(str)) == 0; } -bool string::operator!=(const char *str) { return strcmp(strptr(*this), str) != 0; } -bool string::operator!=(const string &str) { return strcmp(strptr(*this), strptr(str)) != 0; } -bool string::operator< (const char *str) { return strcmp(strptr(*this), str) < 0; } -bool string::operator< (const string &str) { return strcmp(strptr(*this), strptr(str)) < 0; } -bool string::operator<=(const char *str) { return strcmp(strptr(*this), str) <= 0; } -bool string::operator<=(const string &str) { return strcmp(strptr(*this), strptr(str)) <= 0; } -bool string::operator> (const char *str) { return strcmp(strptr(*this), str) > 0; } -bool string::operator> (const string &str) { return strcmp(strptr(*this), strptr(str)) > 0; } -bool string::operator>=(const char *str) { return strcmp(strptr(*this), str) >= 0; } -bool string::operator>=(const string &str) { return strcmp(strptr(*this), strptr(str)) >= 0; } diff --git a/src/lib/libstring_sprintf.cpp b/src/lib/libstring_sprintf.cpp deleted file mode 100644 index 3a852354..00000000 --- a/src/lib/libstring_sprintf.cpp +++ /dev/null @@ -1,220 +0,0 @@ -uint vsprintf(string &str, const char *s, va_list args) { -va_list temp; - va_copy(temp, args); -int length = vsnprintf(0, 0, s, temp); - if(length < 0) length = 16 * 1024; //temp fix for non-C99-complaint vsnprintf - va_end(temp); - - str.reserve(length); - - va_copy(temp, args); - length = vsprintf(strptr(str), s, temp); - va_end(temp); - - return length; -} - -uint sprintf(string &str, const char *s, ...) { -va_list args; - va_start(args, s); -uint length = vsprintf(str, s, args); - va_end(args); - return length; -} - -/* -uint vsprintf(string &str, const char *s, va_list args) { -bool leftalign; -bool showbase; -char positivesign; -char pad; -uint width; -bool useprecision; -uint precision; -char modifier; -char type; - -uint32 vararg32; -uint64 vararg64; -char *varptr; -char varstr[256]; -uint varstrlen; - - strcpy(str, ""); -uint i = 0; - while(s[i]) { - if(s[i] != '%') { - strcat(str, s[i++]); - } else if(s[i + 1] == '%' || !s[i + 1]) { - strcat(str, '%'); - } else { //s[i] == '%' - //format: %[flags][width][.precision][modifiers]type - i++; - - //flags - leftalign = false; - positivesign = 0; - showbase = false; - - while(s[i]) { - if(s[i] == '-') { - leftalign = true; - i++; - } else if(s[i] == '+') { - positivesign = '+'; - i++; - } else if(s[i] == ' ') { - positivesign = ' '; - i++; - } else if(s[i] == '#') { - showbase = true; - i++; - } else { - break; - } - } - - //zero padding - if(s[i] == '0') { - pad = '0'; - i++; - } else { - pad = ' '; - } - - //width - width = 0; - if(s[i] == '*') { - width = va_arg(args, uint32); - i++; - } else { - while(s[i]) { - if(s[i] < '0' || s[i] > '9')break; - width *= 10; - width += s[i++] - '0'; - } - } - if(width == 0)width = 1; - - //precision - useprecision = false; - precision = 0; - if(s[i] == '.') { - useprecision = true; - i++; - - if(s[i] == '*') { - precision = va_arg(args, uint32); - i++; - } else { - while(s[i]) { - if(s[i] < '0' || s[i] > '9')break; - precision *= 10; - precision += s[i++] - '0'; - } - } - } - if(precision == 0)precision = 1; - - //modifier - if(s[i] == 'h') { - modifier = 'h'; - i++; - } else if(s[i] == 'l') { - modifier = 'l'; - i++; - } else if(s[i] == 'L') { - modifier = 'L'; - i++; - } - - //type - type = s[i++]; - switch(type) { - - case 'c': { - //character - vararg32 = va_arg(args, uint32); - - if(leftalign == false) { while(width-- > 1)strcat(str, pad); } - strcat(str, char(vararg32)); - if(leftalign == true) { while(width-- > 1)strcat(str, pad); } - } break; - - case 's': { - //string - varptr = va_arg(args, char*); - - varstrlen = strlen(varptr); - if(useprecision && precision < varstrlen)varstrlen = precision; - if(leftalign == false) { while(width-- > varstrlen)strcat(str, pad); } - uint index = 0; - //todo: optimize to a fixed-width strcat - while(index < varstrlen)strcat(str, varptr[index++]); - if(leftalign == true) { while(width-- > varstrlen)strcat(str, pad); } - } break; - - case 'd': - case 'i': - case 'u': - case 'x': - case 'X': { - //signed integer - vararg32 = va_arg(args, uint32); - - if(type == 'd' || type == 'i') { - itoa(varstr, vararg32); - } else if(type == 'u') { - utoa(varstr, vararg32); - } else if(type == 'x') { - htoa(varstr, vararg32); - } else if(type == 'X') { - uhtoa(varstr, vararg32); - } - - uint basestrlen = strlen(varstr); - varstrlen = (useprecision && precision > basestrlen) ? precision : basestrlen; - - if(type == 'd' || type == 'i') { - if(int32(vararg32) >= 0 && positivesign) { varstrlen++; } - } - - if(type == 'x' || type == 'X') { - if(showbase) { varstrlen += 2; } - } - - if(leftalign == false) { while(width-- > varstrlen)strcat(str, pad); } - if(type == 'd' || type == 'i') { - if(int32(vararg32) >= 0 && positivesign) { strcat(str, positivesign); } - } - if(type == 'x' || type == 'X') { - if(showbase)strcat(str, (type == 'x') ? "0x" : "0X"); - } - if(useprecision) { - while(basestrlen < precision) { strcat(str, "0"); basestrlen++; } - } - strcat(str, varstr); - if(leftalign == true) { while(width-- > varstrlen)strcat(str, pad); } - } break; - - case 'p': { - //todo: add 64-bit pointer support - vararg32 = va_arg(args, uint32); - - strcpy(varstr, "00000000"); - uint index = 8; - htoa(varstr + index, vararg32); - varstrlen = strlen(varstr + index); - index -= 8 - varstrlen; - - if(leftalign == false) { while(width-- > 8)strcat(str, pad); } - strcat(str, varstr + index); - if(leftalign == true) { while(width-- > 8)strcat(str, pad); } - } break; - - } - } - } - return strlen(str); -} -*/ diff --git a/src/lib/libui_gtk.cpp b/src/lib/libui_gtk.cpp deleted file mode 100644 index 276573a5..00000000 --- a/src/lib/libui_gtk.cpp +++ /dev/null @@ -1,283 +0,0 @@ -#include -#include -#include "libui_gtk.h" -#include "libui_gtk_window.cpp" -#include "libui_gtk_control.cpp" - -namespace libui { - -void init() { -int argc = 1; -char **argv; - argv = (char**)malloc(1 * sizeof(char*)); - argv[0] = (char*)malloc(64 * sizeof(char)); - strcpy(argv[0], "./libui"); -//GTK+ insists you provide main()'s argc, argv parameters for -//some special command-line processing options that are likely -//never used by anything. -//However, I insist on libui_init() not requiring arguments so -//that it can be called from anywhere, including a global -//constructor that is invoked before main() is reached. - gtk_init(&argc, &argv); - safe_free(argv[0]); - safe_free(argv); -} - -void term() { -} - -bool run() { - gtk_main_iteration_do(false); - return events_pending(); -} - -bool events_pending() { - return gtk_events_pending(); -} - -uint get_screen_width() { return gdk_screen_width(); } -uint get_screen_height() { return gdk_screen_height(); } - -// - -bool file_load(Window *owner, char *filename, const char *filter, const char *path) { - strcpy(filename, ""); - -GtkWidget *dialog = gtk_file_chooser_dialog_new("Load File", - owner ? GTK_WINDOW(owner->info.window) : (GtkWindow*)0, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, (const gchar*)0); - - if(path && strcmp(path, "")) { - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), 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); - g_free(fn); - } - - gtk_widget_destroy(dialog); - return strcmp(filename, ""); //return true if filename != "" -} - -bool file_save(Window *owner, char *filename, const char *filter, const char *path) { - strcpy(filename, ""); - -GtkWidget *dialog = gtk_file_chooser_dialog_new("Save File", - owner ? GTK_WINDOW(owner->info.window) : (GtkWindow*)0, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, (const gchar*)0); - - if(path && strcmp(path, "")) { - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path); - } - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); - - if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - strcpy(filename, fn); - g_free(fn); - } - - gtk_widget_destroy(dialog); - return strcmp(filename, ""); //return true if filename != "" -} - -// - -uint16 translate_key(uint key) { - switch(key) { - - case GDK_Escape: return keymap::esc; - - case GDK_F1: return keymap::f1; - case GDK_F2: return keymap::f2; - case GDK_F3: return keymap::f3; - case GDK_F4: return keymap::f4; - case GDK_F5: return keymap::f5; - case GDK_F6: return keymap::f6; - case GDK_F7: return keymap::f7; - case GDK_F8: return keymap::f8; - case GDK_F9: return keymap::f9; - case GDK_F10: return keymap::f10; - case GDK_F11: return keymap::f11; - case GDK_F12: return keymap::f12; - - case GDK_Print: return keymap::print_screen; - case GDK_Sys_Req: return keymap::sys_req; - case GDK_Scroll_Lock: return keymap::scroll_lock; - case GDK_Pause: return keymap::pause; - case GDK_Break: return keymap::brk; - - case GDK_grave: return keymap::grave; - case GDK_asciitilde: return keymap::tilde; - - case GDK_1: return keymap::num_1; - case GDK_2: return keymap::num_2; - case GDK_3: return keymap::num_3; - case GDK_4: return keymap::num_4; - case GDK_5: return keymap::num_5; - case GDK_6: return keymap::num_6; - case GDK_7: return keymap::num_7; - case GDK_8: return keymap::num_8; - case GDK_9: return keymap::num_9; - case GDK_0: return keymap::num_0; - - case GDK_exclam: return keymap::exclamation; - case GDK_at: return keymap::at; - case GDK_numbersign: return keymap::pound; - case GDK_dollar: return keymap::dollar; - case GDK_percent: return keymap::percent; - case GDK_asciicircum: return keymap::power; - case GDK_ampersand: return keymap::ampersand; - case GDK_asterisk: return keymap::asterisk; - case GDK_parenleft: return keymap::lparenthesis; - case GDK_parenright: return keymap::rparenthesis; - - case GDK_minus: return keymap::minus; - case GDK_underscore: return keymap::underscore; - case GDK_equal: return keymap::equal; - case GDK_plus: return keymap::plus; - case GDK_BackSpace: return keymap::backspace; - - case GDK_Insert: return keymap::ins; - case GDK_Delete: return keymap::del; - case GDK_Home: return keymap::home; - case GDK_End: return keymap::end; - case GDK_Page_Up: return keymap::page_up; - case GDK_Page_Down: return keymap::page_down; - - case GDK_a: return keymap::a; - case GDK_b: return keymap::b; - case GDK_c: return keymap::c; - case GDK_d: return keymap::d; - case GDK_e: return keymap::e; - case GDK_f: return keymap::f; - case GDK_g: return keymap::g; - case GDK_h: return keymap::h; - case GDK_i: return keymap::i; - case GDK_j: return keymap::j; - case GDK_k: return keymap::k; - case GDK_l: return keymap::l; - case GDK_m: return keymap::m; - case GDK_n: return keymap::n; - case GDK_o: return keymap::o; - case GDK_p: return keymap::p; - case GDK_q: return keymap::q; - case GDK_r: return keymap::r; - case GDK_s: return keymap::s; - case GDK_t: return keymap::t; - case GDK_u: return keymap::u; - case GDK_v: return keymap::v; - case GDK_w: return keymap::w; - case GDK_x: return keymap::x; - case GDK_y: return keymap::y; - case GDK_z: return keymap::z; - - case GDK_A: return keymap::A; - case GDK_B: return keymap::B; - case GDK_C: return keymap::C; - case GDK_D: return keymap::D; - case GDK_E: return keymap::E; - case GDK_F: return keymap::F; - case GDK_G: return keymap::G; - case GDK_H: return keymap::H; - case GDK_I: return keymap::I; - case GDK_J: return keymap::J; - case GDK_K: return keymap::K; - case GDK_L: return keymap::L; - case GDK_M: return keymap::M; - case GDK_N: return keymap::N; - case GDK_O: return keymap::O; - case GDK_P: return keymap::P; - case GDK_Q: return keymap::Q; - case GDK_R: return keymap::R; - case GDK_S: return keymap::S; - case GDK_T: return keymap::T; - case GDK_U: return keymap::U; - case GDK_V: return keymap::V; - case GDK_W: return keymap::W; - case GDK_X: return keymap::X; - case GDK_Y: return keymap::Y; - case GDK_Z: return keymap::Z; - - case GDK_bracketleft: return keymap::lbracket; - case GDK_bracketright: return keymap::rbracket; - case GDK_backslash: return keymap::backslash; - case GDK_semicolon: return keymap::semicolon; - case GDK_apostrophe: return keymap::apostrophe; - case GDK_comma: return keymap::comma; - case GDK_period: return keymap::period; - case GDK_slash: return keymap::slash; - - case GDK_braceleft: return keymap::lbrace; - case GDK_braceright: return keymap::rbrace; - case GDK_bar: return keymap::pipe; - case GDK_colon: return keymap::colon; - case GDK_quotedbl: return keymap::quote; - case GDK_less: return keymap::lcaret; - case GDK_greater: return keymap::rcaret; - case GDK_question: return keymap::question; - - case GDK_KP_1: return keymap::kp_1; - case GDK_KP_2: return keymap::kp_2; - case GDK_KP_3: return keymap::kp_3; - case GDK_KP_4: return keymap::kp_4; - case GDK_KP_5: return keymap::kp_5; - case GDK_KP_6: return keymap::kp_6; - case GDK_KP_7: return keymap::kp_7; - case GDK_KP_8: return keymap::kp_8; - case GDK_KP_9: return keymap::kp_9; - case GDK_KP_0: return keymap::kp_0; - case GDK_KP_Decimal: return keymap::kp_decimal; - - case GDK_KP_End: return keymap::kp_end; - case GDK_KP_Down: return keymap::kp_down; - case GDK_KP_Page_Down: return keymap::kp_page_down; - case GDK_KP_Left: return keymap::kp_left; - case GDK_KP_Begin: return keymap::kp_center; - case GDK_KP_Right: return keymap::kp_right; - case GDK_KP_Home: return keymap::kp_home; - case GDK_KP_Up: return keymap::kp_up; - case GDK_KP_Page_Up: return keymap::kp_page_up; - case GDK_KP_Insert: return keymap::kp_insert; - case GDK_KP_Delete: return keymap::kp_delete; - - case GDK_KP_Add: return keymap::kp_plus; - case GDK_KP_Subtract: return keymap::kp_minus; - case GDK_KP_Multiply: return keymap::kp_mul; - case GDK_KP_Divide: return keymap::kp_div; - case GDK_KP_Enter: return keymap::kp_enter; - - case GDK_Num_Lock: return keymap::num_lock; - case GDK_Caps_Lock: return keymap::caps_lock; - - case GDK_Up: return keymap::up; - case GDK_Down: return keymap::down; - case GDK_Left: return keymap::left; - case GDK_Right: return keymap::right; - - case GDK_Tab: return keymap::tab; - case GDK_Return: return keymap::enter; - case GDK_space: return keymap::space; - - case GDK_Control_L: return keymap::lctrl; - case GDK_Control_R: return keymap::rctrl; - case GDK_Alt_L: return keymap::lalt; - case GDK_Alt_R: return keymap::ralt; - case GDK_Shift_L: return keymap::lshift; - case GDK_Shift_R: return keymap::rshift; - case GDK_Super_L: return keymap::lsuper; - case GDK_Super_R: return keymap::rsuper; - case GDK_Menu: return keymap::menu; - - } - - return keymap::none; -} - -}; diff --git a/src/lib/libui_gtk.h b/src/lib/libui_gtk.h deleted file mode 100644 index 45ac93b5..00000000 --- a/src/lib/libui_gtk.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - libui_gtk ~byuu (2007-06-06) - license: public domain -*/ - -#ifndef LIBUI_H -#define LIBUI_H - -#include "libbase.h" -#include "libarray.h" -#include "libvector.h" -#include "libstring.h" -#include "libkeymap.h" - -//TODO: hide this if possible -#include - -namespace libui { - -class Window; -#include "libui_gtk_control.h" - -void init(); -void term(); -bool run(); -bool events_pending(); - -uint get_screen_width(); -uint get_screen_height(); - -bool file_load(Window *owner, char *filename, const char *filter, const char *path = ""); -bool file_save(Window *owner, char *filename, const char *filter, const char *path = ""); - -uint16 translate_key(uint key); - -namespace Message { - enum { - Invalid = 0, - Close, - Block, - KeyUp, - KeyDown, - Clicked, - DoubleClicked, - Changed, - }; -}; - -class Window { public: -enum Style { - Center = 1, -}; - -MenuBar menu; - void create(uint style, uint width, uint height, const char *caption = ""); - void set_text(const char *str); - void set_background_color(uint8 r, uint8 g, uint8 b); - void focus(); - bool focused(); - void move(uint x, uint y); - void resize(uint width, uint height); - virtual void show(); - virtual void hide(); - void show(bool state); - bool visible(); - void fullscreen(); - void unfullscreen(); - void fullscreen(bool state); - bool is_fullscreen(); - - virtual bool message(uint id, uintptr_t param = 0) { return true; } - -//private: -struct { - GtkWidget *window, *menubar; - GtkWidget *vcontainer, *container; -} info; - -public: - Window() { - info.menubar = 0; - } -}; - -}; - -#endif diff --git a/src/lib/libui_gtk_control.cpp b/src/lib/libui_gtk_control.cpp deleted file mode 100644 index 8f42e877..00000000 --- a/src/lib/libui_gtk_control.cpp +++ /dev/null @@ -1,676 +0,0 @@ -namespace libui { - -/***** - * Control - *****/ - -void Control::move(uint x, uint y) { - gtk_fixed_move(GTK_FIXED(owner->info.container), widget, x, y); -} - -void Control::resize(uint width, uint height) { - gtk_widget_set_size_request(widget, width, height); -} - -void Control::focus() { - gtk_widget_grab_focus(widget); -} - -void Control::show() { - gtk_widget_show(widget); -} - -void Control::hide() { - gtk_widget_hide(widget); -} - -void Control::show(bool state) { - (state == true) ? show() : hide(); -} - -bool Control::visible() { - return GTK_WIDGET_VISIBLE(widget); -} - -void Control::enable() { - gtk_widget_set_sensitive(widget, true); -} - -void Control::disable() { - gtk_widget_set_sensitive(widget, false); -} - -void Control::enable(bool state) { - (state == true) ? enable() : disable(); -} - -bool Control::enabled() { - return GTK_WIDGET_SENSITIVE(widget); -} - -/***** - * MenuBar - *****/ - -void MenuBar::create(Window &r_owner) { - type = ControlType::MenuBar; - widget = r_owner.info.menubar; - owner = &r_owner; - show(); -} - -void MenuBar::finish() { -} - -/***** - * MenuGroup - *****/ - -void MenuGroup::create(MenuBar &r_owner, const char *caption) { - type = ControlType::MenuGroup; - widget = gtk_menu_new(); - item = gtk_menu_item_new_with_label(caption ? caption : "?"); - owner = r_owner.owner; - parent = r_owner.widget; -} - -void MenuGroup::create(MenuGroup &r_owner, const char *caption) { - type = ControlType::MenuGroup; - widget = gtk_menu_new(); - item = gtk_menu_item_new_with_label(caption ? caption : "?"); - owner = r_owner.owner; - parent = r_owner.widget; -} - -void MenuGroup::finish() { - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), widget); - gtk_menu_bar_append(parent, item); - gtk_widget_show(item); -} - -/***** - * MenuItem - *****/ - -void MenuItem::create(MenuGroup &r_owner, const char *caption) { - type = ControlType::MenuItem; - widget = gtk_menu_item_new_with_label(caption ? caption : "?"); - owner = r_owner.owner; - parent = r_owner.widget; - gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget); - g_signal_connect_swapped(G_OBJECT(widget), "activate", - G_CALLBACK(libui_control_clicked), (gpointer)this); - gtk_widget_show(widget); -} - -/***** - * MenuCheckItem - *****/ - -void MenuCheckItem::create(MenuGroup &r_owner, const char *caption) { - type = ControlType::MenuCheckItem; - widget = gtk_check_menu_item_new_with_label(caption ? caption : "?"); - owner = r_owner.owner; - parent = r_owner.widget; - gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget); - g_signal_connect_swapped(G_OBJECT(widget), "activate", - G_CALLBACK(libui_control_clicked), (gpointer)this); - gtk_widget_show(widget); -} - -void MenuCheckItem::check() { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE); -} - -void MenuCheckItem::uncheck() { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), FALSE); -} - -void MenuCheckItem::check(bool state) { - (state == true) ? check() : uncheck(); -} - -bool MenuCheckItem::checked() { - return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); -} - -/***** - * MenuRadioItem - *****/ - -void MenuRadioItem::create(MenuGroup &r_owner, ControlGroup &list, const char *caption) { - if(list.count() == 0)throw; - type = ControlType::MenuRadioItem; - widget = (&list[0] == this) ? - gtk_radio_menu_item_new_with_label(0, caption ? caption : "?") : - gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(list[0].widget), caption ? caption : ""); - owner = r_owner.owner; - parent = r_owner.widget; - gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget); - g_signal_connect_swapped(G_OBJECT(widget), "activate", - G_CALLBACK(libui_control_clicked), (gpointer)this); - gtk_widget_show(widget); -} - -void MenuRadioItem::check() { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), TRUE); -} - -bool MenuRadioItem::checked() { - return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); -} - -/***** - * MenuSeparator - *****/ - -void MenuSeparator::create(MenuGroup &r_owner) { - type = ControlType::MenuSeparator; - widget = gtk_separator_menu_item_new(); - owner = r_owner.owner; - parent = r_owner.widget; - gtk_menu_shell_append(GTK_MENU_SHELL(parent), widget); - gtk_widget_show(widget); -} - -/***** - * Panel - *****/ - -void Panel::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Panel; - widget = gtk_fixed_new(); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -void Panel::attach(Window &window) { - if(attached) { //detach existing child window, return to toplevel window - gtk_widget_reparent(attached->info.vcontainer, attached->info.window); - } - attached = &window; - window.hide(); - gtk_widget_reparent(window.info.vcontainer, widget); -} - -void Panel::detach() { - if(attached) { - gtk_widget_reparent(attached->info.vcontainer, attached->info.window); - } - attached = 0; -} - -/***** - * Container - *****/ - -void Container::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Container; - widget = gtk_drawing_area_new(); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -void Container::set_background_color(uint8 r, uint8 g, uint8 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(widget, GTK_STATE_NORMAL, &color); -} - -unsigned long Container::x_handle() { - return GDK_WINDOW_XWINDOW(widget->window); -} - -GtkWidget *Container::handle() { - return widget; -} - -/***** - * Canvas - * - * Note: for reasons that defy any notion of logic, the GTK+ developers decided to - * store color in semi-reversed format (XBGR) rather than conventional format (XRGB). - * This is not an endian issue. - * As a result, we are forced to perform manual conversion to XBGR format, at the - * cost of significant overhead. - *****/ - -void libui_canvas_expose(GtkWidget *widget, GdkEventAny *any, Canvas *canvas) { -uint32 *d = canvas->rbuffer; -uint32 *s = canvas->buffer; - for(uint y = widget->allocation.height; y; y--) { - for(uint x = widget->allocation.width; x; x--) { - uint32 p = *s++; - *d++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff); - } - } - - gdk_draw_rgb_32_image(widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - 0, 0, widget->allocation.width, widget->allocation.height, - GDK_RGB_DITHER_NONE, (guchar*)canvas->rbuffer, canvas->pitch); -} - -void Canvas::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Canvas; - widget = gtk_drawing_area_new(); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); - - pitch = width * sizeof(uint32); - rbuffer = (uint32*)malloc(pitch * height); - buffer = (uint32*)malloc(pitch * height); - memset(buffer, 0, pitch * height); - memset(rbuffer, 0, pitch * height); - g_signal_connect(G_OBJECT(widget), "expose_event", G_CALLBACK(libui_canvas_expose), this); -} - -void Canvas::redraw() { - if(!widget->window)return; - -GdkRectangle rect; - rect.x = 0; - rect.y = 0; - rect.width = widget->allocation.width; - rect.height = widget->allocation.height; - gdk_window_invalidate_rect(widget->window, &rect, true); -} - -Canvas::Canvas() { - buffer = 0; -} - -Canvas::~Canvas() { - safe_free(rbuffer); - safe_free(buffer); -} - -/***** - * Frame - *****/ - -void Frame::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Frame; - widget = gtk_frame_new(caption ? caption : ""); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -/***** - * Label - *****/ - -void Label::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Label; - widget = gtk_label_new(caption ? caption : ""); - owner = &r_owner; - gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.0); - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -void Label::set_text(const char *str) { - gtk_label_set_label(GTK_LABEL(widget), str); -} - -/***** - * Button - *****/ - -void Button::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Button; - widget = gtk_button_new_with_label(caption ? caption : ""); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); - - g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this); -} - -void Button::set_text(const char *str) { - gtk_button_set_label(GTK_BUTTON(widget), str); -} - -/***** - * Checkbox - *****/ - -void Checkbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Checkbox; - widget = gtk_check_button_new_with_label(caption ? caption : ""); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); - - g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this); -} - -void Checkbox::check() { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); -} - -void Checkbox::uncheck() { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); -} - -void Checkbox::check(bool state) { - (state == true) ? check() : uncheck(); -} - -bool Checkbox::checked() { - return (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) ? true : false; -} - -/***** - * Radiobox - *****/ - -void Radiobox::create(Window &r_owner, ControlGroup &group, uint style, uint x, uint y, uint width, uint height, const char *caption) { - if(group.count() == 0)throw; - type = ControlType::Radiobox; - widget = (&group[0] == this) ? - gtk_radio_button_new_with_label(0, caption ? caption : "") : - gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0].widget), caption ? caption : ""); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); - - g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this); -} - -void Radiobox::check() { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE); -} - -bool Radiobox::checked() { - return (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) ? true : false; -} - -/***** - * Editbox - *****/ - -void Editbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - owner = &r_owner; - type = ControlType::Editbox; - multiline = bool(style & Multiline); - - if(multiline == false) { - widget = gtk_entry_new(); - if(style & Editbox::Readonly) { gtk_entry_set_editable(GTK_ENTRY(widget), false); } - gtk_entry_set_text(GTK_ENTRY(widget), caption ? caption : ""); - } 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; - widget = gtk_scrolled_window_new(0, 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), hscroll, vscroll); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), GTK_SHADOW_ETCHED_IN); - subwidget = gtk_text_view_new(); - gtk_container_add(GTK_CONTAINER(widget), subwidget); - buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(subwidget)); - if(style & Editbox::Readonly) { gtk_text_view_set_editable(GTK_TEXT_VIEW(subwidget), false); } - gtk_text_buffer_set_text(buffer, caption ? caption : "", -1); - gtk_widget_show(subwidget); - } - - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -void Editbox::set_text(const char *str) { - if(multiline == false) { - gtk_entry_set_text(GTK_ENTRY(widget), str); - } else { - gtk_text_buffer_set_text(buffer, str, -1); - } -} - -uint Editbox::get_text(char *str, uint length) { - if(multiline == false) { - const char *temp = gtk_entry_get_text(GTK_ENTRY(widget)); - return strlcpy(str, 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(str, gtk_text_buffer_get_text(buffer, &start, &end, true), length); - } -} - -/***** - * Listbox - *****/ - -/***** - * GTK+'s implementation of list boxes was apparently someone's idea of a very, very cruel joke ... - * Attempt to understand the below code at the risk of your own sanity. - *****/ - -void Listbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *columns) { - owner = &r_owner; - type = ControlType::Listbox; - -bool header = bool(style & Header); - -stringarray list, part; - split(part, "|", columns); - -GType *v = (GType*)malloc(count(part) * sizeof(GType)); - for(uint i = 0; i < count(part); i++) { v[i] = G_TYPE_STRING; } - store = gtk_list_store_newv(count(part), v); - safe_free(v); - - widget = gtk_scrolled_window_new(0, 0); -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; - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), hscroll, vscroll); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), GTK_SHADOW_ETCHED_IN); - subwidget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_container_add(GTK_CONTAINER(widget), subwidget); - g_object_unref(G_OBJECT(store)); - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(subwidget); - gtk_widget_show(widget); - - split(list, "|", columns); -//alternate colors for each listbox entry if there are multiple columns ... - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(subwidget), (count(list) >= 2) ? true : false); - for(uint i = 0; i < count(list); i++) { - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(strptr(list[i]), renderer, "text", i, 0); - column_list[column_list.size()] = column; - gtk_tree_view_append_column(GTK_TREE_VIEW(subwidget), column); - } - - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(subwidget), header); - autosize_columns(); - - g_signal_connect_swapped(G_OBJECT(subwidget), "cursor-changed", G_CALLBACK(libui_control_changed), (gpointer)this); - g_signal_connect_swapped(G_OBJECT(subwidget), "row-activated", G_CALLBACK(libui_control_double_clicked), (gpointer)this); -} - -void Listbox::autosize_columns() { - gtk_tree_view_columns_autosize(GTK_TREE_VIEW(subwidget)); -} - -void Listbox::set_column_width(uint column, uint width) { - gtk_tree_view_column_set_min_width(column_list[column], width); - gtk_tree_view_column_set_max_width(column_list[column], width); -} - -void Listbox::add_item(const char *data) { -stringarray part; - split(part, "|", data); - gtk_list_store_append(store, &iter); - for(uint i = 0; i < count(part); i++) { - gtk_list_store_set(store, &iter, i, strptr(part[i]), -1); - } -} - -void Listbox::set_item(uint index, const char *data) { -GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget)); - for(uint i = 0; i <= index; i++) { - (i == 0) ? - gtk_tree_model_get_iter_first(model, &iter) : - gtk_tree_model_iter_next(model, &iter); - } - -stringarray part; - split(part, "|", data); - for(uint i = 0; i < count(part); i++) { - gtk_list_store_set(store, &iter, i, strptr(part[i]), -1); - } -} - -//... because gtk_tree_view_get_selected_row(GTK_TREE_VIEW(subwidget)) would be too easy ... -int Listbox::get_selection() { -GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subwidget)); -GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget)); - 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(uint 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; -} - -//... because gtk_tree_view_set_selected_row(GTK_TREE_VIEW(subwidget), index) would be too easy ... -void Listbox::set_selection(int index) { -int current = get_selection(); -GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subwidget)); -GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget)); - gtk_tree_selection_unselect_all(selection); - if(index < 0) { goto end; } - if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; } - if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; } - for(uint i = 1; i < 100000; i++) { - if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; } - if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; } - } -end: - if(current != index) { owner->message(Message::Changed, (uintptr_t)this); } -} - -void Listbox::reset() { - gtk_list_store_clear(GTK_LIST_STORE(store)); - gtk_tree_view_set_model(GTK_TREE_VIEW(subwidget), GTK_TREE_MODEL(store)); -} - -/***** - * Combobox - *****/ - -void Combobox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Combobox; - widget = gtk_combo_box_new_text(); //gtk_combo_box_entry_new_text(); /* alternate style */ - owner = &r_owner; - counter = 0; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -void Combobox::add_item(const char *data) { - gtk_combo_box_append_text(GTK_COMBO_BOX(widget), data); - if(counter++ == 0) { set_selection(0); } -} - -int Combobox::get_selection() { - return gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); -} - -void Combobox::set_selection(int index) { - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), index); -} - -void Combobox::reset() { - if(counter == 0) { return; } - for(int i = (counter - 1); i >= 0; i--) { - gtk_combo_box_remove_text(GTK_COMBO_BOX(widget), i); - } - counter = 0; -} - -/***** - * Progressbar - *****/ - -void Progressbar::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Progressbar; - widget = gtk_progress_bar_new(); - owner = &r_owner; - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); -} - -void Progressbar::set_progress(uint progress) { - progress = minmax<0, 100>(progress); -double p = (double)progress / 100.0; - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(widget), p); -} - -uint Progressbar::get_progress() { -uint p = (uint)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(widget)) * 100.0); - return (uint)minmax<0, 100>(p); -} - -/***** - * Slider - *****/ - -void Slider::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, uint range) { - type = ControlType::Slider; - orientation = (style & Vertical) ? 1 : 0; - - if(range < 1)range = 1; - if(orientation == 0) { - widget = gtk_hscale_new_with_range(0, range - 1, 1); - } else { - widget = gtk_vscale_new_with_range(0, range - 1, 1); - } - - owner = &r_owner; - gtk_scale_set_draw_value(GTK_SCALE(widget), FALSE); - gtk_widget_set_size_request(widget, width, height); - gtk_fixed_put(GTK_FIXED(owner->info.container), widget, x, y); - gtk_widget_show(widget); - - g_signal_connect_swapped(G_OBJECT(widget), "value-changed", G_CALLBACK(libui_control_changed), (gpointer)this); -} - -void Slider::set_position(uint position) { - gtk_range_set_value(GTK_RANGE(widget), position); -} - -uint Slider::get_position() { - return (int)gtk_range_get_value(GTK_RANGE(widget)); -} - -}; diff --git a/src/lib/libui_gtk_control.h b/src/lib/libui_gtk_control.h deleted file mode 100644 index f1b1f639..00000000 --- a/src/lib/libui_gtk_control.h +++ /dev/null @@ -1,265 +0,0 @@ -namespace ControlType { - enum { - Invalid, - MenuBar, - MenuGroup, - MenuItem, - MenuCheckItem, - MenuRadioItem, - MenuSeparator, - Panel, - Container, - Canvas, - Frame, - Label, - Button, - Checkbox, - Radiobox, - Editbox, - Listbox, - Combobox, - Progressbar, - Slider, - }; -}; - -class Control { public: -uint type; - void move(uint x, uint y); - void resize(uint width, uint height); - - void focus(); - - void show(bool state); - void show(); - void hide(); - bool visible(); - - void enable(bool state); - void enable(); - void disable(); - bool enabled(); - -//protected: -Window *owner; -GtkWidget *widget; -uint id; - -public: - Control() : owner(0), widget(0), id(0), type(ControlType::Invalid) {} -}; - -class ControlGroup { public: - uint count() { return list.size(); } - void add(Control &control) { list[list.size()] = &control; } - void reset() { list.reset(); } - ControlGroup &operator=(ControlGroup &source) { list = source.list; return *this; } - Control &operator[](int index) { return *list[index]; } - -private: -array list; -}; - -class MenuBar : public Control { public: - void create(Window &owner); - void finish(); -}; - -class MenuGroup : public Control { public: - void create(MenuBar &owner, const char *caption); - void create(MenuGroup &owner, const char *caption); - void finish(); - -private: -GtkWidget *parent, *item; -}; - -class MenuItem : public Control { public: - void create(MenuGroup &owner, const char *caption); - -private: -GtkWidget *parent; -}; - -class MenuCheckItem : public Control { public: - void create(MenuGroup &owner, const char *caption); - void check(); - void uncheck(); - void check(bool state); - bool checked(); - -private: -GtkWidget *parent; -}; - -class MenuRadioItem : public Control { public: - void create(MenuGroup &owner, ControlGroup &list, const char *caption); - void check(); - bool checked(); - -private: -GtkWidget *parent; -}; - -class MenuSeparator : public Control { public: - void create(MenuGroup &owner); - -private: -GtkWidget *parent; -}; - -class Panel : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void attach(Window &window); - void detach(); - -private: -Window *attached; - -public: - Panel() : attached(0) {} -}; - -class Container : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void set_background_color(uint8 r, uint8 g, uint8 b); - -//platform-dependent: - unsigned long x_handle(); - GtkWidget *handle(); -}; - -class Canvas : public Control { public: -uint32 *buffer; -uint pitch; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void redraw(); - Canvas(); - ~Canvas(); - -private: -uint32 *rbuffer; - friend void libui_canvas_expose(GtkWidget *widget, GdkEventAny *any, Canvas *canvas); -}; - -class Frame : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); -}; - -class Label : public Control { public: -enum { ideal_height = 18 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void set_text(const char *str); -}; - -class Button : public Control { public: -enum { ideal_height = 30 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void set_text(const char *str); -}; - -class Checkbox : public Control { public: -enum { ideal_height = 18 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void check(); - void uncheck(); - void check(bool state); - bool checked(); -}; - -class Radiobox : public Control { public: -enum { ideal_height = 18 }; - void create(Window &owner, ControlGroup &group, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void check(); - bool checked(); -}; - -class Editbox : public Control { public: -enum { ideal_height = 30 }; -enum { - Multiline = (1 << 1), - Readonly = (1 << 2), - - HorizontalScrollAuto = 0, - HorizontalScrollAlways = (1 << 3), - HorizontalScrollNever = (1 << 4), - - VerticalScrollAuto = 0, - VerticalScrollAlways = (1 << 5), - VerticalScrollNever = (1 << 6), -}; - - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void set_text(const char *str); - uint get_text(char *str, uint length); - -private: -GtkWidget *subwidget; -GtkTextBuffer *buffer; -bool multiline; -}; - -class Listbox : public Control { public: -enum { - Header = (1 << 1), - - HorizontalScrollAuto = 0, - HorizontalScrollAlways = (1 << 2), - HorizontalScrollNever = (1 << 3), - - VerticalScrollAuto = 0, - VerticalScrollAlways = (1 << 4), - VerticalScrollNever = (1 << 5), -}; - - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *columns = ""); - void autosize_columns(); - void set_column_width(uint column, uint width); - void add_item(const char *data); - void set_item(uint index, const char *data); - int get_selection(); - void set_selection(int index); - void reset(); - -private: -GtkWidget *subwidget; -GtkListStore *store; -GtkCellRenderer *renderer; -GtkTreeViewColumn *column; -array column_list; -GtkTreeIter iter; -}; - -class Combobox : public Control { public: -enum { ideal_height = 30 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void add_item(const char *data); - int get_selection(); - void set_selection(int index); - void reset(); - -private: -uint counter; -}; - -class Progressbar : public Control { public: -enum { ideal_height = 30 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void set_progress(uint progress); - uint get_progress(); -}; - -class Slider : public Control { public: -enum { ideal_height = 25 }; -enum { - Horizontal = 0, - Vertical = 1, -}; - - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, uint range); - void set_position(uint position); - uint get_position(); - -private: -bool orientation; -}; diff --git a/src/lib/libui_gtk_window.cpp b/src/lib/libui_gtk_window.cpp deleted file mode 100644 index 496c361a..00000000 --- a/src/lib/libui_gtk_window.cpp +++ /dev/null @@ -1,119 +0,0 @@ -namespace libui { - -gint libui_window_close(GtkWidget *w, GdkEventAny *any, Window *window) { - if(window) { return !window->message(Message::Close); } - return FALSE; //destroy window by default -} - -gint libui_window_keydown(GtkWidget *w, GdkEventKey *key, Window *window) { - if(window) { window->message(Message::KeyDown, libui::translate_key(key->keyval)); } - return FALSE; -} - -gint libui_window_keyup(GtkWidget *w, GdkEventKey *key, Window *window) { - if(window) { window->message(Message::KeyUp, libui::translate_key(key->keyval)); } - return FALSE; -} - -void libui_control_clicked(Control *control) { - if(control && control->owner) { control->owner->message(Message::Clicked, (uintptr_t)control); } -} - -void libui_control_changed(Control *control) { - if(control && control->owner) { control->owner->message(Message::Changed, (uintptr_t)control); } -} - -void libui_control_double_clicked(Control *control) { - if(control && control->owner) { control->owner->message(Message::DoubleClicked, (uintptr_t)control); } -} - -void Window::create(uint style, uint width, uint height, const char *caption) { - info.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(info.window), caption ? caption : ""); - gtk_window_set_resizable(GTK_WINDOW(info.window), false); - g_signal_connect(G_OBJECT(info.window), "delete_event", G_CALLBACK(libui_window_close), (gpointer)this); - g_signal_connect(G_OBJECT(info.window), "key_press_event", G_CALLBACK(libui_window_keydown), (gpointer)this); - g_signal_connect(G_OBJECT(info.window), "key_release_event", G_CALLBACK(libui_window_keyup), (gpointer)this); - - if(style & Center) { gtk_window_set_position(GTK_WINDOW(info.window), GTK_WIN_POS_CENTER_ALWAYS); } - - info.vcontainer = gtk_vbox_new(false, 0); - gtk_container_add(GTK_CONTAINER(info.window), info.vcontainer); - gtk_widget_show(info.vcontainer); - -//always create menubar, only display it when MenuBar type is created -//this is needed to setup box packing before menubar is defined - info.menubar = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(info.vcontainer), info.menubar, false, false, 0); - - info.container = gtk_fixed_new(); - gtk_widget_set_size_request(info.container, width, height); - gtk_box_pack_end(GTK_BOX(info.vcontainer), info.container, true, true, 0); - gtk_widget_show(info.container); -} - -void Window::focus() { - gtk_window_present(GTK_WINDOW(info.window)); -} - -bool Window::focused() { - return gtk_window_is_active(GTK_WINDOW(info.window)); -} - -void Window::move(uint x, uint y) { -//if window was centered before, GTK+ will ignore move requests, -//therfore we must turn off auto-centering. - gtk_window_set_position(GTK_WINDOW(info.window), GTK_WIN_POS_NONE); - gtk_window_move(GTK_WINDOW(info.window), x, y); -} - -void Window::resize(uint width, uint height) { - gtk_widget_set_size_request(info.container, width, height); -} - -void Window::show() { - gtk_widget_show(info.window); -} - -void Window::hide() { - gtk_widget_hide(info.window); -} - -void Window::show(bool state) { - (state == true) ? show() : hide(); -} - -bool Window::visible() { - return GTK_WIDGET_VISIBLE(info.window); -} - -void Window::fullscreen() { - gtk_window_fullscreen(GTK_WINDOW(info.window)); -} - -void Window::unfullscreen() { - gtk_window_unfullscreen(GTK_WINDOW(info.window)); -} - -void Window::fullscreen(bool state) { - (state == true) ? fullscreen() : unfullscreen(); -} - -bool Window::is_fullscreen() { - return false; -}; - -void Window::set_text(const char *str) { - gtk_window_set_title(GTK_WINDOW(info.window), str); -} - -void Window::set_background_color(uint8 r, uint8 g, uint8 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(info.window, GTK_STATE_NORMAL, &color); -} - -}; diff --git a/src/lib/libui_win.cpp b/src/lib/libui_win.cpp deleted file mode 100644 index 23f3c2e3..00000000 --- a/src/lib/libui_win.cpp +++ /dev/null @@ -1,239 +0,0 @@ -#define _WIN32_IE 0x0600 - -#include "libui_win.h" -#include "libui_win_window.cpp" -#include "libui_win_control.cpp" - -namespace libui { - -long __stdcall canvas_wndproc(HWND, UINT, WPARAM, LPARAM); -long __stdcall label_wndproc (HWND, UINT, WPARAM, LPARAM); - -HFONT create_font(const char *name, uint size) { -HDC hdc = GetDC(0); -HFONT font = CreateFont(-MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72), - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, name); - ReleaseDC(0, hdc); - return font; -} - -void init() { - InitCommonControls(); - -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 = libui_wndproc; - wc.lpszClassName = "libui_class"; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); - - font.variable = create_font("Tahoma", 8); - font.fixed = create_font("Courier New", 8); - - 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 = canvas_wndproc; - wc.lpszClassName = "canvas_class"; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&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 = label_wndproc; - wc.lpszClassName = "label_class"; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); -} - -void term() { -} - -bool run() { -MSG msg; - if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return events_pending(); -} - -bool events_pending() { -MSG msg; - return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); -} - -uint get_screen_width() { return GetSystemMetrics(SM_CXSCREEN); } -uint get_screen_height() { return GetSystemMetrics(SM_CYSCREEN); } - -// - -bool file_load(Window *owner, char *filename, const char *filter, const char *path) { -string dir, f; - strcpy(dir, path ? path : ""); - replace(dir, "/", "\\"); - -stringarray type, part; - strcpy(f, ""); - split(type, "|", filter); - for(int i = 0; i < count(type); i++) { - split(part, ";", type[i]); - if(count(part) != 2)continue; - - strcat(f, part[0]); - strcat(f, " ("); - strcat(f, part[1]); - strcat(f, ")|"); - replace(part[1], ",", ";"); - strcat(f, part[1]); - strcat(f, "|"); - } - -char *pf = strptr(f); - for(int i = strlen(pf) - 1; i >= 0; i--) { - if(pf[i] == '|')pf[i] = '\0'; - } - -OPENFILENAME ofn; - strcpy(filename, ""); - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = owner ? owner->info.hwnd : 0; - ofn.lpstrFilter = pf; - ofn.lpstrInitialDir = strptr(dir); - ofn.lpstrFile = filename; - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; - ofn.lpstrDefExt = ""; - - return GetOpenFileName(&ofn); -} - -bool file_save(Window *owner, char *filename, const char *filter, const char *path) { -string dir, f; - strcpy(dir, path ? path : ""); - replace(dir, "/", "\\"); - -stringarray type, part; - strcpy(f, ""); - split(type, "|", filter); - for(int i = 0; i < count(type); i++) { - split(part, ";", type[i]); - if(count(part) != 2)continue; - - strcat(f, part[0]); - strcat(f, " ("); - strcat(f, part[1]); - strcat(f, ")|"); - replace(part[1], ",", ";"); - strcat(f, part[1]); - strcat(f, "|"); - } - -char *pf = strptr(f); - for(int i = strlen(pf) - 1; i >= 0; i--) { - if(pf[i] == '|')pf[i] = '\0'; - } - -OPENFILENAME ofn; - strcpy(filename, ""); - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = owner ? owner->info.hwnd : 0; - ofn.lpstrFilter = pf; - ofn.lpstrInitialDir = strptr(dir); - ofn.lpstrFile = filename; - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; - ofn.lpstrDefExt = ""; - - return GetSaveFileName(&ofn); -} - -// - -uint16 translate_key(uint key) { - switch(key) { - - case VK_ESCAPE: return keymap::esc; - - case VK_F1: return keymap::f1; - case VK_F2: return keymap::f2; - case VK_F3: return keymap::f3; - case VK_F4: return keymap::f4; - case VK_F5: return keymap::f5; - case VK_F6: return keymap::f6; - case VK_F7: return keymap::f7; - case VK_F8: return keymap::f8; - case VK_F9: return keymap::f9; - case VK_F10: return keymap::f10; - case VK_F11: return keymap::f11; - case VK_F12: return keymap::f12; - - case VK_TAB: return keymap::tab; - case VK_RETURN: return keymap::enter; - case VK_SPACE: return keymap::space; - - case '0': return keymap::num_0; - case '1': return keymap::num_1; - case '2': return keymap::num_2; - case '3': return keymap::num_3; - case '4': return keymap::num_4; - case '5': return keymap::num_5; - case '6': return keymap::num_6; - case '7': return keymap::num_7; - case '8': return keymap::num_8; - case '9': return keymap::num_9; - - case 'A': return keymap::a; - case 'B': return keymap::b; - case 'C': return keymap::c; - case 'D': return keymap::d; - case 'E': return keymap::e; - case 'F': return keymap::f; - case 'G': return keymap::g; - case 'H': return keymap::h; - case 'I': return keymap::i; - case 'J': return keymap::j; - case 'K': return keymap::k; - case 'L': return keymap::l; - case 'M': return keymap::m; - case 'N': return keymap::n; - case 'O': return keymap::o; - case 'P': return keymap::p; - case 'Q': return keymap::q; - case 'R': return keymap::r; - case 'S': return keymap::s; - case 'T': return keymap::t; - case 'U': return keymap::u; - case 'V': return keymap::v; - case 'W': return keymap::w; - case 'X': return keymap::x; - case 'Y': return keymap::y; - case 'Z': return keymap::z; - - case VK_UP: return keymap::up; - case VK_DOWN: return keymap::down; - case VK_LEFT: return keymap::left; - case VK_RIGHT: return keymap::right; - - } - return keymap::none; -} - -}; diff --git a/src/lib/libui_win.h b/src/lib/libui_win.h deleted file mode 100644 index 26ec2645..00000000 --- a/src/lib/libui_win.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - libui_win ~byuu (2007-06-10) - license: public domain -*/ - -#ifndef LIBUI_H -#define LIBUI_H - -#include "libbase.h" -#include "libarray.h" -#include "libvector.h" -#include "libstring.h" -#include "libkeymap.h" - -#undef WINVER -#undef _WIN32_WINNT -#define WINVER 0x0500 -#define _WIN32_WINNT 0x0500 -#include -#include - -namespace libui { - -class Window; -#include "libui_win_control.h" - -void init(); -void term(); -bool run(); -bool events_pending(); - -uint get_screen_width(); -uint get_screen_height(); - -bool file_load(Window *owner, char *filename, const char *filter, const char *path = ""); -bool file_save(Window *owner, char *filename, const char *filter, const char *path = ""); - -uint16 translate_key(uint key); - -namespace Message { - enum { - Invalid = 0, - Close, - Block, - KeyUp, - KeyDown, - Clicked, - DoubleClicked, - Changed, - }; -}; - -class Window { public: -enum Style { - Center = 1, -}; - -MenuBar menu; - void create(uint style, uint width, uint height, const char *caption = ""); - void set_text(const char *str, ...); - void set_background_color(uint8 r, uint8 g, uint8 b); - void focus(); - bool focused(); - void move(uint x, uint y); - void resize(uint width, uint height); - virtual void show(); - virtual void hide(); - void show(bool state); - bool visible(); - void fullscreen(); - void unfullscreen(); - void fullscreen(bool state); - bool is_fullscreen(); - - virtual bool message(uint id, uintptr_t param = 0) { return true; } - - void move(Control &control, uint x, uint y); - void attach(Control &control); - - Window(); - -//platform-dependent: - HWND handle(); - -//private: -struct { - uint width, height; - bool fullscreen; - - HWND hwnd; - HWND hwnd_resize; - HBRUSH background; - HMENU menubar; - bool center; - array control; - uint control_index; - - array menu_check_list; -} info; - long wndproc(HWND hwnd, uint msg, WPARAM wparam, LPARAM lparam); -}; - -//platform-dependent: - -static uint window_count = 0; - -static struct { - HFONT variable; - HFONT fixed; -} font; - -HFONT create_font(const char *name, uint size); - -}; - -#endif diff --git a/src/lib/libui_win_control.cpp b/src/lib/libui_win_control.cpp deleted file mode 100644 index 1594467b..00000000 --- a/src/lib/libui_win_control.cpp +++ /dev/null @@ -1,710 +0,0 @@ -namespace libui { - -/***** - * Control - *****/ - -void Control::move(uint x, uint y) { - SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); -} - -void Control::resize(uint width, uint height) { - SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE); -} - -void Control::focus() { - if(hwnd) { SetFocus(hwnd); } -} - -void Control::show() { - ShowWindow(hwnd, SW_NORMAL); -} - -void Control::hide() { - ShowWindow(hwnd, SW_HIDE); -} - -void Control::show(bool state) { - (state == true) ? show() : hide(); -} - -bool Control::visible() { - return (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) ? true : false; -} - -void Control::enable() { - EnableWindow(hwnd, true); -} - -void Control::disable() { - EnableWindow(hwnd, false); -} - -void Control::enable(bool state) { - (state == true) ? enable() : disable(); -} - -bool Control::enabled() { - return !(GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED); -} - -/***** - * MenuBar - *****/ - -void MenuBar::create(Window &r_owner) { - type = ControlType::MenuBar; - group = CreateMenu(); - r_owner.attach(*this); - owner->info.menu_check_list.reset(); -} - -void MenuBar::finish() { - show(); - -//check all menu radio items that need to be ... - for(uint i = 0; i < owner->info.menu_check_list.size(); i++) { - CheckMenuItem(owner->info.menu_check_list[i]->parent, owner->info.menu_check_list[i]->id, MF_CHECKED); - } - owner->info.menu_check_list.reset(); -} - -void MenuBar::show() { - SetMenu(owner->info.hwnd_resize, group); - SetMenu(owner->info.hwnd, group); - owner->resize(owner->info.width, owner->info.height); -} - -void MenuBar::hide() { - SetMenu(owner->info.hwnd_resize, 0); - SetMenu(owner->info.hwnd, 0); - owner->resize(owner->info.width, owner->info.height); -} - -void MenuBar::show(bool state) { - (state == true) ? show() : hide(); -} - -bool MenuBar::visible() { - return GetMenu(owner->info.hwnd); -} - -/***** - * MenuGroup - *****/ - -void MenuGroup::create(MenuBar &r_owner, const char *_caption) { - type = ControlType::MenuGroup; - owner = r_owner.owner; - parent = r_owner.group; - group = CreatePopupMenu(); - caption = strdup(_caption); - owner->attach(*this); -} - -void MenuGroup::create(MenuGroup &r_owner, const char *_caption) { - type = ControlType::MenuGroup; - owner = r_owner.owner; - parent = r_owner.group; - group = CreatePopupMenu(); - caption = strdup(_caption); - owner->attach(*this); -} - -void MenuGroup::finish() { - AppendMenu(parent, MF_STRING | MF_POPUP, (uint)group, caption); -} - -/***** - * MenuItem - *****/ - -void MenuItem::create(MenuGroup &r_owner, const char *caption) { - type = ControlType::MenuItem; - owner = r_owner.owner; - owner->attach(*this); - AppendMenu(r_owner.group, MF_STRING, (uint)id, caption); -} - -/***** - * MenuCheckItem - *****/ - -void MenuCheckItem::create(MenuGroup &r_owner, const char *caption) { - type = ControlType::MenuCheckItem; - owner = r_owner.owner; - parent = r_owner.group; - owner->attach(*this); - AppendMenu(r_owner.group, MF_STRING, (uint)id, caption); -} - -void MenuCheckItem::check() { - if(checked() == true)return; - CheckMenuItem(parent, id, MF_CHECKED); - owner->message(Message::Clicked, (uintptr_t)this); -} - -void MenuCheckItem::uncheck() { - if(checked() == false)return; - CheckMenuItem(parent, id, MF_UNCHECKED); - owner->message(Message::Clicked, (uintptr_t)this); -} - -void MenuCheckItem::check(bool state) { - (state == true) ? check() : uncheck(); -} - -bool MenuCheckItem::checked() { -MENUITEMINFO info; - memset(&info, 0, sizeof(info)); - info.cbSize = sizeof(info); - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, id, false, &info); - return (info.fState & MFS_CHECKED); -} - -/***** - * MenuRadioItem - *****/ - -void MenuRadioItem::create(MenuGroup &r_owner, ControlGroup &list, const char *caption) { - if(list.count() == 0)throw; - type = ControlType::MenuRadioItem; - owner = r_owner.owner; - parent = r_owner.group; - owner->attach(*this); - AppendMenu(r_owner.group, MF_STRING, (uint)id, caption); - group = list; - if(&group[0] == this) { owner->info.menu_check_list[owner->info.menu_check_list.size()] = this; } -} - -void MenuRadioItem::check() { - if(checked() == true)return; -//uncheck all items in group except for current item ... - for(uint i = 0; i < group.count(); i++) { - CheckMenuItem(parent, group[i].id, (id == group[i].id) ? MF_CHECKED : MF_UNCHECKED); - } - owner->message(Message::Clicked, (uintptr_t)this); -} - -bool MenuRadioItem::checked() { -MENUITEMINFO info; - memset(&info, 0, sizeof(info)); - info.cbSize = sizeof(info); - info.fMask = MIIM_STATE; - GetMenuItemInfo(parent, id, false, &info); - return (info.fState & MFS_CHECKED); -} - -/***** - * MenuSeparator - *****/ - -void MenuSeparator::create(MenuGroup &r_owner) { - AppendMenu(r_owner.group, MF_SEPARATOR, 0, ""); -} - -/***** - * Panel - *****/ - -void Panel::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Panel; - hwnd = CreateWindow("libui_class", "", WS_CHILD | WS_VISIBLE, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - r_owner.attach(*this); -} - -void Panel::attach(Window &window) { - if(attached) { detach(); } - attached = &window; - SetParent(attached->info.hwnd, hwnd); - SetWindowLong(attached->info.hwnd, GWL_STYLE, WS_CHILD); - SetWindowPos(attached->info.hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE); - ShowWindow(attached->info.hwnd, SW_NORMAL); -} - -void Panel::detach() { - if(!attached) { return; } - ShowWindow(attached->info.hwnd, SW_HIDE); - SetWindowLong(attached->info.hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX); - SetParent(attached->info.hwnd, NULL); - attached = 0; -} - -/***** - * Container - *****/ - -void Container::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Container; - -char classname[4096]; - sprintf(classname, "libui_class_%d", window_count++); -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 = libui_wndproc; - wc.lpszClassName = classname; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - RegisterClass(&wc); - - hwnd = CreateWindow(classname, "", WS_CHILD | WS_VISIBLE, - 0, 0, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); -} - -void Container::set_background_color(uint8 r, uint8 g, uint8 b) { -HBRUSH old_brush = background; - background = (HBRUSH)CreateSolidBrush(RGB(r, g, b)); - SetClassLong(hwnd, GCL_HBRBACKGROUND, (LONG)background); - InvalidateRect(hwnd, 0, TRUE); - if(old_brush) { DeleteObject((HGDIOBJ)old_brush); } -} - -HWND Container::handle() { - return hwnd; -} - -Container::Container() { - background = 0; -} - -/***** - * Canvas - *****/ - -long __stdcall canvas_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch(msg) { - - case WM_PAINT: { - Canvas *canvas = (Canvas*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - if(canvas) { canvas->blit(); } - } break; - - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -void Canvas::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - _w = width; - _h = height; - - type = ControlType::Canvas; - hwnd = CreateWindow("canvas_class", "", WS_CHILD | WS_VISIBLE, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); - - pitch = width * sizeof(uint32); - buffer = (uint32*)malloc(pitch * height); - memset(buffer, 0, pitch * height); - - memset(&bmi, 0, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = width; - bmi.bmiHeader.biHeight = -height; //use negative height to tell GDI not to flip bitmap vertically - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = pitch * height; - - r_owner.attach(*this); -} - -void Canvas::blit() { -PAINTSTRUCT ps; - BeginPaint(hwnd, &ps); - SetDIBitsToDevice(ps.hdc, 0, 0, _w, _h, 0, 0, 0, _h, (void*)buffer, &bmi, DIB_RGB_COLORS); - EndPaint(hwnd, &ps); -} - -void Canvas::redraw() { - InvalidateRect(hwnd, 0, FALSE); -} - -Canvas::Canvas() { - buffer = 0; -} - -Canvas::~Canvas() { - safe_free(buffer); -} - -/***** - * Frame - *****/ - -void Frame::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Frame; - hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); -} - -/***** - * Label - *****/ - -long __stdcall label_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch(msg) { - - case WM_PAINT: { - PAINTSTRUCT ps; - BeginPaint(hwnd, &ps); - RECT rc; - char t[4096]; - GetWindowText(hwnd, t, 4095); //TODO: use internal buffer, so length is not limited ... - GetClientRect(hwnd, &rc); - SetTextColor(ps.hdc, RGB(0, 0, 0)); - SetBkMode(ps.hdc, TRANSPARENT); - SelectObject(ps.hdc, (HGDIOBJ)libui::font.variable); - //center text if text height < control height, otherwise draw from top left corner - RECT trc; - GetClientRect(hwnd, &trc); - DrawText(ps.hdc, t, strlen(t), &trc, DT_CALCRECT); - if(trc.bottom < rc.bottom) { - rc.top = (rc.bottom - trc.bottom) / 2; - rc.bottom = rc.top + trc.bottom; - } - // - DrawText(ps.hdc, t, strlen(t), &rc, DT_END_ELLIPSIS | DT_NOPREFIX); - EndPaint(hwnd, &ps); - } break; - - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -void Label::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { -string t; - strcpy(t, caption ? caption : ""); - replace(t, "\r", ""); - replace(t, "\n", "\r\n"); - - type = ControlType::Label; - hwnd = CreateWindow("label_class", strptr(t), WS_CHILD | WS_VISIBLE, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); -} - -void Label::set_text(const char *str, ...) { -va_list args; - va_start(args, str); -string temp; - vsprintf(temp, str, args); - va_end(args); - SetWindowText(hwnd, strptr(temp)); - InvalidateRect(hwnd, 0, TRUE); -} - -/***** - * Button - *****/ - -void Button::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Button; - hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); -} - -/***** - * Checkbox - *****/ - -void Checkbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Checkbox; - hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); -} - -void Checkbox::check() { - if(checked() == true)return; - SendMessage(hwnd, BM_SETCHECK, (WPARAM)TRUE, 0); - owner->message(Message::Clicked, (uintptr_t)this); -} - -void Checkbox::uncheck() { - if(checked() == false)return; - SendMessage(hwnd, BM_SETCHECK, (WPARAM)FALSE, 0); - owner->message(Message::Clicked, (uintptr_t)this); -} - -void Checkbox::check(bool state) { - (state == true) ? check() : uncheck(); -} - -bool Checkbox::checked() { - return SendMessage(hwnd, BM_GETCHECK, 0, 0); -} - -/***** - * Radiobox - *****/ - -void Radiobox::create(Window &r_owner, ControlGroup &list, uint style, uint x, uint y, uint width, uint height, const char *caption) { - if(list.count() == 0)throw; - type = ControlType::Radiobox; - group = list; - hwnd = CreateWindow("BUTTON", caption ? caption : "", WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); - if(this == &group[0])check(); -} - -void Radiobox::check() { - if(checked() == true)return; - for(uint i = 0; i < group.count(); i++) { - SendMessage(group[i].hwnd, BM_SETCHECK, (group[i].hwnd == hwnd) ? (WPARAM)TRUE : (WPARAM)FALSE, 0); - } - owner->message(Message::Clicked, (uintptr_t)this); -} - -bool Radiobox::checked() { - return SendMessage(hwnd, BM_GETCHECK, 0, 0); -} - -/***** - * Editbox - *****/ - -void Editbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *caption) { - type = ControlType::Editbox; - multiline = (style & Multiline); - readonly = (style & Readonly); - vscroll = false; - hscroll = false; - -uint hscroll = (style & HorizontalScrollAlways) ? WS_HSCROLL : - (style & HorizontalScrollNever) ? 0 : - ES_AUTOHSCROLL; -uint vscroll = (style & VerticalScrollAlways) ? WS_VSCROLL : - (style & VerticalScrollNever) ? 0 : - ES_AUTOVSCROLL; - -string data = caption; - replace(data, "\r", ""); - replace(data, "\n", "\r\n"); - hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", strptr(data), - WS_CHILD | WS_VISIBLE | vscroll | hscroll | - (multiline == true ? ES_MULTILINE : 0) | - (readonly == true ? ES_READONLY : 0), - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); -} - -void Editbox::set_text(const char *str, ...) { -va_list args; - va_start(args, str); -string data; - vsprintf(data, str, args); - va_end(args); - - replace(data, "\r", ""); - replace(data, "\n", "\r\n"); - SetWindowText(hwnd, strptr(data)); -} - -uint Editbox::get_text(char *str, uint length) { - GetWindowText(hwnd, str, length); - return strlen(str); -} - -/***** - * Listbox - *****/ - -void Listbox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, const char *columns) { -stringarray part; - header = (style & Header); - -uint hscroll = (style & HorizontalScrollAlways) ? WS_HSCROLL : - (style & HorizontalScrollNever) ? 0 : - 0; -uint vscroll = (style & VerticalScrollAlways) ? WS_VSCROLL : - (style & VerticalScrollNever) ? 0 : - 0; - - type = ControlType::Listbox; - hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, "", - WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll | - (header == true ? 0 : LVS_NOCOLUMNHEADER), - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT); - - split(part, "|", columns); - column_count = count(part); - for(uint i = 0; i < column_count; i++) { - LVCOLUMN column; - column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM; - column.fmt = LVCFMT_LEFT; - column.iSubItem = count(part); - column.pszText = (LPSTR)strptr(part[i]); - ListView_InsertColumn(hwnd, i, &column); - } - - autosize_columns(); - r_owner.attach(*this); -} - -void Listbox::autosize_columns() { - for(uint i = 0; i < column_count; i++) { - ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER); - } -} - -void Listbox::set_column_width(uint column, uint width) { - ListView_SetColumnWidth(hwnd, column, width); -} - -void Listbox::add_item(const char *data, ...) { -va_list args; - va_start(args, data); -string temp; - vsprintf(temp, data, args); - va_end(args); - -stringarray part; - split(part, "|", temp); - -LVITEM item; -uint pos = ListView_GetItemCount(hwnd); - item.mask = LVIF_TEXT; - item.iItem = pos; - item.iSubItem = 0; - item.pszText = (LPSTR)strptr(part[0]); - ListView_InsertItem(hwnd, &item); - - for(uint i = 1; i < count(part); i++) { - ListView_SetItemText(hwnd, pos, i, (LPSTR)strptr(part[i])); - } -} - -void Listbox::set_item(uint index, const char *data, ...) { -va_list args; - va_start(args, data); -string temp; - vsprintf(temp, data, args); - va_end(args); - -stringarray part; - split(part, "|", temp); - - for(uint i = 0; i < count(part); i++) { - ListView_SetItemText(hwnd, index, i, strptr(part[i])); - } -} - -int Listbox::get_selection() { -uint count = ListView_GetItemCount(hwnd); - for(uint i = 0; i < count; i++) { - if(ListView_GetItemState(hwnd, i, LVIS_SELECTED))return i; - } - return -1; -} - -void Listbox::set_selection(int index) { -uint count = ListView_GetItemCount(hwnd); - for(uint 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 Listbox::reset() { - ListView_DeleteAllItems(hwnd); -} - -/***** - * Combobox - *****/ - -void Combobox::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Combobox; - hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "COMBOBOX", "", - WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, - x, y, width, 200, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, WM_SETFONT, (WPARAM)libui::font.variable, 0); - r_owner.attach(*this); -} - -void Combobox::add_item(const char *data) { - SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)data); - if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) { set_selection(0); } -} - -void Combobox::set_selection(int index) { - SendMessage(hwnd, CB_SETCURSEL, index, 0); -} - -int Combobox::get_selection() { - return SendMessage(hwnd, CB_GETCURSEL, 0, 0); -} - -void Combobox::reset() { - SendMessage(hwnd, CB_RESETCONTENT, 0, 0); -} - -/***** - * Progressbar - *****/ - -void Progressbar::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height) { - type = ControlType::Progressbar; - hwnd = CreateWindow(PROGRESS_CLASS, "", WS_CHILD | WS_VISIBLE | PBS_SMOOTH, - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); - SendMessage(hwnd, PBM_SETSTEP, MAKEWPARAM(1, 0), 0); - r_owner.attach(*this); -} - -void Progressbar::set_progress(uint progress) { - progress = minmax<0, 100>(progress); - SendMessage(hwnd, PBM_SETPOS, (WPARAM)progress, 0); -} - -uint Progressbar::get_progress() { - return minmax<0, 100>(SendMessage(hwnd, PBM_GETPOS, 0, 0)); -} - -/***** - * Slider - *****/ - -void Slider::create(Window &r_owner, uint style, uint x, uint y, uint width, uint height, uint range) { - type = ControlType::Slider; - orientation = (style & Vertical) ? 1 : 0; - if(range < 1)range = 1; - - hwnd = CreateWindow(TRACKBAR_CLASS, "", - WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_BOTH | (orientation == 0 ? TBS_HORZ : TBS_VERT), - x, y, width, height, r_owner.info.hwnd, (HMENU)0, GetModuleHandle(0), 0); - SendMessage(hwnd, TBM_SETRANGE, (WPARAM)true, (LPARAM)MAKELONG(0, range - 1)); - SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM)(range >> 3)); - SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)0); - r_owner.attach(*this); -} - -void Slider::set_position(uint position) { - SendMessage(hwnd, TBM_SETPOS, (WPARAM)true, (LPARAM)position); -} - -uint Slider::get_position() { - return SendMessage(hwnd, TBM_GETPOS, 0, 0); -} - -}; diff --git a/src/lib/libui_win_control.h b/src/lib/libui_win_control.h deleted file mode 100644 index 07883449..00000000 --- a/src/lib/libui_win_control.h +++ /dev/null @@ -1,271 +0,0 @@ -namespace ControlType { - enum { - Invalid, - MenuBar, - MenuGroup, - MenuItem, - MenuCheckItem, - MenuRadioItem, - MenuSeparator, - Panel, - Container, - Canvas, - Frame, - Label, - Button, - Checkbox, - Radiobox, - Editbox, - Listbox, - Combobox, - Progressbar, - Slider, - }; -}; - -class Control { public: -uint type; - void move(uint x, uint y); - void resize(uint width, uint height); - - void focus(); - - virtual void show(); - virtual void hide(); - virtual void show(bool state); - virtual bool visible(); - - void enable(); - void disable(); - void enable(bool state); - bool enabled(); - -//private: -Window *owner; -HWND hwnd; -uint id; - -public: - Control() : owner(0), hwnd(0), id(0), type(ControlType::Invalid) {} -}; - -class ControlGroup { public: - uint count() { return list.size(); } - void add(Control &control) { list[list.size()] = &control; } - void reset() { list.reset(); } - ControlGroup &operator=(ControlGroup &source) { list = source.list; return *this; } - Control &operator[](int index) { return *list[index]; } - -//private: -array list; -}; - -// - -class MenuBar : public Control { public: - void create(Window &owner); - void finish(); - - void show(); - void hide(); - void show(bool state); - bool visible(); - -//private: -HMENU group; -}; - -class MenuGroup : public Control { public: - void create(MenuBar &owner, const char *caption); - void create(MenuGroup &owner, const char *caption); - void finish(); - -//private: -HMENU parent, group; -char *caption; - ~MenuGroup() { safe_free(caption); } -}; - -class MenuItem : public Control { public: - void create(MenuGroup &owner, const char *caption); -}; - -class MenuCheckItem : public Control { public: - void create(MenuGroup &owner, const char *caption); - void check(); - void uncheck(); - void check(bool state); - bool checked(); - -//private: -HMENU parent; -}; - -class MenuRadioItem : public Control { public: - void create(MenuGroup &owner, ControlGroup &list, const char *caption); - void check(); - bool checked(); - -//private: -HMENU parent; -ControlGroup group; -}; - -class MenuSeparator : public Control { public: - void create(MenuGroup &owner); -}; - -// - -class Panel : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void attach(Window &window); - void detach(); - -//private: -Window *attached; - Panel() : attached(0) {} -}; - -class Container : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void set_background_color(uint8 r, uint8 g, uint8 b); - -//platform-dependent: - HWND handle(); - -//private: -HBRUSH background; - Container(); -}; - -class Canvas : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void redraw(); - -//private: -BITMAPINFO bmi; -uint32 *buffer; -uint pitch, _w, _h; - void blit(); - Canvas(); - ~Canvas(); -}; - -class Frame : public Control { public: - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); -}; - -class Label : public Control { public: -enum { ideal_height = 16 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void set_text(const char *str, ...); -}; - -class Button : public Control { public: -enum { ideal_height = 21 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); -}; - -class Checkbox : public Control { public: -enum { ideal_height = 15 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void check(); - void uncheck(); - void check(bool state); - bool checked(); -}; - -class Radiobox : public Control { public: -enum { ideal_height = 15 }; - void create(Window &owner, ControlGroup &list, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void check(); - bool checked(); - -//private: -ControlGroup group; -}; - -class Editbox : public Control { public: -enum { ideal_height = 21 }; -enum { - Multiline = (1 << 1), - Readonly = (1 << 2), - - HorizontalScrollAuto = 0, - HorizontalScrollAlways = (1 << 3), - HorizontalScrollNever = (1 << 4), - - VerticalScrollAuto = 0, - VerticalScrollAlways = (1 << 5), - VerticalScrollNever = (1 << 6), -}; - - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = ""); - void set_text(const char *str, ...); - uint get_text(char *str, uint length); - -//private: -bool multiline; -bool readonly; -bool vscroll; -bool hscroll; -}; - -class Listbox : public Control { public: -enum { - Header = (1 << 1), - - HorizontalScrollAuto = 0, - HorizontalScrollAlways = (1 << 2), - HorizontalScrollNever = (1 << 3), - - VerticalScrollAuto = 0, - VerticalScrollAlways = (1 << 4), - VerticalScrollNever = (1 << 5), -}; - - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *columns = ""); - void autosize_columns(); - void set_column_width(uint column, uint width); - void add_item(const char *data, ...); - void set_item(uint index, const char *data, ...); - int get_selection(); - void set_selection(int index); - void reset(); - -//private: -bool header; -uint column_count; -}; - -class Combobox : public Control { public: -enum { ideal_height = 21 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void add_item(const char *data); - void set_selection(int index); - int get_selection(); - void reset(); -}; - -class Progressbar : public Control { public: -enum { ideal_height = 30 }; - void create(Window &owner, uint style, uint x, uint y, uint width, uint height); - void set_progress(uint progress); - uint get_progress(); -}; - -class Slider : public Control { public: -enum { ideal_height = 25 }; -enum Style { - Horizontal = 0, - Vertical = 1, -}; - - void create(Window &owner, uint style, uint x, uint y, uint width, uint height, uint range); - void set_position(uint position); - uint get_position(); - -//private: -bool orientation; -}; diff --git a/src/lib/libui_win_window.cpp b/src/lib/libui_win_window.cpp deleted file mode 100644 index b2e814fd..00000000 --- a/src/lib/libui_win_window.cpp +++ /dev/null @@ -1,290 +0,0 @@ -namespace libui { - -long __stdcall libui_wndproc(HWND hwnd, uint msg, WPARAM wparam, LPARAM lparam) { -Window *window = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - if(window) { return window->wndproc(hwnd, msg, wparam, lparam); } - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -long Window::wndproc(HWND hwnd, uint msg, WPARAM wparam, LPARAM lparam) { - switch(msg) { - - case WM_CLOSE: { - if(message(Message::Close) == false) { return TRUE; } - } break; - - case WM_ENTERMENULOOP: { - message(Message::Block); - } - - case WM_PAINT: { - uint16 i = LOWORD(wparam); - if(!i || !info.control[i])break; - Control &control = *info.control[i]; - if(control.id != i)break; //this should never happen - - switch(control.type) { - - case ControlType::Canvas: { - ((Canvas&)control).redraw(); - } break; - - } - } break; - - case WM_KEYDOWN: { - message(Message::KeyDown, libui::translate_key(wparam)); - } break; - - case WM_KEYUP: { - message(Message::KeyUp, libui::translate_key(wparam)); - } break; - - case WM_COMMAND: { - uint16 i = LOWORD(wparam); - if(!i || !info.control[i])break; - Control &control = *info.control[i]; - if(control.id != i)break; //this should never happen - - switch(control.type) { - - //emit Message::Clicked message indirectly, through control.check() - case ControlType::MenuCheckItem: { - ((MenuCheckItem&)control).check(!((MenuCheckItem&)control).checked()); //toggle checked status - } break; - - case ControlType::MenuRadioItem: { - ((MenuRadioItem&)control).check(); - } break; - - case ControlType::Checkbox: { - ((Checkbox&)control).check(!((Checkbox&)control).checked()); //toggle checked status - } break; - - case ControlType::Radiobox: { - ((Radiobox&)control).check(); - } break; - - //emit Message::Clicked message directly - case ControlType::MenuItem: - case ControlType::Button: { - message(Message::Clicked, (uintptr_t)&control); - } break; - - } - } break; - - case WM_HSCROLL: - case WM_VSCROLL: { - uint16 i = GetDlgCtrlID((HWND)lparam); - if(!i || !info.control[i])break; - Control &control = *info.control[i]; - if(control.id != i)break; - - switch(control.type) { - - case ControlType::Slider: { - message(Message::Changed, (uintptr_t)&control); - } break; - - } - } break; - - case WM_NOTIFY: { - uint16 i = (uint16)wparam; - if(!i || !info.control[i])break; - Control &control = *info.control[i]; - if(control.id != i)break; - - switch(control.type) { - - case ControlType::Listbox: { - Listbox &listbox = ((Listbox&)control); - if(((LPNMHDR)lparam)->code == LVN_ITEMCHANGED) { - if(((LPNMLISTVIEW)lparam)->uChanged & LVIF_STATE) { - if(ListView_GetItemState(listbox.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_FOCUSED)) { - if(ListView_GetItemState(listbox.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_SELECTED)) { - message(Message::Changed, (uintptr_t)&control); - } - } - } - } else if(((LPNMHDR)lparam)->code == LVN_ITEMACTIVATE) { - message(Message::DoubleClicked, (uintptr_t)&control); - } - } break; - - } - } break; - - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -void Window::attach(Control &control) { - info.control[info.control_index] = &control; - control.id = info.control_index++; - control.owner = this; - -//menu items will not have HWND, and do not require GWL_ID to be set - if(control.hwnd) { SetWindowLong(control.hwnd, GWL_ID, control.id); } -} - -void Window::focus() { - if(!visible()) { show(); } - SetFocus(info.hwnd); -} - -bool Window::focused() { - return (GetForegroundWindow() == info.hwnd); -} - -void Window::move(Control &control, uint x, uint y) { - SetWindowPos(control.hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); -} - -void Window::create(uint style, uint width, uint height, const char *caption) { - info.center = bool(style & Center); - -char classname[4096]; - sprintf(classname, "libui_class_%d", window_count++); -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 = libui_wndproc; - wc.lpszClassName = classname; - wc.lpszMenuName = 0; - wc.style = CS_HREDRAW | CS_VREDRAW; - RegisterClass(&wc); - -RECT rc; - SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); - - info.hwnd = CreateWindowEx(0, classname, caption ? caption : "", - WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, - rc.left, rc.top, width, height, 0, 0, GetModuleHandle(0), 0); - info.hwnd_resize = CreateWindowEx(0, "libui_class", "", - WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, - rc.left, rc.top, width, height, 0, 0, GetModuleHandle(0), 0); - SetWindowLongPtr(info.hwnd, GWLP_USERDATA, (LONG_PTR)this); - - resize(width, height); -} - -void Window::move(uint x, uint y) { -RECT rc; - SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); - if(x < rc.left) { x = rc.left; } - if(y < rc.top ) { y = rc.top; } - SetWindowPos(info.hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE); -} - -void Window::resize(uint width, uint height) { - if(info.fullscreen == true) { - info.width = GetSystemMetrics(SM_CXSCREEN); - info.height = GetSystemMetrics(SM_CYSCREEN); - SetWindowPos(info.hwnd, 0, 0, 0, info.width, info.height, SWP_NOZORDER); - return; - } - - info.width = width; - info.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(info.hwnd_resize, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE); -RECT rc; - GetClientRect(info.hwnd_resize, &rc); - width += width - (rc.right - rc.left); - height += height - (rc.bottom - rc.top); - -int x = (GetSystemMetrics(SM_CXSCREEN) - int(width)) / 2; -int y = (GetSystemMetrics(SM_CYSCREEN) - int(height)) / 2; - -//do not allow window to be placed offscreen, force to top-left if window is larger than screen size - SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); - if(x < rc.left) { x = rc.left; } - if(y < rc.top) { y = rc.top; } - - SetWindowPos(info.hwnd, 0, x, y, width, height, SWP_NOZORDER | (info.center == true ? 0 : SWP_NOMOVE)); -} - -void Window::show() { - ShowWindow(info.hwnd, SW_NORMAL); - SetFocus(info.hwnd); -} - -void Window::hide() { - ShowWindow(info.hwnd, SW_HIDE); -} - -void Window::show(bool state) { - (state == true) ? show() : hide(); -} - -bool Window::visible() { - return GetWindowLong(info.hwnd, GWL_STYLE) & WS_VISIBLE; -} - -void Window::fullscreen() { - if(info.fullscreen)return; - info.fullscreen = true; - SetWindowLong(info.hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); - resize(get_screen_width(), get_screen_height()); -} - -void Window::unfullscreen() { - if(!info.fullscreen)return; - info.fullscreen = false; - SetWindowLong(info.hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE); - resize(info.width, info.height); -} - -void Window::fullscreen(bool state) { - (state == true) ? fullscreen() : unfullscreen(); -} - -bool Window::is_fullscreen() { - return info.fullscreen; -} - -// - -void Window::set_text(const char *str, ...) { -va_list args; - va_start(args, str); -string temp; - vsprintf(temp, str, args); - va_end(args); - SetWindowText(info.hwnd, strptr(temp)); -} - -void Window::set_background_color(uint8 r, uint8 g, uint8 b) { -HBRUSH old_brush = info.background; - info.background = (HBRUSH)CreateSolidBrush(RGB(r, g, b)); - SetClassLong(info.hwnd, GCL_HBRBACKGROUND, (LONG)info.background); - InvalidateRect(info.hwnd, 0, TRUE); - if(old_brush) { DeleteObject((HGDIOBJ)old_brush); } -} - -// - -Window::Window() { - info.fullscreen = false; - info.background = 0; - info.center = false; - info.control_index = 1; -} - -//platform-dependent: - -HWND Window::handle() { - return info.hwnd; -} - -}; diff --git a/src/lib/miu.cpp b/src/lib/miu.cpp new file mode 100644 index 00000000..56208806 --- /dev/null +++ b/src/lib/miu.cpp @@ -0,0 +1,253 @@ +#include "miu.h" + +namespace ns_miu { + +/* Miu (singleton) */ + +void Miu::init() { p.init(); } +void Miu::term() { p.term(); } +bool Miu::run() { return p.run(); } +bool Miu::pending() { return p.pending(); } +bool Miu::file_load(Window *focus, char *filename, const char *filter, const char *path) { return p.file_load(focus, filename, filter, path); } +bool Miu::file_save(Window *focus, char *filename, const char *filter, const char *path) { return p.file_save(focus, filename, filter, path); } +uint Miu::screen_width() { return p.screen_width(); } +uint Miu::screen_height() { return p.screen_height(); } +Miu& Miu::handle() { static Miu miu; return miu; } +Miu::Miu() : p(*new pMiu(*this)) {} +Miu::~Miu() { delete &p; } +Miu& miu() { return Miu::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(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); } +void Window::close() { p.close(); } +void Window::move(uint x, uint y) { p.move(x, y); } +void Window::resize(uint width, uint 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(); } +void Window::set_background_color(uint8 r, uint8 g, uint8 b) { p.set_background_color(r, g, b); } +void Window::set_text(const char *text) { p.set_text(text); } +void Window::attach(Window &window, uint x, uint y) { p.attach(window, x, y); } +void Window::attach(MenuGroup &menugroup) { p.attach(menugroup); } +void Window::attach(FormControl &formcontrol, uint x, uint y) { p.attach(formcontrol, x, y); } +void Window::move(Window &window, uint x, uint y) { p.move(window, x, y); } +void Window::move(FormControl &formcontrol, uint x, uint y) { p.move(formcontrol, x, y); } +void Window::menu_show(bool state) { p.menu_show(state); } +void Window::menu_hide() { p.menu_hide(); } +bool Window::menu_visible() { return p.menu_visible(); } +Window::Window() : + base_from_member(*new pWindow(*this)), + Widget(base_from_member::value), + p(base_from_member::value) { type = WindowType; } +Window::Window(pWindow &p_) : + base_from_member(p_), + Widget(base_from_member::value), + p(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(uint width, uint 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(uint style, uint width, uint 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(uint style, uint width, uint height) { p.create(style, width, height); } +void Canvas::redraw() { p.redraw(); } +uint32* 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(uint style, uint width, uint 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(uint style, uint width, uint 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(uint style, uint width, uint 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, uint style, uint width, uint 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(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); } +uint Editbox::get_text(char *text, uint 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(uint style, uint width, uint 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(uint column, uint width) { p.set_column_width(column, width); } +void Listbox::add_item(const char *text) { p.add_item(text); } +void Listbox::set_item(uint 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(uint style, uint width, uint 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(uint style, uint width, uint height) { p.create(style, width, height); } +uint Progressbar::get_progress() { return p.get_progress(); } +void Progressbar::set_progress(uint 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(uint style, uint width, uint height, uint length) { p.create(style, width, height, length); } +uint Slider::get_position() { return p.get_position(); } +void Slider::set_position(uint 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 ns_miu diff --git a/src/lib/miu.gtk/miu.gtk.button.cpp b/src/lib/miu.gtk/miu.gtk.button.cpp new file mode 100644 index 00000000..06523dac --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.button.cpp @@ -0,0 +1,25 @@ +void miu_pbutton_tick(pButton *p) { + if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self)); +} + +void pButton::create(uint style, uint width, uint height, const char *text) { + button = gtk_button_new_with_label(text ? text : ""); + gtk_widget_set_size_request(button, width, height); + gtk_widget_show(button); + g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(miu_pbutton_tick), (gpointer)this); +} + +void pButton::set_text(const char *text) { + if(!button) return; + gtk_button_set_label(GTK_BUTTON(button), text ? text : ""); +} + +pButton::pButton(Button &self_) : pFormControl(self_), self(self_) { + button = 0; +} + +/* internal */ + +GtkWidget* pButton::gtk_handle() { + return button; +} diff --git a/src/lib/miu.gtk/miu.gtk.button.h b/src/lib/miu.gtk/miu.gtk.button.h new file mode 100644 index 00000000..10bab078 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.button.h @@ -0,0 +1,12 @@ +class pButton : public pFormControl { +public: + Button &self; + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + pButton(Button&); + +/* internal */ + GtkWidget *button; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.canvas.cpp b/src/lib/miu.gtk/miu.gtk.canvas.cpp new file mode 100644 index 00000000..42454289 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.canvas.cpp @@ -0,0 +1,72 @@ +void miu_pcanvas_expose(pCanvas *p) { +uint32 *f = p->fbuffer; +uint32 *r = p->rbuffer; + for(uint y = p->canvas->allocation.height; y; y--) { + for(uint x = p->canvas->allocation.width; x; x--) { + uint32 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); +} + +void pCanvas::create(uint style, uint width, uint 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_show(canvas); + + g_signal_connect_swapped(G_OBJECT(canvas), "expose_event", G_CALLBACK(miu_pcanvas_expose), (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* pCanvas::buffer() { + return fbuffer; +} + +pCanvas::pCanvas(Canvas &self_) : pFormControl(self_), self(self_) { + canvas = 0; + fbuffer = 0; + rbuffer = 0; + bpitch = 0; +} + +pCanvas::~pCanvas() { + safe_free(fbuffer); + safe_free(rbuffer); +} + +/* internal */ + +void pCanvas::resize(uint width, uint height) { + safe_free(fbuffer); + safe_free(rbuffer); + + bpitch = width * sizeof(uint32); + fbuffer = (uint32*)malloc(bpitch * height); + rbuffer = (uint32*)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/miu.gtk/miu.gtk.canvas.h b/src/lib/miu.gtk/miu.gtk.canvas.h new file mode 100644 index 00000000..5e334e93 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.canvas.h @@ -0,0 +1,19 @@ +class pCanvas : public pFormControl { +public: + void create(uint style, uint width, uint height); + void redraw(); + uint32* buffer(); + + Canvas &self; + pCanvas(Canvas&); + ~pCanvas(); + +/* internal */ + GtkWidget *canvas; +//GTK+ RGB drawing function draws in xBGR format, so two buffers are needed ... + uint32 *fbuffer; //one for the xRGB image + uint32 *rbuffer; //one for the xBGR image + uint bpitch; + void resize(uint width, uint height); + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.checkbox.cpp b/src/lib/miu.gtk/miu.gtk.checkbox.cpp new file mode 100644 index 00000000..17012664 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.checkbox.cpp @@ -0,0 +1,37 @@ +void miu_pcheckbox_tick(pCheckbox *p) { + if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, p->checked(), &p->self)); +} + +void pCheckbox::create(uint style, uint width, uint height, const char *text) { + checkbox = gtk_check_button_new_with_label(text ? text : ""); + gtk_widget_set_size_request(checkbox, width, height); + gtk_widget_show(checkbox); + g_signal_connect_swapped(G_OBJECT(checkbox), "toggled", G_CALLBACK(miu_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) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), state ? TRUE : 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; +} + +/* internal */ + +GtkWidget* pCheckbox::gtk_handle() { + return checkbox; +} diff --git a/src/lib/miu.gtk/miu.gtk.checkbox.h b/src/lib/miu.gtk/miu.gtk.checkbox.h new file mode 100644 index 00000000..c22b8496 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.checkbox.h @@ -0,0 +1,15 @@ +class pCheckbox : public pFormControl { +public: + void create(uint style, uint width, uint 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 *checkbox; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.combobox.cpp b/src/lib/miu.gtk/miu.gtk.combobox.cpp new file mode 100644 index 00000000..f7d1012b --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.combobox.cpp @@ -0,0 +1,44 @@ +void miu_pcombobox_change(pCombobox *p) { + if(p->self.on_change) p->self.on_change(Event(Event::Change, p->get_selection(), &p->self)); +} + +void pCombobox::create(uint style, uint width, uint height, const char *text) { + combobox = gtk_combo_box_new_text(); + gtk_widget_set_size_request(combobox, width, height); + gtk_widget_show(combobox); + + g_signal_connect_swapped(G_OBJECT(combobox), "changed", G_CALLBACK(miu_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/miu.gtk/miu.gtk.combobox.h b/src/lib/miu.gtk/miu.gtk.combobox.h new file mode 100644 index 00000000..7a209027 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.combobox.h @@ -0,0 +1,16 @@ +class pCombobox : public pFormControl { +public: + void create(uint style, uint width, uint 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; + uint counter; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.cpp b/src/lib/miu.gtk/miu.gtk.cpp new file mode 100644 index 00000000..f5391c13 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.cpp @@ -0,0 +1,118 @@ +#include "miu.gtk.h" +#include "../miu.cpp" + +namespace ns_miu { + +#include "miu.gtk.keymap.cpp" +#include "miu.gtk.widget.cpp" + #include "miu.gtk.window.cpp" + #include "miu.gtk.menucontrol.cpp" + #include "miu.gtk.menugroup.cpp" + #include "miu.gtk.menuitem.cpp" + #include "miu.gtk.menucheckitem.cpp" + #include "miu.gtk.menuradioitem.cpp" + #include "miu.gtk.menuseparator.cpp" + #include "miu.gtk.formcontrol.cpp" + #include "miu.gtk.frame.cpp" + #include "miu.gtk.canvas.cpp" + #include "miu.gtk.label.cpp" + #include "miu.gtk.button.cpp" + #include "miu.gtk.checkbox.cpp" + #include "miu.gtk.radiobox.cpp" + #include "miu.gtk.editbox.cpp" + #include "miu.gtk.listbox.cpp" + #include "miu.gtk.combobox.cpp" + #include "miu.gtk.progressbar.cpp" + #include "miu.gtk.slider.cpp" + +void pMiu::init() { +//simulate passing argc, argv to gtk_init() +int argc = 1; +char **argv; + argv = (char**)malloc(1 * sizeof(char*)); + argv[0] = (char*)malloc(64 * sizeof(char)); + strcpy(argv[0], "./miu"); + gtk_init(&argc, &argv); + safe_free(argv[0]); + safe_free(argv); +} + +void pMiu::term() { +} + +bool pMiu::run() { + gtk_main_iteration_do(false); + return pending(); +} + +bool pMiu::pending() { + return gtk_events_pending(); +} + +bool pMiu::file_load(Window *focus, char *filename, const char *filter, const char *path) { + if(!filename) return false; + strcpy(filename, ""); + +GtkWidget *dialog = gtk_file_chooser_dialog_new("Load 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); + + if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + strcpy(filename, fn); + g_free(fn); + } + + gtk_widget_destroy(dialog); + return strcmp(filename, ""); //return true if filename exists +} + +bool pMiu::file_save(Window *focus, char *filename, const char *filter, const char *path) { + 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); + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); + + if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + char *fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + strcpy(filename, fn); + g_free(fn); + } + + gtk_widget_destroy(dialog); + return strcmp(filename, ""); //return true if filename exists +} + +uint pMiu::screen_width() { + return gdk_screen_width(); +} + +uint pMiu::screen_height() { + return gdk_screen_height(); +} + +pMiu& pMiu::handle() { + return miu().p; +} + +pMiu::pMiu(Miu &self_) : self(self_) { +} + +pMiu& pmiu() { + return pMiu::handle(); +} + +} //namespace ns_miu diff --git a/src/lib/miu.gtk/miu.gtk.editbox.cpp b/src/lib/miu.gtk/miu.gtk.editbox.cpp new file mode 100644 index 00000000..a27655f5 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.editbox.cpp @@ -0,0 +1,62 @@ +void pEditbox::create(uint style, uint width, uint 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); + } 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_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); + } +} + +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); + } +} + +uint pEditbox::get_text(char *text, uint 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/miu.gtk/miu.gtk.editbox.h b/src/lib/miu.gtk/miu.gtk.editbox.h new file mode 100644 index 00000000..682f2ce1 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.editbox.h @@ -0,0 +1,16 @@ +class pEditbox : public pFormControl { +public: + Editbox &self; + void create(uint style, uint width, uint height, const char *text = ""); + uint get_text(char *text, uint 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/miu.gtk/miu.gtk.formcontrol.cpp b/src/lib/miu.gtk/miu.gtk.formcontrol.cpp new file mode 100644 index 00000000..cc9d8cda --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.formcontrol.cpp @@ -0,0 +1,32 @@ +void pFormControl::resize(uint width, uint 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/miu.gtk/miu.gtk.formcontrol.h b/src/lib/miu.gtk/miu.gtk.formcontrol.h new file mode 100644 index 00000000..b775632b --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.formcontrol.h @@ -0,0 +1,15 @@ +class pFormControl : public pWidget { +public: + virtual void resize(uint width, uint 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/miu.gtk/miu.gtk.frame.cpp b/src/lib/miu.gtk/miu.gtk.frame.cpp new file mode 100644 index 00000000..f378bb9e --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.frame.cpp @@ -0,0 +1,19 @@ +void pFrame::create(uint style, uint width, uint height, const char *text) { + frame = gtk_frame_new(text ? text : ""); + 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/miu.gtk/miu.gtk.frame.h b/src/lib/miu.gtk/miu.gtk.frame.h new file mode 100644 index 00000000..446f016e --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.frame.h @@ -0,0 +1,12 @@ +class pFrame : public pFormControl { +public: + Frame &self; + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + pFrame(Frame&); + +/* internal */ + GtkWidget *frame; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.h b/src/lib/miu.gtk/miu.gtk.h new file mode 100644 index 00000000..9aba9374 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.h @@ -0,0 +1,58 @@ +#ifndef MIU_GTK_H +#define MIU_GTK_H + +#include "../miu.h" + +#include +#include +#include + +namespace ns_miu { + +#include "miu.gtk.widget.h" + #include "miu.gtk.window.h" + #include "miu.gtk.menucontrol.h" + #include "miu.gtk.menugroup.h" + #include "miu.gtk.menuitem.h" + #include "miu.gtk.menucheckitem.h" + #include "miu.gtk.menuradioitem.h" + #include "miu.gtk.menuseparator.h" + #include "miu.gtk.formcontrol.h" + #include "miu.gtk.frame.h" + #include "miu.gtk.canvas.h" + #include "miu.gtk.label.h" + #include "miu.gtk.button.h" + #include "miu.gtk.checkbox.h" + #include "miu.gtk.radiobox.h" + #include "miu.gtk.editbox.h" + #include "miu.gtk.listbox.h" + #include "miu.gtk.combobox.h" + #include "miu.gtk.progressbar.h" + #include "miu.gtk.slider.h" + +class pMiu { +public: + Miu &self; + void init(); + void term(); + bool run(); + bool pending(); + + bool file_load(Window *focus, char *filename, const char *filter, const char *path); + bool file_save(Window *focus, char *filename, const char *filter, const char *path); + + uint screen_width(); + uint screen_height(); + + static pMiu& handle(); + pMiu(Miu&); + +/* internal */ + uint16 translate_key(uint key); +}; + +pMiu& pmiu(); + +} //namespace ns_miu + +#endif //ifndef MIU_GTK_H diff --git a/src/lib/miu.gtk/miu.gtk.keymap.cpp b/src/lib/miu.gtk/miu.gtk.keymap.cpp new file mode 100644 index 00000000..621f8e0f --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.keymap.cpp @@ -0,0 +1,188 @@ +uint16 pMiu::translate_key(uint key) { + switch(key) { + case GDK_Escape: return keymap::esc; + + case GDK_F1: return keymap::f1; + case GDK_F2: return keymap::f2; + case GDK_F3: return keymap::f3; + case GDK_F4: return keymap::f4; + case GDK_F5: return keymap::f5; + case GDK_F6: return keymap::f6; + case GDK_F7: return keymap::f7; + case GDK_F8: return keymap::f8; + case GDK_F9: return keymap::f9; + case GDK_F10: return keymap::f10; + case GDK_F11: return keymap::f11; + case GDK_F12: return keymap::f12; + + case GDK_Print: return keymap::print_screen; + case GDK_Sys_Req: return keymap::sys_req; + case GDK_Scroll_Lock: return keymap::scroll_lock; + case GDK_Pause: return keymap::pause; + case GDK_Break: return keymap::brk; + + case GDK_grave: return keymap::grave; + case GDK_asciitilde: return keymap::tilde; + + case GDK_1: return keymap::num_1; + case GDK_2: return keymap::num_2; + case GDK_3: return keymap::num_3; + case GDK_4: return keymap::num_4; + case GDK_5: return keymap::num_5; + case GDK_6: return keymap::num_6; + case GDK_7: return keymap::num_7; + case GDK_8: return keymap::num_8; + case GDK_9: return keymap::num_9; + case GDK_0: return keymap::num_0; + + case GDK_exclam: return keymap::exclamation; + case GDK_at: return keymap::at; + case GDK_numbersign: return keymap::pound; + case GDK_dollar: return keymap::dollar; + case GDK_percent: return keymap::percent; + case GDK_asciicircum: return keymap::power; + case GDK_ampersand: return keymap::ampersand; + case GDK_asterisk: return keymap::asterisk; + case GDK_parenleft: return keymap::lparenthesis; + case GDK_parenright: return keymap::rparenthesis; + + case GDK_minus: return keymap::minus; + case GDK_underscore: return keymap::underscore; + case GDK_equal: return keymap::equal; + case GDK_plus: return keymap::plus; + case GDK_BackSpace: return keymap::backspace; + + case GDK_Insert: return keymap::ins; + case GDK_Delete: return keymap::del; + case GDK_Home: return keymap::home; + case GDK_End: return keymap::end; + case GDK_Page_Up: return keymap::page_up; + case GDK_Page_Down: return keymap::page_down; + + case GDK_a: return keymap::a; + case GDK_b: return keymap::b; + case GDK_c: return keymap::c; + case GDK_d: return keymap::d; + case GDK_e: return keymap::e; + case GDK_f: return keymap::f; + case GDK_g: return keymap::g; + case GDK_h: return keymap::h; + case GDK_i: return keymap::i; + case GDK_j: return keymap::j; + case GDK_k: return keymap::k; + case GDK_l: return keymap::l; + case GDK_m: return keymap::m; + case GDK_n: return keymap::n; + case GDK_o: return keymap::o; + case GDK_p: return keymap::p; + case GDK_q: return keymap::q; + case GDK_r: return keymap::r; + case GDK_s: return keymap::s; + case GDK_t: return keymap::t; + case GDK_u: return keymap::u; + case GDK_v: return keymap::v; + case GDK_w: return keymap::w; + case GDK_x: return keymap::x; + case GDK_y: return keymap::y; + case GDK_z: return keymap::z; + + case GDK_A: return keymap::A; + case GDK_B: return keymap::B; + case GDK_C: return keymap::C; + case GDK_D: return keymap::D; + case GDK_E: return keymap::E; + case GDK_F: return keymap::F; + case GDK_G: return keymap::G; + case GDK_H: return keymap::H; + case GDK_I: return keymap::I; + case GDK_J: return keymap::J; + case GDK_K: return keymap::K; + case GDK_L: return keymap::L; + case GDK_M: return keymap::M; + case GDK_N: return keymap::N; + case GDK_O: return keymap::O; + case GDK_P: return keymap::P; + case GDK_Q: return keymap::Q; + case GDK_R: return keymap::R; + case GDK_S: return keymap::S; + case GDK_T: return keymap::T; + case GDK_U: return keymap::U; + case GDK_V: return keymap::V; + case GDK_W: return keymap::W; + case GDK_X: return keymap::X; + case GDK_Y: return keymap::Y; + case GDK_Z: return keymap::Z; + + case GDK_bracketleft: return keymap::lbracket; + case GDK_bracketright: return keymap::rbracket; + case GDK_backslash: return keymap::backslash; + case GDK_semicolon: return keymap::semicolon; + case GDK_apostrophe: return keymap::apostrophe; + case GDK_comma: return keymap::comma; + case GDK_period: return keymap::period; + case GDK_slash: return keymap::slash; + + case GDK_braceleft: return keymap::lbrace; + case GDK_braceright: return keymap::rbrace; + case GDK_bar: return keymap::pipe; + case GDK_colon: return keymap::colon; + case GDK_quotedbl: return keymap::quote; + case GDK_less: return keymap::lcaret; + case GDK_greater: return keymap::rcaret; + case GDK_question: return keymap::question; + + case GDK_KP_1: return keymap::kp_1; + case GDK_KP_2: return keymap::kp_2; + case GDK_KP_3: return keymap::kp_3; + case GDK_KP_4: return keymap::kp_4; + case GDK_KP_5: return keymap::kp_5; + case GDK_KP_6: return keymap::kp_6; + case GDK_KP_7: return keymap::kp_7; + case GDK_KP_8: return keymap::kp_8; + case GDK_KP_9: return keymap::kp_9; + case GDK_KP_0: return keymap::kp_0; + case GDK_KP_Decimal: return keymap::kp_decimal; + + case GDK_KP_End: return keymap::kp_end; + case GDK_KP_Down: return keymap::kp_down; + case GDK_KP_Page_Down: return keymap::kp_page_down; + case GDK_KP_Left: return keymap::kp_left; + case GDK_KP_Begin: return keymap::kp_center; + case GDK_KP_Right: return keymap::kp_right; + case GDK_KP_Home: return keymap::kp_home; + case GDK_KP_Up: return keymap::kp_up; + case GDK_KP_Page_Up: return keymap::kp_page_up; + case GDK_KP_Insert: return keymap::kp_insert; + case GDK_KP_Delete: return keymap::kp_delete; + + case GDK_KP_Add: return keymap::kp_plus; + case GDK_KP_Subtract: return keymap::kp_minus; + case GDK_KP_Multiply: return keymap::kp_mul; + case GDK_KP_Divide: return keymap::kp_div; + case GDK_KP_Enter: return keymap::kp_enter; + + case GDK_Num_Lock: return keymap::num_lock; + case GDK_Caps_Lock: return keymap::caps_lock; + + case GDK_Up: return keymap::up; + case GDK_Down: return keymap::down; + case GDK_Left: return keymap::left; + case GDK_Right: return keymap::right; + + case GDK_Tab: return keymap::tab; + case GDK_Return: return keymap::enter; + case GDK_space: return keymap::space; + + case GDK_Control_L: return keymap::lctrl; + case GDK_Control_R: return keymap::rctrl; + case GDK_Alt_L: return keymap::lalt; + case GDK_Alt_R: return keymap::ralt; + case GDK_Shift_L: return keymap::lshift; + case GDK_Shift_R: return keymap::rshift; + case GDK_Super_L: return keymap::lsuper; + case GDK_Super_R: return keymap::rsuper; + case GDK_Menu: return keymap::menu; + } + + return keymap::none; +} diff --git a/src/lib/miu.gtk/miu.gtk.label.cpp b/src/lib/miu.gtk/miu.gtk.label.cpp new file mode 100644 index 00000000..809a8561 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.label.cpp @@ -0,0 +1,21 @@ +void pLabel::create(uint style, uint width, uint height, const char *text) { + label = gtk_label_new(text ? text : ""); + 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/miu.gtk/miu.gtk.label.h b/src/lib/miu.gtk/miu.gtk.label.h new file mode 100644 index 00000000..e08540ea --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.label.h @@ -0,0 +1,12 @@ +class pLabel : public pFormControl { +public: + Label &self; + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + pLabel(Label&); + +/* internal */ + GtkWidget *label; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.listbox.cpp b/src/lib/miu.gtk/miu.gtk.listbox.cpp new file mode 100644 index 00000000..f90e01c3 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.listbox.cpp @@ -0,0 +1,135 @@ +void miu_plistbox_change(pListbox *p) { + if(p->listbox_selection == p->get_selection()) return; + if(p->self.on_change) p->self.on_change(Event(Event::Change, p->listbox_selection = p->get_selection(), &p->self)); +} + +void miu_plistbox_activate(pListbox *p) { + if(p->self.on_activate) p->self.on_activate(Event(Event::Activate, p->listbox_selection = p->get_selection(), &p->self)); +} + +void pListbox::create(uint style, uint width, uint 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; + split(list, "\t", columns); + +GType *v = (GType*)malloc(count(list) * sizeof(GType)); + for(uint i = 0; i < count(list); i++) v[i] = G_TYPE_STRING; + store = gtk_list_store_newv(count(list), v); + safe_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), count(list) >= 2 ? true : false); + for(uint i = 0; i < count(list); i++) { + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(list[i], renderer, "text", i, 0); + column_list[column_list.size()] = column; + gtk_tree_view_append_column(GTK_TREE_VIEW(listbox), column); + } + + if(text && *text) { + split(list, "\n", text); + for(uint i = 0; i < count(list); 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(miu_plistbox_change), (gpointer)this); + g_signal_connect_swapped(G_OBJECT(listbox), "row-activated", G_CALLBACK(miu_plistbox_activate), (gpointer)this); +} + +void pListbox::autosize_columns() { + gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listbox)); +} + +void pListbox::set_column_width(uint column, uint width) { + gtk_tree_view_column_set_min_width(column_list[column], width); + gtk_tree_view_column_set_max_width(column_list[column], width); +} + +void pListbox::add_item(const char *text) { +lstring list; + split(list, "\t", text); + gtk_list_store_append(store, &iter); + for(uint i = 0; i < count(list); i++) { + gtk_list_store_set(store, &iter, i, list[i](), -1); + } +} + +void pListbox::set_item(uint index, const char *text) { +GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox)); + for(uint i = 0; i <= index; i++) { + i == 0 ? + gtk_tree_model_get_iter_first(model, &iter) : + gtk_tree_model_iter_next(model, &iter); + } + +lstring list; + split(list, "\t", text); + for(uint i = 0; i < count(list); i++) { + gtk_list_store_set(store, &iter, i, 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(uint 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) { goto end; } + if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; } + if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; } + for(uint i = 1; i < 100000; i++) { + if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; } + if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; } + } +end: + if(current != index) ;//{ owner->message(Message::Changed, (uintptr_t)this); } +} + +void pListbox::reset() { + 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/miu.gtk/miu.gtk.listbox.h b/src/lib/miu.gtk/miu.gtk.listbox.h new file mode 100644 index 00000000..faeae4cf --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.listbox.h @@ -0,0 +1,25 @@ +class pListbox : public pFormControl { +public: + void create(uint style, uint width, uint height, const char *columns = "", const char *text = ""); + void autosize_columns(); + void set_column_width(uint column, uint width); + void add_item(const char *text); + void set_item(uint 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; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + array column_list; + GtkTreeIter iter; + int listbox_selection; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.menucheckitem.cpp b/src/lib/miu.gtk/miu.gtk.menucheckitem.cpp new file mode 100644 index 00000000..c185d497 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menucheckitem.cpp @@ -0,0 +1,31 @@ +void miu_pmenucheckitem_tick(pMenuCheckItem *p) { + if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, p->checked(), &p->self)); +} + +void pMenuCheckItem::create(const char *text) { + item = gtk_check_menu_item_new_with_label(text ? text : "?"); + gtk_widget_show(item); + g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(miu_pmenucheckitem_tick), (gpointer)this); +} + +void pMenuCheckItem::check(bool state) { + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), state ? TRUE : 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; +} + +/* internal */ + +GtkWidget* pMenuCheckItem::gtk_handle() { + return item; +} diff --git a/src/lib/miu.gtk/miu.gtk.menucheckitem.h b/src/lib/miu.gtk/miu.gtk.menucheckitem.h new file mode 100644 index 00000000..a161249e --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menucheckitem.h @@ -0,0 +1,14 @@ +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 *item; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.menucontrol.cpp b/src/lib/miu.gtk/miu.gtk.menucontrol.cpp new file mode 100644 index 00000000..de6281bb --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menucontrol.cpp @@ -0,0 +1,20 @@ +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/miu.gtk/miu.gtk.menucontrol.h b/src/lib/miu.gtk/miu.gtk.menucontrol.h new file mode 100644 index 00000000..0204eacd --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menucontrol.h @@ -0,0 +1,12 @@ +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/miu.gtk/miu.gtk.menugroup.cpp b/src/lib/miu.gtk/miu.gtk.menugroup.cpp new file mode 100644 index 00000000..74c2d499 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menugroup.cpp @@ -0,0 +1,21 @@ +void pMenuGroup::create(const char *text) { + group = gtk_menu_new(); + item = gtk_menu_item_new_with_label(text ? text : ""); + 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/miu.gtk/miu.gtk.menugroup.h b/src/lib/miu.gtk/miu.gtk.menugroup.h new file mode 100644 index 00000000..594ba51f --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menugroup.h @@ -0,0 +1,13 @@ +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/miu.gtk/miu.gtk.menuitem.cpp b/src/lib/miu.gtk/miu.gtk.menuitem.cpp new file mode 100644 index 00000000..64699dba --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menuitem.cpp @@ -0,0 +1,19 @@ +void miu_pmenuitem_tick(pMenuItem *p) { + if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self)); +} + +void pMenuItem::create(const char *text) { + item = gtk_menu_item_new_with_label(text ? text : ""); + g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(miu_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/miu.gtk/miu.gtk.menuitem.h b/src/lib/miu.gtk/miu.gtk.menuitem.h new file mode 100644 index 00000000..55d02bca --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menuitem.h @@ -0,0 +1,11 @@ +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/miu.gtk/miu.gtk.menuradioitem.cpp b/src/lib/miu.gtk/miu.gtk.menuradioitem.cpp new file mode 100644 index 00000000..0e9a436b --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menuradioitem.cpp @@ -0,0 +1,33 @@ +void miu_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->checked() && p->self.on_tick) p->self.on_tick(Event(Event::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 : ""); + } + gtk_widget_show(item); + g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(miu_pmenuradioitem_tick), (gpointer)this); +} + +void pMenuRadioItem::check() { + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); +} + +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; +} + +/* internal */ + +GtkWidget* pMenuRadioItem::gtk_handle() { + return item; +} diff --git a/src/lib/miu.gtk/miu.gtk.menuradioitem.h b/src/lib/miu.gtk/miu.gtk.menuradioitem.h new file mode 100644 index 00000000..bd020cb2 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menuradioitem.h @@ -0,0 +1,13 @@ +class pMenuRadioItem : public pMenuControl { +public: + void create(MenuRadioItemGroup &group, const char *text = ""); + void check(); + bool checked(); + + MenuRadioItem &self; + pMenuRadioItem(MenuRadioItem&); + +/* internal */ + GtkWidget *item; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.menuseparator.cpp b/src/lib/miu.gtk/miu.gtk.menuseparator.cpp new file mode 100644 index 00000000..a03ba421 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menuseparator.cpp @@ -0,0 +1,14 @@ +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/miu.gtk/miu.gtk.menuseparator.h b/src/lib/miu.gtk/miu.gtk.menuseparator.h new file mode 100644 index 00000000..54d8d151 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.menuseparator.h @@ -0,0 +1,11 @@ +class pMenuSeparator : public pMenuControl { +public: + MenuSeparator &self; + void create(); + + pMenuSeparator(MenuSeparator&); + +/* internal */ + GtkWidget *item; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.progressbar.cpp b/src/lib/miu.gtk/miu.gtk.progressbar.cpp new file mode 100644 index 00000000..2cef9fc0 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.progressbar.cpp @@ -0,0 +1,25 @@ +void pProgressbar::create(uint style, uint width, uint height) { + progressbar = gtk_progress_bar_new(); + gtk_widget_set_size_request(progressbar, width, height); + gtk_widget_show(progressbar); +} + +uint pProgressbar::get_progress() { +uint progress = (uint)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar)) * 100.0); + return max(0, min(progress, 100)); +} + +void pProgressbar::set_progress(uint progress) { + progress = max(0, min(progress, 100)); + 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/miu.gtk/miu.gtk.progressbar.h b/src/lib/miu.gtk/miu.gtk.progressbar.h new file mode 100644 index 00000000..251c47dc --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.progressbar.h @@ -0,0 +1,13 @@ +class pProgressbar : public pFormControl { +public: + Progressbar &self; + void create(uint style, uint width, uint height); + uint get_progress(); + void set_progress(uint progress); + + pProgressbar(Progressbar&); + +/* internal */ + GtkWidget *progressbar; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.radiobox.cpp b/src/lib/miu.gtk/miu.gtk.radiobox.cpp new file mode 100644 index 00000000..1e7ec75d --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.radiobox.cpp @@ -0,0 +1,39 @@ +void miu_pradiobox_tick(pRadiobox *p) { +//GTK+ sends two messages: one for the activated radiobox, +//and one for the deactivated radiobox. ignore the latter. + if(p->checked() && p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self)); +} + +void pRadiobox::create(RadioboxGroup &group, uint style, uint width, uint 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 : ""); + } + gtk_widget_set_size_request(radiobox, width, height); + gtk_widget_show(radiobox); + g_signal_connect_swapped(G_OBJECT(radiobox), "toggled", G_CALLBACK(miu_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() { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobox), TRUE); +} + +bool pRadiobox::checked() { + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radiobox)); +} + +pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self), self(self_) { + radiobox = 0; +} + +/* internal */ + +GtkWidget* pRadiobox::gtk_handle() { + return radiobox; +} diff --git a/src/lib/miu.gtk/miu.gtk.radiobox.h b/src/lib/miu.gtk/miu.gtk.radiobox.h new file mode 100644 index 00000000..ea45c369 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.radiobox.h @@ -0,0 +1,14 @@ +class pRadiobox : public pFormControl { +public: + void create(RadioboxGroup &group, uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + void check(); + bool checked(); + + Radiobox &self; + pRadiobox(Radiobox&); + +/* internal */ + GtkWidget *radiobox; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.slider.cpp b/src/lib/miu.gtk/miu.gtk.slider.cpp new file mode 100644 index 00000000..c1f40b2c --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.slider.cpp @@ -0,0 +1,36 @@ +void miu_pslider_change(pSlider *p) { + if(p->slider_position == p->get_position()) return; + if(p->self.on_change) p->self.on_change(Event(Event::Change, p->slider_position = p->get_position(), &p->self)); +} + +void pSlider::create(uint style, uint width, uint height, uint 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(miu_pslider_change), (gpointer)this); +} + +uint pSlider::get_position() { + return (uint)gtk_range_get_value(GTK_RANGE(slider)); +} + +void pSlider::set_position(uint 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/miu.gtk/miu.gtk.slider.h b/src/lib/miu.gtk/miu.gtk.slider.h new file mode 100644 index 00000000..9b2d02c1 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.slider.h @@ -0,0 +1,14 @@ +class pSlider : public pFormControl { +public: + void create(uint style, uint width, uint height, uint length); + uint get_position(); + void set_position(uint position); + + Slider &self; + pSlider(Slider&); + +/* internal */ + GtkWidget *slider; + uint slider_position; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.gtk/miu.gtk.widget.cpp b/src/lib/miu.gtk/miu.gtk.widget.cpp new file mode 100644 index 00000000..464351d0 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.widget.cpp @@ -0,0 +1,24 @@ +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_XWINDOW(gtk_handle()->window); +} + +pWidget::pWidget(Widget &self_) : self(self_) { +} + +/* internal */ + +GtkWidget* pWidget::gtk_handle() { + return 0; +} diff --git a/src/lib/miu.gtk/miu.gtk.widget.h b/src/lib/miu.gtk/miu.gtk.widget.h new file mode 100644 index 00000000..dfdec8c1 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.widget.h @@ -0,0 +1,13 @@ +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/miu.gtk/miu.gtk.window.cpp b/src/lib/miu.gtk/miu.gtk.window.cpp new file mode 100644 index 00000000..5fd71962 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.window.cpp @@ -0,0 +1,135 @@ +gint miu_pwindow_close(pWindow *p) { +uintptr_t r = p->self.on_close ? p->self.on_close(Event(Event::Close, 0, &p->self)) : true; + return !bool(r); +} + +gint miu_pwindow_keydown(GtkWidget *w, GdkEventKey *key, pWindow *p) { + if(p && p->self.on_keydown) p->self.on_keydown(Event(Event::KeyDown, pmiu().translate_key(key->keyval), &p->self)); + return FALSE; +} + +gint miu_pwindow_keyup(GtkWidget *w, GdkEventKey *key, pWindow *p) { + if(p && p->self.on_keyup) p->self.on_keyup(Event(Event::KeyUp, pmiu().translate_key(key->keyval), &p->self)); + return FALSE; +} + +void pWindow::create(uint style, uint width, uint height, const char *text) { + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), text ? text : ""); + gtk_window_set_resizable(GTK_WINDOW(window), false); + 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(miu_pwindow_close), (gpointer)this); + g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(miu_pwindow_keydown), (gpointer)this); + g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(miu_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_end(GTK_BOX(menucontainer), formcontainer, true, true, 0); + gtk_widget_show(formcontainer); +} + +void pWindow::close() { + gtk_widget_destroy(window); +} + +void pWindow::move(uint x, uint y) { + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE); + gtk_window_move(GTK_WINDOW(window), x, y); +} + +void pWindow::resize(uint width, uint height) { + gtk_widget_set_size_request(formcontainer, width, height); +} + +void pWindow::focus() { + gtk_window_present(GTK_WINDOW(window)); +} + +bool pWindow::focused() { + return gtk_window_is_active(GTK_WINDOW(window)); +} + +void pWindow::fullscreen() { + gtk_window_fullscreen(GTK_WINDOW(window)); +} + +void pWindow::unfullscreen() { + gtk_window_unfullscreen(GTK_WINDOW(window)); +} + +void pWindow::set_background_color(uint8 r, uint8 g, uint8 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); + gtk_widget_modify_bg(formcontainer, GTK_STATE_NORMAL, &color); +} + +void pWindow::set_text(const char *text) { + gtk_window_set_title(GTK_WINDOW(window), text ? text : ""); +} + +void pWindow::attach(Window &window, uint x, uint 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, uint x, uint y) { + gtk_fixed_put(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y); +} + +void pWindow::move(Window &window, uint x, uint y) { + gtk_fixed_move(GTK_FIXED(formcontainer), window.p.gtk_handle(), x, y); +} + +void pWindow::move(FormControl &formcontrol, uint x, uint y) { + gtk_fixed_move(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y); +} + +void pWindow::menu_show(bool state) { + if(!menubar) return; + 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); +} + +pWindow::pWindow(Window &self_) : pWidget(self_), self(self_) { + owner = 0; + window = 0; + menubar = 0; + menucontainer = 0; + formcontainer = 0; +} + +/* internal */ + +GtkWidget* pWindow::gtk_handle() { + return owner ? formcontainer : window; +} diff --git a/src/lib/miu.gtk/miu.gtk.window.h b/src/lib/miu.gtk/miu.gtk.window.h new file mode 100644 index 00000000..6b2c28a4 --- /dev/null +++ b/src/lib/miu.gtk/miu.gtk.window.h @@ -0,0 +1,32 @@ +class pWindow : public pWidget { +public: + void create(uint style, uint width, uint height, const char *text = ""); + void close(); + void move(uint x, uint y); + void resize(uint width, uint height); + void focus(); + bool focused(); + void fullscreen(); + void unfullscreen(); + void set_background_color(uint8 r, uint8 g, uint8 b); + void set_text(const char *text = ""); + void attach(Window &window, uint x, uint y); + void attach(MenuGroup &menugroup); + void attach(FormControl &formcontrol, uint x, uint y); + void move(Window &window, uint x, uint y); + void move(FormControl &formcontrol, uint x, uint y); + void menu_show(bool state = true); + void menu_hide(); + bool menu_visible(); + + Window &self; + pWindow(Window&); + +/* internal */ + pWindow *owner; //0 = no owner (default) + GtkWidget *window; + GtkWidget *menubar; + GtkWidget *menucontainer; + GtkWidget *formcontainer; + GtkWidget* gtk_handle(); +}; diff --git a/src/lib/miu.h b/src/lib/miu.h new file mode 100644 index 00000000..8ce90101 --- /dev/null +++ b/src/lib/miu.h @@ -0,0 +1,506 @@ +/* + miu + version: 0.012 (2007-12-22) + author: byuu + license: public domain +*/ + +#ifndef MIU_H +#define MIU_H + +#include "bbase.h" +#include "barray.h" +#include "bfunction.h" +#include "bkeymap.h" +#include "bstring.h" + +namespace ns_miu { + +class pMiu; +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 pMiu; \ + 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 Miu; +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 array MenuRadioItemGroup; +typedef array RadioboxGroup; + +struct Event { + enum Type { + Close, + Block, + KeyDown, + KeyUp, + Change, + Tick, + Activate, + } type; + uintptr_t param; + Widget *widget; + + Event(Type type_, uintptr_t param_ = 0, Widget *widget_ = 0) : + type(type_), param(param_), widget(widget_) {} +}; + +class Miu : noncopyable { +public: + void init(); + void term(); + bool run(); + bool pending(); + + bool file_load(Window *focus, char *filename, const char *filter, const char *path); + bool file_save(Window *focus, char *filename, const char *filter, const char *path); + + uint screen_width(); + uint screen_height(); + + static Miu& handle(); + Miu(); + ~Miu(); + +private: + pFriends; + pMiu &p; +}; + +Miu& miu(); + +class Widget : 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 base_from_member, public Widget { +public: + enum Style { + AutoCenter = 1 << 1, + }; + + void create(uint style, uint width, uint height, const char *text = ""); + void close(); + void move(uint x, uint y); + void resize(uint width, uint height); + void focus(); + bool focused(); + void fullscreen(); + void unfullscreen(); + void set_background_color(uint8 r, uint8 g, uint8 b); + void set_text(const char *text = ""); + void attach(Window &window, uint x, uint y); + void attach(MenuGroup &menugroup); + void attach(FormControl &formcontrol, uint x, uint y); + void move(Window &window, uint x, uint y); + void move(FormControl &formcontrol, uint x, uint y); + void menu_show(bool = true); + void menu_hide(); + bool menu_visible(); + + function on_close; + function on_block; + function on_keydown; + function on_keyup; + + Window(); + +protected: + Window(pWindow&); + +private: + pFriends; + pWindow &p; +}; + +class MenuControl : public 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 base_from_member, public MenuControl { +public: + MenuGroup& create(const char *text); + void attach(MenuControl &menucontrol); + MenuGroup(); + +private: + pFriends; + pMenuGroup &p; +}; + +class MenuItem : public base_from_member, public MenuControl { +public: + MenuItem& create(const char *text); + MenuItem(); + + function on_tick; + +private: + pFriends; + pMenuItem &p; +}; + +class MenuCheckItem : public base_from_member, public MenuControl { +public: + MenuCheckItem& create(const char *text); + void check(bool = true); + void uncheck(); + bool checked(); + MenuCheckItem(); + + function on_tick; + +private: + pFriends; + pMenuCheckItem &p; +}; + +class MenuRadioItem : public base_from_member, public MenuControl { +public: + MenuRadioItem& create(MenuRadioItemGroup &group, const char *text); + void check(); + bool checked(); + MenuRadioItem(); + + function on_tick; + +private: + pFriends; + pMenuRadioItem &p; +}; + +class MenuSeparator : public base_from_member, public MenuControl { +public: + MenuSeparator& create(); + MenuSeparator(); + +private: + pFriends; + pMenuSeparator &p; +}; + +class FormControl : private base_from_member, public Widget { +public: + void resize(uint width, uint height); + void focus(); + bool focused(); + void enable(bool = true); + void disable(); + bool enabled(); + + FormControl(); + +protected: + FormControl(pFormControl&); + +private: + pFriends; + pFormControl &p; +}; + +class Frame : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + Frame(); + +private: + pFriends; + pFrame &p; +}; + +class Canvas : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height); + void redraw(); + uint32* buffer(); + + Canvas(); + +private: + pFriends; + pCanvas &p; +}; + +class Label : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + Label(); + +private: + pFriends; + pLabel &p; +}; + +class Button : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + function on_tick; + + Button(); + +private: + pFriends; + pButton &p; +}; + +class Checkbox : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + void check(bool = true); + void uncheck(); + bool checked(); + + function on_tick; + + Checkbox(); + +private: + pFriends; + pCheckbox &p; +}; + +class Radiobox : private base_from_member, public FormControl { +public: + void create(RadioboxGroup &group, uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + void check(); + bool checked(); + + function on_tick; + + Radiobox(); + +private: + pFriends; + pRadiobox &p; +}; + +class Editbox : private 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(uint style, uint width, uint height, const char *text = ""); + uint get_text(char *text, uint length = -1U); + void set_text(const char *text = ""); + + Editbox(); + +private: + pFriends; + pEditbox &p; +}; + +class Listbox : private 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(uint style, uint width, uint height, const char *columns = "", const char *text = ""); + void autosize_columns(); + void set_column_width(uint column, uint width); + void add_item(const char *text); + void set_item(uint index, const char *text); + int get_selection(); + void set_selection(int index); + void reset(); + + function on_change; + function on_activate; + + Listbox(); + +private: + pFriends; + pListbox &p; +}; + +class Combobox : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height, const char *text = ""); + void add_item(const char *text); + int get_selection(); + void set_selection(int index); + void reset(); + + function on_change; + + Combobox(); + +private: + pFriends; + pCombobox &p; +}; + +class Progressbar : private base_from_member, public FormControl { +public: + void create(uint style, uint width, uint height); + uint get_progress(); + void set_progress(uint progress); + + Progressbar(); + +private: + pFriends; + pProgressbar &p; +}; + +class Slider : private base_from_member, public FormControl { +public: + enum Style { + Horizontal = 0, + Vertical = 1 << 1, + }; + + void create(uint style, uint width, uint height, uint length); + uint get_position(); + void set_position(uint position); + + function on_change; + + Slider(); + +private: + pFriends; + pSlider &p; +}; + +#undef pFriends + +} //namespace ns_miu + +#endif //ifndef MIU_H diff --git a/src/lib/miu.win/miu.win.button.cpp b/src/lib/miu.win/miu.win.button.cpp new file mode 100644 index 00000000..618b70a3 --- /dev/null +++ b/src/lib/miu.win/miu.win.button.cpp @@ -0,0 +1,14 @@ +void pButton::create(uint style, uint width, uint height, const char *text) { + hwnd = CreateWindow("BUTTON", text ? text : "", WS_CHILD | WS_VISIBLE, + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); +} + +void pButton::set_text(const char *text) { + SetWindowText(hwnd, text ? text : ""); +} + +pButton::pButton(Button &self_) : pFormControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.button.h b/src/lib/miu.win/miu.win.button.h new file mode 100644 index 00000000..ee125e68 --- /dev/null +++ b/src/lib/miu.win/miu.win.button.h @@ -0,0 +1,8 @@ +class pButton : public pFormControl { +public: + Button &self; + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + pButton(Button&); +}; diff --git a/src/lib/miu.win/miu.win.canvas.cpp b/src/lib/miu.win/miu.win.canvas.cpp new file mode 100644 index 00000000..5431934d --- /dev/null +++ b/src/lib/miu.win/miu.win.canvas.cpp @@ -0,0 +1,54 @@ +void pCanvas::create(uint style, uint width, uint height) { + hwnd = CreateWindow("miu_window", "", WS_CHILD, + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); + resize(width, height); + ShowWindow(hwnd, SW_NORMAL); +} + +void pCanvas::redraw() { +} + +uint32* 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() { + safe_free(ibuffer); +} + +/* internal */ + +void pCanvas::blit() { +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); +} + +void pCanvas::resize(uint width, uint height) { + safe_free(ibuffer); + + ipitch = width * sizeof(uint32); + iwidth = width; + iheight = height; + ibuffer = (uint32*)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/miu.win/miu.win.canvas.h b/src/lib/miu.win/miu.win.canvas.h new file mode 100644 index 00000000..9b39f6fb --- /dev/null +++ b/src/lib/miu.win/miu.win.canvas.h @@ -0,0 +1,17 @@ +class pCanvas : public pFormControl { +public: + void create(uint style, uint width, uint height); + void redraw(); + uint32* buffer(); + + Canvas &self; + pCanvas(Canvas&); + ~pCanvas(); + +/* internal */ + BITMAPINFO bmi; + uint32 *ibuffer; + uint ipitch, iwidth, iheight; + void blit(); + void resize(uint width, uint height); +}; diff --git a/src/lib/miu.win/miu.win.checkbox.cpp b/src/lib/miu.win/miu.win.checkbox.cpp new file mode 100644 index 00000000..db7caf3b --- /dev/null +++ b/src/lib/miu.win/miu.win.checkbox.cpp @@ -0,0 +1,29 @@ +void pCheckbox::create(uint style, uint width, uint height, const char *text) { + hwnd = CreateWindow("BUTTON", text ? text : "", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); +} + +void pCheckbox::set_text(const char *text) { + SetWindowText(hwnd, text ? text : ""); +} + +void pCheckbox::check(bool state) { +bool prev = checked(); + SendMessage(hwnd, BM_SETCHECK, (WPARAM)(state ? TRUE : FALSE), 0); + if(prev != state) { + if(self.on_tick) self.on_tick(Event(Event::Tick, state, &self)); + } +} + +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/miu.win/miu.win.checkbox.h b/src/lib/miu.win/miu.win.checkbox.h new file mode 100644 index 00000000..8334b9a5 --- /dev/null +++ b/src/lib/miu.win/miu.win.checkbox.h @@ -0,0 +1,11 @@ +class pCheckbox : public pFormControl { +public: + void create(uint style, uint width, uint 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/miu.win/miu.win.combobox.cpp b/src/lib/miu.win/miu.win.combobox.cpp new file mode 100644 index 00000000..458d416b --- /dev/null +++ b/src/lib/miu.win/miu.win.combobox.cpp @@ -0,0 +1,28 @@ +void pCombobox::create(uint style, uint width, uint height, const char *text) { + hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "COMBOBOX", "", + WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, + 0, 0, width, 200, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); +} + +void pCombobox::add_item(const char *text) { + SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)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/miu.win/miu.win.combobox.h b/src/lib/miu.win/miu.win.combobox.h new file mode 100644 index 00000000..f7b7713d --- /dev/null +++ b/src/lib/miu.win/miu.win.combobox.h @@ -0,0 +1,14 @@ +class pCombobox : public pFormControl { +public: + Combobox &self; + void create(uint style, uint width, uint 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/miu.win/miu.win.cpp b/src/lib/miu.win/miu.win.cpp new file mode 100644 index 00000000..81025313 --- /dev/null +++ b/src/lib/miu.win/miu.win.cpp @@ -0,0 +1,318 @@ +#include "miu.win.h" +#include "../miu.cpp" + +namespace ns_miu { + +long __stdcall pmiu_wndproc(HWND, UINT, WPARAM, LPARAM); + +#include "miu.win.keymap.cpp" +#include "miu.win.widget.cpp" + #include "miu.win.window.cpp" + #include "miu.win.menucontrol.cpp" + #include "miu.win.menugroup.cpp" + #include "miu.win.menuitem.cpp" + #include "miu.win.menucheckitem.cpp" + #include "miu.win.menuradioitem.cpp" + #include "miu.win.menuseparator.cpp" + #include "miu.win.formcontrol.cpp" + #include "miu.win.frame.cpp" + #include "miu.win.canvas.cpp" + #include "miu.win.label.cpp" + #include "miu.win.button.cpp" + #include "miu.win.checkbox.cpp" + #include "miu.win.radiobox.cpp" + #include "miu.win.editbox.cpp" + #include "miu.win.listbox.cpp" + #include "miu.win.combobox.cpp" + #include "miu.win.progressbar.cpp" + #include "miu.win.slider.cpp" + +void pMiu::init() { +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 = pmiu_wndproc; + wc.lpszClassName = "miu_window"; + wc.lpszMenuName = 0; + wc.style = CS_HREDRAW | CS_VREDRAW; + RegisterClass(&wc); + + InitCommonControls(); + default_hwnd = CreateWindow("miu_window", "", WS_POPUP, 0, 0, 640, 480, 0, 0, GetModuleHandle(0), 0); + default_font = create_font("Tahoma", 9); + black_brush = CreateSolidBrush(RGB(0, 0, 0)); +} + +void pMiu::term() { + DeleteObject(black_brush); +} + +bool pMiu::run() { +MSG msg; + if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return pending(); +} + +bool pMiu::pending() { +MSG msg; + return PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); +} + +bool pMiu::file_load(Window *focus, char *filename, const char *filter, const char *path) { +string dir, f; + strcpy(dir, path ? path : ""); + replace(dir, "/", "\\"); + +lstring type, part; + strcpy(f, ""); + split(type, "|", filter); + for(int i = 0; i < count(type); i++) { + split(part, ";", type[i]); + if(count(part) != 2)continue; + + strcat(f, part[0]); + strcat(f, " ("); + strcat(f, part[1]); + strcat(f, ")|"); + replace(part[1], ",", ";"); + strcat(f, part[1]); + strcat(f, "|"); + } + +char *pf = f(); + for(int i = strlen(pf) - 1; i >= 0; i--) { + if(pf[i] == '|') pf[i] = '\0'; + } + +OPENFILENAME ofn; + strcpy(filename, ""); + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = focus ? focus->p.hwnd : 0; + ofn.lpstrFilter = pf; + ofn.lpstrInitialDir = dir; + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; + ofn.lpstrDefExt = ""; + + return GetOpenFileName(&ofn); +} + +bool pMiu::file_save(Window *focus, char *filename, const char *filter, const char *path) { +string dir, f; + strcpy(dir, path ? path : ""); + replace(dir, "/", "\\"); + +lstring type, part; + strcpy(f, ""); + split(type, "|", filter); + for(int i = 0; i < count(type); i++) { + split(part, ";", type[i]); + if(count(part) != 2)continue; + + strcat(f, part[0]); + strcat(f, " ("); + strcat(f, part[1]); + strcat(f, ")|"); + replace(part[1], ",", ";"); + strcat(f, part[1]); + strcat(f, "|"); + } + +char *pf = f(); + for(int i = strlen(pf) - 1; i >= 0; i--) { + if(pf[i] == '|') pf[i] = '\0'; + } + +OPENFILENAME ofn; + strcpy(filename, ""); + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = focus ? focus->p.hwnd : 0; + ofn.lpstrFilter = pf; + ofn.lpstrInitialDir = dir; + ofn.lpstrFile = filename; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; + ofn.lpstrDefExt = ""; + + return GetSaveFileName(&ofn); +} + +uint pMiu::screen_width() { + return GetSystemMetrics(SM_CXSCREEN); +} + +uint pMiu::screen_height() { + return GetSystemMetrics(SM_CYSCREEN); +} + +pMiu& pMiu::handle() { + return miu().p; +} + +pMiu::pMiu(Miu &self_) : self(self_) { +} + +pMiu& pmiu() { + return pMiu::handle(); +} + +/* internal */ + +HFONT pMiu::create_font(const char *name, uint size) { +HDC hdc = GetDC(0); +HFONT font = CreateFont(-MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, name); + ReleaseDC(0, hdc); + return font; +} + +Widget* pMiu::get_widget(uint instance) { +Widget *widget = 0; + for(uint i = 0; i < widget_list.size(); i++) { + if(widget_list[i]->p.instance != instance) continue; + widget = widget_list[i]; + break; + } + return widget; +} + +long __stdcall pmiu_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + return pmiu().wndproc(hwnd, msg, wparam, lparam); +} + +long pMiu::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { +pWidget *p = (pWidget*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch(msg) { + 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(Event::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(Event::Block, 0, &w)); + } break; + + case WM_KEYDOWN: { + if(!p || p->self.type != Widget::WindowType) break; + Window &w = ((pWindow*)p)->self; + if(w.on_keydown) w.on_keydown(Event(Event::KeyDown, translate_key(wparam), &w)); + } break; + + case WM_KEYUP: { + if(!p || p->self.type != Widget::WindowType) break; + Window &w = ((pWindow*)p)->self; + if(w.on_keyup) w.on_keyup(Event(Event::KeyUp, translate_key(wparam), &w)); + } 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 = pmiu().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)->blit(); + } 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(Event::Tick, 0, &w)); + } break; + case Widget::MenuCheckItemType: { + MenuCheckItem &w = (MenuCheckItem&)*widget; + w.check(!w.checked()); //invert check state + } break; + case Widget::MenuRadioItemType: { + MenuRadioItem &w = (MenuRadioItem&)*widget; + w.check(); + } break; + case Widget::ButtonType: { + Button &w = (Button&)*widget; + if(w.on_tick) w.on_tick(Event(Event::Tick, 0, &w)); + } break; + case Widget::CheckboxType: { + Checkbox &w = (Checkbox&)*widget; + w.check(!w.checked()); //invert check state + } break; + case Widget::RadioboxType: { + Radiobox &w = (Radiobox&)*widget; + w.check(); + } 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(Event::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(Event::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; + if(((LPNMHDR)lparam)->code == LVN_ITEMCHANGED + && ((LPNMLISTVIEW)lparam)->uChanged & LVIF_STATE + && ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_FOCUSED) + && ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_SELECTED) + ) { + if(listbox.on_change) listbox.on_change(Event(Event::Change, listbox.get_selection(), &listbox)); + } else if(((LPNMHDR)lparam)->code == LVN_ITEMACTIVATE) { + if(listbox.on_activate) listbox.on_activate(Event(Event::Activate, listbox.get_selection(), &listbox)); + } + } break; + } + } break; + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +} //namespace ns_miu diff --git a/src/lib/miu.win/miu.win.editbox.cpp b/src/lib/miu.win/miu.win.editbox.cpp new file mode 100644 index 00000000..76388572 --- /dev/null +++ b/src/lib/miu.win/miu.win.editbox.cpp @@ -0,0 +1,37 @@ +void pEditbox::create(uint style, uint width, uint height, const char *text) { +bool multiline = style & Editbox::Multiline; +bool readonly = style & Editbox::Readonly; +uint vscroll = (style & Editbox::VerticalScrollAlways) ? WS_VSCROLL : + (style & Editbox::VerticalScrollNever) ? 0 : + ES_AUTOVSCROLL; +uint hscroll = (style & Editbox::HorizontalScrollAlways) ? WS_HSCROLL : + (style & Editbox::HorizontalScrollNever) ? 0 : + ES_AUTOHSCROLL; + + hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD | WS_VISIBLE | vscroll | hscroll | + (multiline == true ? ES_MULTILINE : 0) | + (readonly == true ? ES_READONLY : 0), + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); + set_text(text); +} + +void pEditbox::set_text(const char *text) { +string temp = text ? text : ""; + replace(temp, "\r", ""); + replace(temp, "\n", "\r\n"); + SetWindowText(hwnd, temp); +} + +uint pEditbox::get_text(char *text, uint length) { + GetWindowText(hwnd, text, length); +string temp = text; + replace(temp, "\r", ""); + strcpy(text, temp); + return strlen(text); +} + +pEditbox::pEditbox(Editbox &self_) : pFormControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.editbox.h b/src/lib/miu.win/miu.win.editbox.h new file mode 100644 index 00000000..6cd3f5a6 --- /dev/null +++ b/src/lib/miu.win/miu.win.editbox.h @@ -0,0 +1,9 @@ +class pEditbox : public pFormControl { +public: + Editbox &self; + void create(uint style, uint width, uint height, const char *text = ""); + uint get_text(char *text, uint length = -1U); + void set_text(const char *text = ""); + + pEditbox(Editbox&); +}; diff --git a/src/lib/miu.win/miu.win.formcontrol.cpp b/src/lib/miu.win/miu.win.formcontrol.cpp new file mode 100644 index 00000000..3f96e298 --- /dev/null +++ b/src/lib/miu.win/miu.win.formcontrol.cpp @@ -0,0 +1,31 @@ +void pFormControl::resize(uint width, uint 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; +} diff --git a/src/lib/miu.win/miu.win.formcontrol.h b/src/lib/miu.win/miu.win.formcontrol.h new file mode 100644 index 00000000..7d4e119a --- /dev/null +++ b/src/lib/miu.win/miu.win.formcontrol.h @@ -0,0 +1,16 @@ +class pFormControl : public pWidget { +public: + virtual void resize(uint width, uint height); + void focus(); + bool focused(); + void enable(bool = true); + void disable(); + bool enabled(); + uintptr_t handle(); + + FormControl &self; + pFormControl(FormControl&); + +/* internal */ + HWND hwnd; +}; diff --git a/src/lib/miu.win/miu.win.frame.cpp b/src/lib/miu.win/miu.win.frame.cpp new file mode 100644 index 00000000..e7386977 --- /dev/null +++ b/src/lib/miu.win/miu.win.frame.cpp @@ -0,0 +1,13 @@ +void pFrame::create(uint style, uint width, uint height, const char *text) { + hwnd = CreateWindow("BUTTON", text ? text : "", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); +} + +void pFrame::set_text(const char *text) { + SetWindowText(hwnd, text ? text : ""); +} + +pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.frame.h b/src/lib/miu.win/miu.win.frame.h new file mode 100644 index 00000000..742afcc9 --- /dev/null +++ b/src/lib/miu.win/miu.win.frame.h @@ -0,0 +1,8 @@ +class pFrame : public pFormControl { +public: + Frame &self; + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + pFrame(Frame&); +}; diff --git a/src/lib/miu.win/miu.win.h b/src/lib/miu.win/miu.win.h new file mode 100644 index 00000000..5cf41e29 --- /dev/null +++ b/src/lib/miu.win/miu.win.h @@ -0,0 +1,73 @@ +#ifndef MIU_WIN_H +#define MIU_WIN_H + +#undef WINVER +#undef _WIN32_WINNT +#undef _WIN32_IE + +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0600 + +#include +#include + +#include "../miu.h" + +namespace ns_miu { + +#include "miu.win.widget.h" + #include "miu.win.window.h" + #include "miu.win.menucontrol.h" + #include "miu.win.menugroup.h" + #include "miu.win.menuitem.h" + #include "miu.win.menucheckitem.h" + #include "miu.win.menuradioitem.h" + #include "miu.win.menuseparator.h" + #include "miu.win.formcontrol.h" + #include "miu.win.frame.h" + #include "miu.win.canvas.h" + #include "miu.win.label.h" + #include "miu.win.button.h" + #include "miu.win.checkbox.h" + #include "miu.win.radiobox.h" + #include "miu.win.editbox.h" + #include "miu.win.listbox.h" + #include "miu.win.combobox.h" + #include "miu.win.progressbar.h" + #include "miu.win.slider.h" + +class pMiu { +public: + Miu &self; + void init(); + void term(); + bool run(); + bool pending(); + + bool file_load(Window *focus, char *filename, const char *filter, const char *path); + bool file_save(Window *focus, char *filename, const char *filter, const char *path); + + uint screen_width(); + uint screen_height(); + + static pMiu& handle(); + pMiu(Miu&); + +/* internal */ + 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, uint size); + + array widget_list; + Widget* get_widget(uint instance); + long wndproc(HWND, UINT, WPARAM, LPARAM); + uint16 translate_key(uint key); +}; + +pMiu& pmiu(); + +} //namsepace ns_miu + +#endif //ifndef MIU_WIN_H diff --git a/src/lib/miu.win/miu.win.keymap.cpp b/src/lib/miu.win/miu.win.keymap.cpp new file mode 100644 index 00000000..221a2894 --- /dev/null +++ b/src/lib/miu.win/miu.win.keymap.cpp @@ -0,0 +1,67 @@ +uint16 pMiu::translate_key(uint key) { + switch(key) { + case VK_ESCAPE: return keymap::esc; + + case VK_F1: return keymap::f1; + case VK_F2: return keymap::f2; + case VK_F3: return keymap::f3; + case VK_F4: return keymap::f4; + case VK_F5: return keymap::f5; + case VK_F6: return keymap::f6; + case VK_F7: return keymap::f7; + case VK_F8: return keymap::f8; + case VK_F9: return keymap::f9; + case VK_F10: return keymap::f10; + case VK_F11: return keymap::f11; + case VK_F12: return keymap::f12; + + case VK_TAB: return keymap::tab; + case VK_RETURN: return keymap::enter; + case VK_SPACE: return keymap::space; + + case '0': return keymap::num_0; + case '1': return keymap::num_1; + case '2': return keymap::num_2; + case '3': return keymap::num_3; + case '4': return keymap::num_4; + case '5': return keymap::num_5; + case '6': return keymap::num_6; + case '7': return keymap::num_7; + case '8': return keymap::num_8; + case '9': return keymap::num_9; + + case 'A': return keymap::a; + case 'B': return keymap::b; + case 'C': return keymap::c; + case 'D': return keymap::d; + case 'E': return keymap::e; + case 'F': return keymap::f; + case 'G': return keymap::g; + case 'H': return keymap::h; + case 'I': return keymap::i; + case 'J': return keymap::j; + case 'K': return keymap::k; + case 'L': return keymap::l; + case 'M': return keymap::m; + case 'N': return keymap::n; + case 'O': return keymap::o; + case 'P': return keymap::p; + case 'Q': return keymap::q; + case 'R': return keymap::r; + case 'S': return keymap::s; + case 'T': return keymap::t; + case 'U': return keymap::u; + case 'V': return keymap::v; + case 'W': return keymap::w; + case 'X': return keymap::x; + case 'Y': return keymap::y; + case 'Z': return keymap::z; + + case VK_UP: return keymap::up; + case VK_DOWN: return keymap::down; + case VK_LEFT: return keymap::left; + case VK_RIGHT: return keymap::right; + } + + return keymap::none; +} diff --git a/src/lib/miu.win/miu.win.label.cpp b/src/lib/miu.win/miu.win.label.cpp new file mode 100644 index 00000000..48d34ea7 --- /dev/null +++ b/src/lib/miu.win/miu.win.label.cpp @@ -0,0 +1,13 @@ +void pLabel::create(uint style, uint width, uint height, const char *text) { + hwnd = CreateWindow("STATIC", text ? text : "", WS_CHILD | WS_VISIBLE, + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); +} + +void pLabel::set_text(const char *text) { + SetWindowText(hwnd, text ? text : ""); +} + +pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.label.h b/src/lib/miu.win/miu.win.label.h new file mode 100644 index 00000000..5c4368b7 --- /dev/null +++ b/src/lib/miu.win/miu.win.label.h @@ -0,0 +1,8 @@ +class pLabel : public pFormControl { +public: + Label &self; + void create(uint style, uint width, uint height, const char *text = ""); + void set_text(const char *text = ""); + + pLabel(Label&); +}; diff --git a/src/lib/miu.win/miu.win.listbox.cpp b/src/lib/miu.win/miu.win.listbox.cpp new file mode 100644 index 00000000..b97fb647 --- /dev/null +++ b/src/lib/miu.win/miu.win.listbox.cpp @@ -0,0 +1,92 @@ +void pListbox::create(uint style, uint width, uint height, const char *columns, const char *text) { +bool header = style & Listbox::Header; +uint hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL : + (style & Listbox::HorizontalScrollNever) ? 0 : + 0; +uint vscroll = (style & Listbox::VerticalScrollAlways) ? WS_VSCROLL : + (style & Listbox::VerticalScrollNever) ? 0 : + 0; + hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, "", + WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll | + (header ? 0 : LVS_NOCOLUMNHEADER), + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); + ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT); + +lstring list; + split(list, "\t", columns ? columns : ""); + column_count = count(list); + for(uint i = 0; i < count(list); i++) { + LVCOLUMN column; + column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM; + column.fmt = LVCFMT_LEFT; + column.iSubItem = count(list); + column.pszText = (LPSTR)list[i](); + ListView_InsertColumn(hwnd, i, &column); + } + + if(text && *text) { + split(list, "\n", text); + for(uint i = 0; i < count(list); i++) add_item(list[i]); + } + autosize_columns(); +} + +void pListbox::autosize_columns() { + for(uint i = 0; i < column_count; i++) { + ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER); + } +} + +void pListbox::set_column_width(uint column, uint width) { + ListView_SetColumnWidth(hwnd, column, width); +} + +void pListbox::add_item(const char *text) { +lstring list; + split(list, "\t", text ? text : ""); +LVITEM item; +uint pos = ListView_GetItemCount(hwnd); + item.mask = LVIF_TEXT; + item.iItem = pos; + item.iSubItem = 0; + item.pszText = (LPSTR)list[0](); + ListView_InsertItem(hwnd, &item); + + for(uint i = 1; i < count(list); i++) { + ListView_SetItemText(hwnd, pos, i, (LPSTR)list[i]()); + } +} + +void pListbox::set_item(uint index, const char *text) { +lstring list; + split(list, "\t", text ? text : ""); + for(uint i = 0; i < count(list); i++) { + ListView_SetItemText(hwnd, index, i, list[i]()); + } +} + +int pListbox::get_selection() { +uint count = ListView_GetItemCount(hwnd); + for(uint i = 0; i < count; i++) { + if(ListView_GetItemState(hwnd, i, LVIS_SELECTED)) return i; + } + return -1; +} + +void pListbox::set_selection(int index) { +uint count = ListView_GetItemCount(hwnd); + for(uint 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; +} diff --git a/src/lib/miu.win/miu.win.listbox.h b/src/lib/miu.win/miu.win.listbox.h new file mode 100644 index 00000000..e36b3a4d --- /dev/null +++ b/src/lib/miu.win/miu.win.listbox.h @@ -0,0 +1,17 @@ +class pListbox : public pFormControl { +public: + Listbox &self; + void create(uint style, uint width, uint height, const char *columns = "", const char *text = ""); + void autosize_columns(); + void set_column_width(uint column, uint width); + void add_item(const char *text); + void set_item(uint index, const char *text); + int get_selection(); + void set_selection(int index); + void reset(); + + pListbox(Listbox&); + +/* internal */ + uint column_count; +}; diff --git a/src/lib/miu.win/miu.win.menucheckitem.cpp b/src/lib/miu.win/miu.win.menucheckitem.cpp new file mode 100644 index 00000000..b327ce8f --- /dev/null +++ b/src/lib/miu.win/miu.win.menucheckitem.cpp @@ -0,0 +1,27 @@ +void pMenuCheckItem::create(const char *text_) { + text = strdup(text_); +} + +void pMenuCheckItem::check(bool state) { +bool prev = checked(); + CheckMenuItem(parent, instance, state ? MF_CHECKED : MF_UNCHECKED); + if(prev != state) { + if(self.on_tick) self.on_tick(Event(Event::Tick, state, &self)); + } +} + +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; +} + +pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.menucheckitem.h b/src/lib/miu.win/miu.win.menucheckitem.h new file mode 100644 index 00000000..9bcacade --- /dev/null +++ b/src/lib/miu.win/miu.win.menucheckitem.h @@ -0,0 +1,10 @@ +class pMenuCheckItem : public pMenuControl { +public: + void create(const char *text = ""); + void check(bool state = true); + void uncheck(); + bool checked(); + + MenuCheckItem &self; + pMenuCheckItem(MenuCheckItem&); +}; diff --git a/src/lib/miu.win/miu.win.menucontrol.cpp b/src/lib/miu.win/miu.win.menucontrol.cpp new file mode 100644 index 00000000..9e118af3 --- /dev/null +++ b/src/lib/miu.win/miu.win.menucontrol.cpp @@ -0,0 +1,25 @@ +void pMenuControl::enable(bool state) { + EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED)); +} + +void pMenuControl::disable() { + enable(false); +} + +bool pMenuControl::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; +} + +pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) { + parent = 0; + text = 0; +} + +pMenuControl::~pMenuControl() { + safe_free(text); +} diff --git a/src/lib/miu.win/miu.win.menucontrol.h b/src/lib/miu.win/miu.win.menucontrol.h new file mode 100644 index 00000000..5dc179b9 --- /dev/null +++ b/src/lib/miu.win/miu.win.menucontrol.h @@ -0,0 +1,14 @@ +class pMenuControl : public pWidget { +public: + void enable(bool = true); + void disable(); + bool enabled(); + + MenuControl &self; + pMenuControl(MenuControl&); + virtual ~pMenuControl(); + +/* internal */ + HMENU parent; + char *text; +}; diff --git a/src/lib/miu.win/miu.win.menugroup.cpp b/src/lib/miu.win/miu.win.menugroup.cpp new file mode 100644 index 00000000..b1b4a2a7 --- /dev/null +++ b/src/lib/miu.win/miu.win.menugroup.cpp @@ -0,0 +1,31 @@ +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, (uint)((MenuGroup&)menucontrol).p.group, menucontrol.p.text); + } break; + + case Widget::MenuItemType: + case Widget::MenuCheckItemType: + case Widget::MenuRadioItemType: { + AppendMenu(group, MF_STRING, menucontrol.p.instance, 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, ""); + } break; + } + + menucontrol.p.parent = group; +} + +pMenuGroup::pMenuGroup(MenuGroup &self_) : pMenuControl(self_), self(self_) { + group = 0; +} diff --git a/src/lib/miu.win/miu.win.menugroup.h b/src/lib/miu.win/miu.win.menugroup.h new file mode 100644 index 00000000..da3bdaed --- /dev/null +++ b/src/lib/miu.win/miu.win.menugroup.h @@ -0,0 +1,11 @@ +class pMenuGroup : public pMenuControl { +public: + MenuGroup &self; + void create(const char *text); + void attach(MenuControl &menucontrol); + + pMenuGroup(MenuGroup&); + +/* internal */ + HMENU group; +}; diff --git a/src/lib/miu.win/miu.win.menuitem.cpp b/src/lib/miu.win/miu.win.menuitem.cpp new file mode 100644 index 00000000..98ea66c2 --- /dev/null +++ b/src/lib/miu.win/miu.win.menuitem.cpp @@ -0,0 +1,6 @@ +void pMenuItem::create(const char *text_) { + text = strdup(text_); +} + +pMenuItem::pMenuItem(MenuItem &self_) : pMenuControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.menuitem.h b/src/lib/miu.win/miu.win.menuitem.h new file mode 100644 index 00000000..715f8cc3 --- /dev/null +++ b/src/lib/miu.win/miu.win.menuitem.h @@ -0,0 +1,7 @@ +class pMenuItem : public pMenuControl { +public: + void create(const char *text = ""); + + MenuItem &self; + pMenuItem(MenuItem&); +}; diff --git a/src/lib/miu.win/miu.win.menuradioitem.cpp b/src/lib/miu.win/miu.win.menuradioitem.cpp new file mode 100644 index 00000000..0b69f6b3 --- /dev/null +++ b/src/lib/miu.win/miu.win.menuradioitem.cpp @@ -0,0 +1,26 @@ +void pMenuRadioItem::create(MenuRadioItemGroup &group_, const char *text_) { + group = group_; + text = strdup(text_); + create_checked = (group[0] == &self); +} + +void pMenuRadioItem::check() { +bool prev = checked(); + for(uint i = 0; i < group.size(); i++) { + CheckMenuItem(parent, group[i]->p.instance, (group[i] == &self) ? MF_CHECKED : MF_UNCHECKED); + } + if(prev == false && self.on_tick) self.on_tick(Event(Event::Tick, 0, &self)); +} + +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; +} + +pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) { + create_checked = false; +} diff --git a/src/lib/miu.win/miu.win.menuradioitem.h b/src/lib/miu.win/miu.win.menuradioitem.h new file mode 100644 index 00000000..2776ff64 --- /dev/null +++ b/src/lib/miu.win/miu.win.menuradioitem.h @@ -0,0 +1,13 @@ +class pMenuRadioItem : public pMenuControl { +public: + void create(MenuRadioItemGroup &group, const char *text = ""); + void check(); + bool checked(); + + MenuRadioItem &self; + pMenuRadioItem(MenuRadioItem&); + +/* internal */ + MenuRadioItemGroup group; + bool create_checked; +}; diff --git a/src/lib/miu.win/miu.win.menuseparator.cpp b/src/lib/miu.win/miu.win.menuseparator.cpp new file mode 100644 index 00000000..4fa3e0c1 --- /dev/null +++ b/src/lib/miu.win/miu.win.menuseparator.cpp @@ -0,0 +1,5 @@ +void pMenuSeparator::create() { +} + +pMenuSeparator::pMenuSeparator(MenuSeparator &self_) : pMenuControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.menuseparator.h b/src/lib/miu.win/miu.win.menuseparator.h new file mode 100644 index 00000000..c270b58b --- /dev/null +++ b/src/lib/miu.win/miu.win.menuseparator.h @@ -0,0 +1,7 @@ +class pMenuSeparator : public pMenuControl { +public: + MenuSeparator &self; + void create(); + + pMenuSeparator(MenuSeparator&); +}; diff --git a/src/lib/miu.win/miu.win.progressbar.cpp b/src/lib/miu.win/miu.win.progressbar.cpp new file mode 100644 index 00000000..6518b28e --- /dev/null +++ b/src/lib/miu.win/miu.win.progressbar.cpp @@ -0,0 +1,20 @@ +void pProgressbar::create(uint style, uint width, uint height) { + hwnd = CreateWindow(PROGRESS_CLASS, "", WS_CHILD | WS_VISIBLE | PBS_SMOOTH, + 0, 0, width, height, + miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); + SendMessage(hwnd, PBM_SETSTEP, MAKEWPARAM(1, 0), 0); +} + +uint pProgressbar::get_progress() { +uint progress = SendMessage(hwnd, PBM_GETPOS, 0, 0); + return max(0, min(progress, 100)); +} + +void pProgressbar::set_progress(uint progress) { + progress = max(0, min(progress, 100)); + SendMessage(hwnd, PBM_SETPOS, (WPARAM)progress, 0); +} + +pProgressbar::pProgressbar(Progressbar &self_) : pFormControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.progressbar.h b/src/lib/miu.win/miu.win.progressbar.h new file mode 100644 index 00000000..d3ca64c4 --- /dev/null +++ b/src/lib/miu.win/miu.win.progressbar.h @@ -0,0 +1,9 @@ +class pProgressbar : public pFormControl { +public: + Progressbar &self; + void create(uint style, uint width, uint height); + uint get_progress(); + void set_progress(uint progress); + + pProgressbar(Progressbar&); +}; diff --git a/src/lib/miu.win/miu.win.radiobox.cpp b/src/lib/miu.win/miu.win.radiobox.cpp new file mode 100644 index 00000000..f857db1d --- /dev/null +++ b/src/lib/miu.win/miu.win.radiobox.cpp @@ -0,0 +1,26 @@ +void pRadiobox::create(RadioboxGroup &group_, uint style, uint width, uint height, const char *text) { + group = group_; + hwnd = CreateWindow("BUTTON", text ? text : "", WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON, + 0, 0, width, height, miu().p.default_hwnd, (HMENU)instance, GetModuleHandle(0), 0); + SendMessage(hwnd, WM_SETFONT, (WPARAM)miu().p.default_font, 0); + if(group[0] == &self) check(); +} + +void pRadiobox::set_text(const char *text) { + SetWindowText(hwnd, text); +} + +void pRadiobox::check() { +bool prev = checked(); + for(uint i = 0; i < group.size(); i++) { + SendMessage(group[i]->p.hwnd, BM_SETCHECK, (WPARAM)(group[i] == &self), 0); + } + if(prev == false && self.on_tick) self.on_tick(Event(Event::Tick, 0, &self)); +} + +bool pRadiobox::checked() { + return SendMessage(hwnd, BM_GETCHECK, 0, 0); +} + +pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self_), self(self_) { +} diff --git a/src/lib/miu.win/miu.win.radiobox.h b/src/lib/miu.win/miu.win.radiobox.h new file mode 100644 index 00000000..40dae4f7 --- /dev/null +++ b/src/lib/miu.win/miu.win.radiobox.h @@ -0,0 +1,13 @@ +class pRadiobox : public pFormControl { +public: + void create(RadioboxGroup &group, uint style, uint width, uint 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/miu.win/miu.win.slider.cpp b/src/lib/miu.win/miu.win.slider.cpp new file mode 100644 index 00000000..e41ad000 --- /dev/null +++ b/src/lib/miu.win/miu.win.slider.cpp @@ -0,0 +1,24 @@ +void pSlider::create(uint style, uint width, uint height, uint length) { + if(length < 1) length = 1; + + hwnd = CreateWindow(TRACKBAR_CLASS, "", + WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_BOTH | + (style & Slider::Vertical ? TBS_VERT : TBS_HORZ), + 0, 0, width, height, + miu().p.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); +} + +uint pSlider::get_position() { + return SendMessage(hwnd, TBM_GETPOS, 0, 0); +} + +void pSlider::set_position(uint 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/miu.win/miu.win.slider.h b/src/lib/miu.win/miu.win.slider.h new file mode 100644 index 00000000..17b11e57 --- /dev/null +++ b/src/lib/miu.win/miu.win.slider.h @@ -0,0 +1,12 @@ +class pSlider : public pFormControl { +public: + Slider &self; + void create(uint style, uint width, uint height, uint length); + uint get_position(); + void set_position(uint position); + + pSlider(Slider&); + +/* internal */ + uint slider_position; +}; diff --git a/src/lib/miu.win/miu.win.widget.cpp b/src/lib/miu.win/miu.win.widget.cpp new file mode 100644 index 00000000..ea6b74a5 --- /dev/null +++ b/src/lib/miu.win/miu.win.widget.cpp @@ -0,0 +1,27 @@ +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++; + miu().p.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) +uint pWidget::instance_counter = 100; diff --git a/src/lib/miu.win/miu.win.widget.h b/src/lib/miu.win/miu.win.widget.h new file mode 100644 index 00000000..5354a262 --- /dev/null +++ b/src/lib/miu.win/miu.win.widget.h @@ -0,0 +1,19 @@ +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 uint instance_counter; + uint instance; +}; diff --git a/src/lib/miu.win/miu.win.window.cpp b/src/lib/miu.win/miu.win.window.cpp new file mode 100644 index 00000000..460a37d1 --- /dev/null +++ b/src/lib/miu.win/miu.win.window.cpp @@ -0,0 +1,183 @@ +void pWindow::create(uint style, uint width_, uint height_, const char *text) { + auto_center = style & Window::AutoCenter; + +RECT rc; + SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); + + hwnd = CreateWindowEx(0, "miu_window", text ? text : "", + WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, + rc.left, rc.top, width_, height_, + 0, 0, GetModuleHandle(0), 0); + hwndr = CreateWindowEx(0, "miu_window", text ? text : "", + WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, + rc.left, rc.top, width_, height_, + 0, 0, GetModuleHandle(0), 0); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); + menu = CreateMenu(); + + resize(width_, height_); +} + +void pWindow::close() { + CloseWindow(hwnd); +} + +void pWindow::move(uint x, uint y) { + if(is_fullscreen == true) return; + SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +void pWindow::resize(uint width_, uint height_) { + if(is_fullscreen == true) { + width_ = GetSystemMetrics(SM_CXSCREEN); + height_ = GetSystemMetrics(SM_CYSCREEN); + SetWindowPos(hwnd, 0, 0, 0, width_, 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); + +int x = (GetSystemMetrics(SM_CXSCREEN) - width_) / 2; +int y = (GetSystemMetrics(SM_CYSCREEN) - height_) / 2; + +//if window is larger than screen, force window to top-left corner + SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0); + if(x < rc.left) x = rc.left; + if(y < rc.top) y = rc.top; + + 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); +} + +void pWindow::set_background_color(uint8 r, uint8 g, uint8 b) { + if(background) DeleteObject(background); + background = CreateSolidBrush(RGB(r, g, b)); +} + +void pWindow::set_text(const char *text) { + SetWindowText(hwnd, text); +} + +void pWindow::attach(Window &window, uint x, uint 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); + 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(menu, MF_STRING | MF_POPUP, (uint)menugroup.p.group, menugroup.p.text); + if(menu_visible() == false) menu_show(); +} + +void pWindow::attach(FormControl &formcontrol, uint x, uint y) { + SetWindowPos(formcontrol.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + SetParent(formcontrol.p.hwnd, hwnd); +} + +void pWindow::move(Window &window, uint x, uint y) { + SetWindowPos(window.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +void pWindow::move(FormControl &formcontrol, uint x, uint y) { + SetWindowPos(formcontrol.p.hwnd, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +void pWindow::menu_show(bool state) { + if(!menu) return; + if(state) { + SetMenu(hwnd, menu); + SetMenu(hwndr, menu); + } else { + SetMenu(hwnd, 0); + SetMenu(hwndr, 0); + } + resize(width, height); +} + +void pWindow::menu_hide() { + menu_show(false); +} + +bool pWindow::menu_visible() { + if(!menu) return false; + return GetMenu(hwnd); +} + +uintptr_t pWindow::handle() { + return (uintptr_t)hwnd; +} + +pWindow::pWindow(Window &self_) : pWidget(self_), self(self_) { + hwnd = 0; + hwndr = 0; + menu = 0; + background = 0; + is_fullscreen = false; + auto_center = false; + width = 0; + height = 0; +} + +pWindow::~pWindow() { + if(background) DeleteObject(background); +} diff --git a/src/lib/miu.win/miu.win.window.h b/src/lib/miu.win/miu.win.window.h new file mode 100644 index 00000000..eeefebc2 --- /dev/null +++ b/src/lib/miu.win/miu.win.window.h @@ -0,0 +1,39 @@ +class pWindow : public pWidget { +public: + Window &self; + void create(uint style, uint width, uint height, const char *text = ""); + void close(); + void move(uint x, uint y); + void resize(uint width, uint height); + void focus(); + bool focused(); + void fullscreen(); + void unfullscreen(); + void set_background_color(uint8 r, uint8 g, uint8 b); + void set_text(const char *text = ""); + void attach(Window &window, uint x, uint y); + void attach(MenuGroup &menugroup); + void attach(FormControl &formcontrol, uint x, uint y); + void move(Window &window, uint x, uint y); + void move(FormControl &formcontrol, uint x, uint y); + void menu_show(bool = true); + void menu_hide(); + bool menu_visible(); + uintptr_t handle(); + + pWindow(Window&); + ~pWindow(); + +/* internal */ + HWND hwnd; + HWND hwndr; //hidden window, used as resize assistant + HMENU menu; + HBRUSH background; + bool is_fullscreen; + bool auto_center; + uint width, height; + + void show(bool = true); + void hide(); + bool visible(); +}; diff --git a/src/lib/opgen.cpp b/src/lib/tool/opgen.cpp similarity index 94% rename from src/lib/opgen.cpp rename to src/lib/tool/opgen.cpp index 487631a6..ed50771d 100644 --- a/src/lib/opgen.cpp +++ b/src/lib/tool/opgen.cpp @@ -1,3 +1,5 @@ +/* broken -- need to port libstring to bstring */ + #include "libbase.h" #include "libstring.h" #include "libstring.cpp" diff --git a/src/lib/opgen_s.cpp b/src/lib/tool/opgen_s.cpp similarity index 93% rename from src/lib/opgen_s.cpp rename to src/lib/tool/opgen_s.cpp index 054b705d..2ffd360d 100644 --- a/src/lib/opgen_s.cpp +++ b/src/lib/tool/opgen_s.cpp @@ -1,3 +1,5 @@ +/* broken -- need to port libstring to bstring */ + #include "libbase.h" #include "libstring.h" #include "libstring.cpp" diff --git a/src/lib/opgen_so.cpp b/src/lib/tool/opgen_so.cpp similarity index 94% rename from src/lib/opgen_so.cpp rename to src/lib/tool/opgen_so.cpp index 13d0bdd2..1f948bd9 100644 --- a/src/lib/opgen_so.cpp +++ b/src/lib/tool/opgen_so.cpp @@ -1,3 +1,5 @@ +/* broken -- need to port libstring to bstring */ + #include "libbase.h" #include "libstring.h" #include "libstring.cpp" diff --git a/src/memory/memory.h b/src/memory/memory.h index 904d41c6..eb33ff44 100644 --- a/src/memory/memory.h +++ b/src/memory/memory.h @@ -76,9 +76,17 @@ enum MapMode { MapDirect, MapLinear, MapShadow }; Memory &access, uint offset = 0, uint size = 0); alwaysinline uint8 read(uint addr) { + #if defined(CHEAT_SYSTEM) + if(cheat.enabled() && cheat.exists(addr)) { + uint8 r; + if(cheat.read(addr, r)) return r; + } + #endif + Page &p = page[addr >> 8]; return p.access->read(p.offset + addr); } + alwaysinline void write(uint addr, uint8 data) { Page &p = page[addr >> 8]; return p.access->write(p.offset + addr, data); diff --git a/src/ui/audio/ao.cpp b/src/ui/audio/ao.cpp deleted file mode 100644 index d962b147..00000000 --- a/src/ui/audio/ao.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "ao.h" - -uint AudioAO::object_count = 0; - -void AudioAO::sample(uint16 l_sample, uint16 r_sample) { -uint32 samp = (l_sample << 0) + (r_sample << 16); - ao_play(audio_device, (char*)&samp, 4); //This may need to be byte swapped for Big Endian -} - -void AudioAO::update_frequency() { - Audio::update_frequency(); - driver_format.rate = frequency; - if(audio_device) { - term(); - init(); - } -} - -void AudioAO::init() { - audio_device = ao_open_live(driver_id, &driver_format, 0); - if(audio_device) { - ao_info *di = ao_driver_info(driver_id); - } else { - dprintf("libao: failed to open audio device.\n"); - } -} - -void AudioAO::term() { - if(audio_device) { - ao_close(audio_device); - audio_device = 0; - } -} - -AudioAO::AudioAO(const char *driver) { - if(!object_count++) { - ao_initialize(); - } - - driver_id = (driver && *driver) ? ao_driver_id(driver) : ao_default_driver_id(); - if(driver_id < 0) { driver_id = ao_default_driver_id(); } //fallback on default if driver doesn't exist - driver_format.bits = 16; - driver_format.channels = 2; - driver_format.rate = frequency; - driver_format.byte_format = AO_FMT_LITTLE; - audio_device = 0; -} - -AudioAO::~AudioAO() { - if(audio_device) { - ao_close(audio_device); - } - if(!--object_count) { - ao_shutdown(); - } -} diff --git a/src/ui/audio/ao.h b/src/ui/audio/ao.h deleted file mode 100644 index 1f44f82e..00000000 --- a/src/ui/audio/ao.h +++ /dev/null @@ -1,19 +0,0 @@ -#include - -class AudioAO : public Audio { -private: -static uint object_count; - -int driver_id; -ao_sample_format driver_format; -ao_device *audio_device; - -public: - void sample(uint16 l_sample, uint16 r_sample); - void update_frequency(); - void init(); - void term(); - - AudioAO(const char *driver = 0); - ~AudioAO(); -}; diff --git a/src/ui/audio/audio.cpp b/src/ui/audio/audio.cpp deleted file mode 100644 index 2201b46f..00000000 --- a/src/ui/audio/audio.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "audio.h" - -void Audio::update_frequency() { -uint freq = config::audio.frequency; -uint speed = config::system.speed_normal; - switch(uint(config::system.speed)) { - case 1: speed = config::system.speed_slowest; break; - case 2: speed = config::system.speed_slow; break; - case 3: speed = config::system.speed_normal; break; - case 4: speed = config::system.speed_fast; break; - case 5: speed = config::system.speed_fastest; break; - } -//convert speed setting from integer to fp-percentage and adjust default frequency by this value - frequency = uint( double(speed) * 0.01 * double(freq) ); -//convert latency from time in ms to time in samples, divide by 3 for ring buffers - latency = uint( (double(frequency) / 1000.0) * (double(config::audio.latency) / 3.0) ); -} - -Audio::Audio() { - update_frequency(); -} diff --git a/src/ui/audio/audio.h b/src/ui/audio/audio.h deleted file mode 100644 index 8086e6db..00000000 --- a/src/ui/audio/audio.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef AUDIO_H -#define AUDIO_H - -class Audio { -public: -uint frequency, latency; - virtual void sample(uint16 l_sample, uint16 r_sample) {} - virtual void update_frequency(); - virtual void clear_audio() {} - virtual void init() {} - virtual void term() {} - - Audio(); -} *uiAudio; - -#endif diff --git a/src/ui/audio/dsound.cpp b/src/ui/audio/dsound.cpp deleted file mode 100644 index 5e3ac2b2..00000000 --- a/src/ui/audio/dsound.cpp +++ /dev/null @@ -1,143 +0,0 @@ -void AudioDS::sample(uint16 l_sample, uint16 r_sample) { - data.buffer[data.buffer_pos++] = (l_sample << 0) + (r_sample << 16); - if(data.buffer_pos < latency)return; - -DWORD ring_pos, pos, size; - for(;;) { - dsb_b->GetCurrentPosition(&pos, 0); - ring_pos = pos / data.ring_size; - if( - config::system.regulate_speed == false || - config::audio.synchronize == false || - ring_pos != data.ring_pos - ) break; - Sleep(1); - } - - data.ring_pos = ring_pos; -void *output; - if(dsb_b->Lock(((data.ring_pos + 2) % 3) * data.ring_size, - data.ring_size, &output, &size, 0, 0, 0) == DS_OK) { - //Audio::resample_hermite((uint32*)output, data.buffer, latency, data.buffer_pos); - memcpy(output, data.buffer, data.ring_size); - dsb_b->Unlock(output, size, 0, 0); - } - - data.buffer_pos = 0; -} - -/*void AudioDS::sample(uint16 l_sample, uint16 r_sample) { - data.buffer[data.buffer_pos++] = (l_sample << 0) + (r_sample << 16); -//if(data.buffer_pos & 15)return; - -DWORD ring_pos, pos, size; - dsb_b->GetCurrentPosition(&pos, 0); - ring_pos = pos / data.ring_size; - if(ring_pos == data.ring_pos)return; - data.ring_pos = ring_pos; - -void *output; - if(dsb_b->Lock(((data.ring_pos + 2) % 3) * data.ring_size, - data.ring_size, &output, &size, 0, 0, 0) == DS_OK) { - Audio::resample_hermite((uint32*)output, data.buffer, latency, data.buffer_pos); - //memcpy(output, data.buffer, data.ring_size); - dsb_b->Unlock(output, size, 0, 0); - } - - dprintf("* %10d -> %10d / %10I64d", data.buffer_pos, latency, scheduler.clock.cpusmp); - - data.buffer_pos = 0; -}*/ - -void AudioDS::update_frequency() { - Audio::update_frequency(); - init(); -} - -void AudioDS::clear_audio() { - data.buffer_pos = 0; - data.ring_pos = 0; - if(data.buffer) { - memset(data.buffer, 0, data.buffer_size); - } - - if(!dsb_b)return; - - dsb_b->Stop(); - dsb_b->SetCurrentPosition(0); - -DWORD size; -void *output; - dsb_b->Lock(0, data.ring_size * 3, &output, &size, 0, 0, 0); - memset(output, 0, size); - dsb_b->Unlock(output, size, 0, 0); - - dsb_b->Play(0, 0, DSBPLAY_LOOPING); -} - -void AudioDS::init() { - clear_audio(); - term(); - - data.ring_size = latency * sizeof(uint32); - data.buffer_size = data.ring_size * 16; - data.buffer = (uint32*)malloc(data.buffer_size); - data.buffer_pos = 0; - - DirectSoundCreate(0, &ds, 0); - ds->SetCooperativeLevel(hwnd, DSSCL_PRIORITY); - - memset(&dsbd, 0, sizeof(dsbd)); - dsbd.dwSize = sizeof(dsbd); - dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; - dsbd.dwBufferBytes = 0; - dsbd.lpwfxFormat = 0; - ds->CreateSoundBuffer(&dsbd, &dsb_p, 0); - - memset(&wfx, 0, sizeof(wfx)); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = 2; - wfx.nSamplesPerSec = frequency; - wfx.wBitsPerSample = 16; - wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - dsb_p->SetFormat(&wfx); - - memset(&dsbd, 0, sizeof(dsbd)); - dsbd.dwSize = sizeof(dsbd); - dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY | - DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE; - dsbd.dwBufferBytes = data.ring_size * 3; - dsbd.guid3DAlgorithm = GUID_NULL; - dsbd.lpwfxFormat = &wfx; - ds->CreateSoundBuffer(&dsbd, &dsb_b, 0); - dsb_b->SetFrequency(frequency); - dsb_b->SetCurrentPosition(0); - - clear_audio(); -} - -void AudioDS::term() { - safe_free(data.buffer); - - if(dsb_b) { dsb_b->Stop(); dsb_b->Release(); dsb_b = 0; } - if(dsb_p) { dsb_p->Stop(); dsb_p->Release(); dsb_p = 0; } - if(ds) { ds->Release(); ds = 0; } -} - -AudioDS::AudioDS(HWND handle) { - hwnd = handle ? handle : GetDesktopWindow(); - ds = 0; - dsb_p = 0; - dsb_b = 0; - - data.buffer = 0; - data.buffer_pos = 0; - data.ring_pos = 0; - data.buffer_size = 0; - data.ring_size = 0; -} - -AudioDS::~AudioDS() { - term(); -} diff --git a/src/ui/audio/dsound.h b/src/ui/audio/dsound.h deleted file mode 100644 index 453b66b9..00000000 --- a/src/ui/audio/dsound.h +++ /dev/null @@ -1,25 +0,0 @@ -#include - -class AudioDS : public Audio { -public: -HWND hwnd; -LPDIRECTSOUND ds; -LPDIRECTSOUNDBUFFER dsb_p, dsb_b; -DSBUFFERDESC dsbd; -WAVEFORMATEX wfx; - -struct { - uint32 *buffer; - uint buffer_pos, ring_pos; - uint buffer_size, ring_size; -} data; - - void sample(uint16 l_sample, uint16 r_sample); - void update_frequency(); - void clear_audio(); - void init(); - void term(); - - AudioDS(HWND handle = 0); - ~AudioDS(); -}; diff --git a/src/ui/config.cpp b/src/ui/config.cpp index 5db727be..a670bf26 100644 --- a/src/ui/config.cpp +++ b/src/ui/config.cpp @@ -4,26 +4,15 @@ char filename[PATH_MAX + 16] = "bsnes.cfg"; struct System { static StringSetting video, audio, input; - static StringSetting video_flags, audio_flags, input_flags; - static IntegerSetting regulate_speed, speed; - static IntegerSetting speed_slowest, speed_slow, speed_normal, speed_fast, speed_fastest; } system; + StringSetting System::video(&config(), "system.video", "Video hardware interface", ""); StringSetting System::audio(&config(), "system.audio", "Audio hardware interface", ""); StringSetting System::input(&config(), "system.input", "Input hardware interface", ""); -StringSetting System::video_flags(&config(), "system.video_flags", "Video hardware interface flags", ""); -StringSetting System::audio_flags(&config(), "system.audio_flags", "Audio hardware interface flags", ""); -StringSetting System::input_flags(&config(), "system.input_flags", "Input hardware interface flags", ""); - IntegerSetting System::regulate_speed(&config(), "system.regulate_speed", "Regulate speed to 60hz (NTSC) / 50hz (PAL)", IntegerSetting::Boolean, true); -IntegerSetting System::speed (0, "system.speed", "Current speed regulation setting (1-5)", IntegerSetting::Decimal, 3); -IntegerSetting System::speed_slowest (&config(), "system.speed_slowest", "Slowest speed setting", IntegerSetting::Decimal, 50); -IntegerSetting System::speed_slow (&config(), "system.speed_slow", "Slow speed setting", IntegerSetting::Decimal, 75); -IntegerSetting System::speed_normal (&config(), "system.speed_normal", "Normal speed setting", IntegerSetting::Decimal, 100); -IntegerSetting System::speed_fast (&config(), "system.speed_fast", "Fast speed setting", IntegerSetting::Decimal, 150); -IntegerSetting System::speed_fastest (&config(), "system.speed_fastest", "Fastest speed setting", IntegerSetting::Decimal, 200); +IntegerSetting System::speed(0, "system.speed", "Current speed regulation setting (1-5)", IntegerSetting::Decimal, 3); struct Video { static IntegerSetting mode; @@ -86,16 +75,9 @@ IntegerSetting Video::use_vram(&config(), "video.use_vram", "Use Video RAM inste struct Audio { static IntegerSetting synchronize; static IntegerSetting frequency; - static IntegerSetting latency; } audio; IntegerSetting Audio::synchronize(&config(), "audio.synchronize", "Synchronize to audio sample rate.", IntegerSetting::Boolean, true); IntegerSetting Audio::frequency(&config(), "audio.frequency", "Default audio playback frequency.", IntegerSetting::Decimal, 32000); -IntegerSetting Audio::latency(&config(), "audio.latency", "Audio playback latency in milliseconds.\n" - "Specifies how long audio playback is delayed compared to a real SNES.\n" - "A delay is necessary to allow smooth audio playback via buffering.\n" - "Raising this value may help with audio playback problems, but will decrease\n" - "audio responsiveness.", - IntegerSetting::Decimal, 75); struct Input { static IntegerSetting axis_resistance; diff --git a/src/ui/input/dinput.cpp b/src/ui/input/dinput.cpp deleted file mode 100644 index 0f9f946f..00000000 --- a/src/ui/input/dinput.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "dinput.h" - -void InputDI::clear_input() { - memset(keystate, 0, sizeof keystate); -} - -void InputDI::poll() { - clear_input(); - -HRESULT hr; -DIJOYSTATE2 js; - if(di_key) { - hr = di_key->GetDeviceState(256, keystate); - if(FAILED(hr)) { - di_key->Acquire(); - hr = di_key->GetDeviceState(256, keystate); - } - } - - for(int i = 0; i < di_joy_count; i++) { - if(!di_joy[i])continue; - - memset(js.rgbButtons, 0, 128); - - hr = di_joy[i]->Poll(); - if(FAILED(hr)) { - di_joy[i]->Acquire(); - di_joy[i]->Poll(); - } - di_joy[i]->GetDeviceState(sizeof(DIJOYSTATE2), &js); - - uint index = keymap::joypad_flag | (i << 8); //joypad index - memcpy(keystate + index, js.rgbButtons, 128); - - //map d-pad axes - int resistance = config::input.axis_resistance; - if(resistance < 1)resistance = 1; - if(resistance > 99)resistance = 99; - resistance = int32(double(resistance) * 32768.0 / 100.0); - int resistance_lo = 0x7fff - resistance; - int resistance_hi = 0x8000 + resistance; - keystate[index + keymap::joypad_up] = (js.lY <= resistance_lo) ? 0x80 : 0x00; - keystate[index + keymap::joypad_down] = (js.lY >= resistance_hi) ? 0x80 : 0x00; - keystate[index + keymap::joypad_left] = (js.lX <= resistance_lo) ? 0x80 : 0x00; - keystate[index + keymap::joypad_right] = (js.lX >= resistance_hi) ? 0x80 : 0x00; - - //map analog POV (analog directional pad) as well - uint pov = js.rgdwPOV[0]; - keystate[index + keymap::joypad_up] |= (pov == 0 || pov == 31500 || pov == 4500) ? 0x80 : 0x00; - keystate[index + keymap::joypad_down] |= (pov == 18000 || pov == 13500 || pov == 22500) ? 0x80 : 0x00; - keystate[index + keymap::joypad_left] |= (pov == 27000 || pov == 22500 || pov == 31500) ? 0x80 : 0x00; - keystate[index + keymap::joypad_right] |= (pov == 9000 || pov == 4500 || pov == 13500) ? 0x80 : 0x00; - } -} - -BOOL CALLBACK DI_EnumJoypadsCallback(const DIDEVICEINSTANCE *instance, void *context) { - return static_cast(uiInput)->enum_joypads(instance); -} - -bool InputDI::enum_joypads(const DIDEVICEINSTANCE *instance) { -HRESULT hr = di->CreateDevice(instance->guidInstance, &di_joy[di_joy_count], 0); - if(FAILED(hr)) { - return DIENUM_CONTINUE; - } - - di_joy[di_joy_count]->SetDataFormat(&c_dfDIJoystick2); - di_joy[di_joy_count]->SetCooperativeLevel(owner, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - - if(++di_joy_count >= DIRECTINPUT_JOYMAX) { - //too many joypads? - return DIENUM_STOP; - } - - return DIENUM_CONTINUE; -} - -void InputDI::init() { - di_key = 0; - for(int i = 0; i < DIRECTINPUT_JOYMAX; i++)di_joy[i] = 0; - di = 0; - di_joy_count = 0; - - DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, - IID_IDirectInput8, (void**)&di, 0); - di->CreateDevice(GUID_SysKeyboard, &di_key, 0); - - di_key->SetDataFormat(&c_dfDIKeyboard); - di_key->SetCooperativeLevel(owner, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); - di_key->Acquire(); - - di->EnumDevices(DI8DEVCLASS_GAMECTRL, DI_EnumJoypadsCallback, 0, DIEDFL_ATTACHEDONLY); - - Input::init(); -} - -void InputDI::term() { - if(di_key) { di_key->Unacquire(); di_key->Release(); di_key = 0; } - for(int i = 0; i < DIRECTINPUT_JOYMAX; i++) { - if(di_joy[i]) { di_joy[i]->Unacquire(); di_joy[i]->Release(); di_joy[i] = 0; } - } - if(di) { di->Release(); di = 0; } - di_joy_count = 0; - - Input::term(); -} - -bool InputDI::key_down(uint16 key) { - return keystate[translate(key)] & 0x80; -} - -//translate keymap code to DirectInput code, to lookup key status in DI status table -uint16 InputDI::translate(uint16 key) { -//DI joypad codes share 1:1 mapping with keymap codes - if(key & keymap::joypad_flag) { return key; } - - switch(key) { - case keymap::esc: return 0x01; - - case keymap::f1: return 0x3b; - case keymap::f2: return 0x3c; - case keymap::f3: return 0x3d; - case keymap::f4: return 0x3e; - case keymap::f5: return 0x3f; - case keymap::f6: return 0x40; - case keymap::f7: return 0x41; - case keymap::f8: return 0x42; - case keymap::f9: return 0x43; - case keymap::f10: return 0x44; - case keymap::f11: return 0x57; - case keymap::f12: return 0x58; - - case keymap::print_screen: return 0xb7; - case keymap::scroll_lock: return 0x46; - case keymap::pause: return 0xc5; - - case keymap::grave: return 0x29; - - case keymap::num_1: return 0x02; - case keymap::num_2: return 0x03; - case keymap::num_3: return 0x04; - case keymap::num_4: return 0x05; - case keymap::num_5: return 0x06; - case keymap::num_6: return 0x07; - case keymap::num_7: return 0x08; - case keymap::num_8: return 0x09; - case keymap::num_9: return 0x0a; - case keymap::num_0: return 0x0b; - - case keymap::minus: return 0x0c; - case keymap::equal: return 0x0d; - case keymap::backspace: return 0x0e; - - case keymap::ins: return 0xd2; - case keymap::del: return 0xd3; - case keymap::home: return 0xc7; - case keymap::end: return 0xcf; - case keymap::page_up: return 0xc9; - case keymap::page_down: return 0xd1; - - case keymap::a: return 0x1e; - case keymap::b: return 0x30; - case keymap::c: return 0x2e; - case keymap::d: return 0x20; - case keymap::e: return 0x12; - case keymap::f: return 0x21; - case keymap::g: return 0x22; - case keymap::h: return 0x23; - case keymap::i: return 0x17; - case keymap::j: return 0x24; - case keymap::k: return 0x25; - case keymap::l: return 0x26; - case keymap::m: return 0x32; - case keymap::n: return 0x31; - case keymap::o: return 0x18; - case keymap::p: return 0x19; - case keymap::q: return 0x10; - case keymap::r: return 0x13; - case keymap::s: return 0x1f; - case keymap::t: return 0x14; - case keymap::u: return 0x16; - case keymap::v: return 0x2f; - case keymap::w: return 0x11; - case keymap::x: return 0x2d; - case keymap::y: return 0x15; - case keymap::z: return 0x2c; - - case keymap::lbracket: return 0x1a; - case keymap::rbracket: return 0x1b; - case keymap::backslash: return 0x2b; - case keymap::semicolon: return 0x27; - case keymap::apostrophe: return 0x28; - case keymap::comma: return 0x33; - case keymap::period: return 0x34; - case keymap::slash: return 0x35; - - case keymap::kp_1: return 0x4f; - case keymap::kp_2: return 0x50; - case keymap::kp_3: return 0x51; - case keymap::kp_4: return 0x4b; - case keymap::kp_5: return 0x4c; - case keymap::kp_6: return 0x4d; - case keymap::kp_7: return 0x47; - case keymap::kp_8: return 0x48; - case keymap::kp_9: return 0x49; - case keymap::kp_0: return 0x52; - case keymap::kp_decimal: return 0x53; - - case keymap::kp_plus: return 0x4e; - case keymap::kp_minus: return 0x4a; - case keymap::kp_mul: return 0x37; - case keymap::kp_div: return 0xb5; - case keymap::kp_enter: return 0x9c; - - case keymap::num_lock : return 0x45; - case keymap::caps_lock: return 0x3a; - - case keymap::up: return 0xc8; - case keymap::down: return 0xd0; - case keymap::left: return 0xcb; - case keymap::right: return 0xcd; - - case keymap::tab: return 0x0f; - case keymap::enter: return 0x1c; - case keymap::space: return 0x39; - - case keymap::lctrl : return 0x1d; - case keymap::rctrl : return 0x9d; - case keymap::lalt : return 0x38; - case keymap::ralt : return 0xb8; - case keymap::lshift: return 0x2a; - case keymap::rshift: return 0x36; - case keymap::lsuper: return 0xdb; - case keymap::rsuper: return 0xdc; - case keymap::menu: return 0xdd; - } - - return 0x00; -} diff --git a/src/ui/input/dinput.h b/src/ui/input/dinput.h deleted file mode 100644 index 8acf8cc7..00000000 --- a/src/ui/input/dinput.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef DINPUT_H -#define DINPUT_H - -#define DIRECTINPUT_VERSION 0x0800 -#define DIRECTINPUT_JOYMAX 16 -#include - -class InputDI : public Input { -private: -uint8 keystate[65536]; - -public: -HWND owner; -LPDIRECTINPUT8 di; -LPDIRECTINPUTDEVICE8 di_key, di_joy[DIRECTINPUT_JOYMAX]; -uint32 di_joy_count; - - void clear_input(); - void poll(); - void init(); - void term(); - bool key_down(uint16 key); - -// - uint16 translate(uint16 key); - bool enum_joypads(const DIDEVICEINSTANCE *instance); - - InputDI(HWND hwnd) { - owner = hwnd; - di = 0; - di_key = 0; - for(int i = 0; i < DIRECTINPUT_JOYMAX; i++)di_joy[i] = 0; - } - - ~InputDI() { term(); } -}; - -#endif diff --git a/src/ui/input/input.cpp b/src/ui/input/input.cpp deleted file mode 100644 index 018d9c79..00000000 --- a/src/ui/input/input.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "input.h" diff --git a/src/ui/input/input.h b/src/ui/input/input.h deleted file mode 100644 index 6bc9801a..00000000 --- a/src/ui/input/input.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef INPUT_H -#define INPUT_H - -class Input { public: - virtual bool key_down(uint16 key) { return false; } - virtual bool key_up (uint16 key) { return !key_down(key); } - - virtual void clear_input() {} - virtual void poll() {} - virtual void init() {} - virtual void term() {} -} *uiInput; - -#endif diff --git a/src/ui/input/xinput.cpp b/src/ui/input/xinput.cpp deleted file mode 100644 index b420d705..00000000 --- a/src/ui/input/xinput.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "xinput.h" - -bool InputX::key_down(uint16 key) { -#define map(i) (keymap[i >> 3] & (1 << (i & 7))) - switch(key) { - case keymap::esc: return map(0x09); - - case keymap::f1: return map(0x43); - case keymap::f2: return map(0x44); - case keymap::f3: return map(0x45); - case keymap::f4: return map(0x46); - case keymap::f5: return map(0x47); - case keymap::f6: return map(0x48); - case keymap::f7: return map(0x49); - case keymap::f8: return map(0x4a); - case keymap::f9: return map(0x4b); - case keymap::f10: return map(0x4c); - case keymap::f11: return map(0x5f); - case keymap::f12: return map(0x60); - - case keymap::print_screen: return map(0x6f); - case keymap::scroll_lock: return map(0x4e); - case keymap::pause: return map(0x6e); - - case keymap::grave: return map(0x31); - - case keymap::num_1: return map(0x0a); - case keymap::num_2: return map(0x0b); - case keymap::num_3: return map(0x0c); - case keymap::num_4: return map(0x0d); - case keymap::num_5: return map(0x0e); - case keymap::num_6: return map(0x0f); - case keymap::num_7: return map(0x10); - case keymap::num_8: return map(0x11); - case keymap::num_9: return map(0x12); - case keymap::num_0: return map(0x13); - - case keymap::minus: return map(0x14); - case keymap::equal: return map(0x15); - case keymap::backspace: return map(0x16); - - case keymap::ins: return map(0x6a); - case keymap::del: return map(0x6b); - case keymap::home: return map(0x61); - case keymap::end: return map(0x67); - case keymap::page_up: return map(0x63); - case keymap::page_down: return map(0x69); - - case keymap::a: return map(0x26); - case keymap::b: return map(0x38); - case keymap::c: return map(0x36); - case keymap::d: return map(0x28); - case keymap::e: return map(0x1a); - case keymap::f: return map(0x29); - case keymap::g: return map(0x2a); - case keymap::h: return map(0x2b); - case keymap::i: return map(0x1f); - case keymap::j: return map(0x2c); - case keymap::k: return map(0x2d); - case keymap::l: return map(0x2e); - case keymap::m: return map(0x3a); - case keymap::n: return map(0x39); - case keymap::o: return map(0x20); - case keymap::p: return map(0x21); - case keymap::q: return map(0x18); - case keymap::r: return map(0x1b); - case keymap::s: return map(0x27); - case keymap::t: return map(0x1c); - case keymap::u: return map(0x1e); - case keymap::v: return map(0x37); - case keymap::w: return map(0x19); - case keymap::x: return map(0x35); - case keymap::y: return map(0x1d); - case keymap::z: return map(0x34); - - case keymap::lbracket: return map(0x22); - case keymap::rbracket: return map(0x23); - case keymap::backslash: return map(0x33); - case keymap::semicolon: return map(0x2f); - case keymap::apostrophe: return map(0x30); - case keymap::comma: return map(0x3b); - case keymap::period: return map(0x3c); - case keymap::slash: return map(0x3d); - - case keymap::kp_1: return map(0x57); - case keymap::kp_2: return map(0x58); - case keymap::kp_3: return map(0x59); - case keymap::kp_4: return map(0x53); - case keymap::kp_5: return map(0x54); - case keymap::kp_6: return map(0x55); - case keymap::kp_7: return map(0x4f); - case keymap::kp_8: return map(0x50); - case keymap::kp_9: return map(0x51); - - case keymap::kp_plus: return map(0x56); - case keymap::kp_minus: return map(0x52); - case keymap::kp_mul: return map(0x3f); - case keymap::kp_div: return map(0x70); - case keymap::kp_enter: return map(0x6c); - - case keymap::num_lock: return map(0x4d); - case keymap::caps_lock: return map(0x42); - - case keymap::up: return map(0x62); - case keymap::down: return map(0x68); - case keymap::left: return map(0x64); - case keymap::right: return map(0x66); - - case keymap::tab: return map(0x17); - case keymap::enter: return map(0x24); - case keymap::space: return map(0x41); - - case keymap::lctrl: return map(0x25); - case keymap::rctrl: return map(0x6d); - case keymap::lalt: return map(0x40); - case keymap::ralt: return map(0x71); - case keymap::lshift: return map(0x32); - case keymap::rshift: return map(0x3e); - case keymap::lsuper: return map(0x73); - case keymap::rsuper: return map(0x74); - case keymap::menu: return map(0x75); - } -#undef map - - return false; -} - -void InputX::clear_input() { - memset(keymap, 0, sizeof keymap); -} - -void InputX::poll() { - XQueryKeymap(display, keymap); -} - -void InputX::init() { - Input::init(); - display = XOpenDisplay(0); -} - -void InputX::term() { - Input::term(); -} diff --git a/src/ui/input/xinput.h b/src/ui/input/xinput.h deleted file mode 100644 index 772a12ba..00000000 --- a/src/ui/input/xinput.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef XINPUT_H -#define XINPUT_H - -#include -#include -#include -#include -#include -#include -#include -#include - -class InputX : public Input { public: - bool key_down(uint16 key); - - void clear_input(); - void poll(); - void init(); - void term(); - -private: -Display *display; -char keymap[32]; -}; - -#endif diff --git a/src/ui/lui/loader/ui_bsxloader.cpp b/src/ui/lui/loader/ui_bsxloader.cpp deleted file mode 100644 index a7f1fe68..00000000 --- a/src/ui/lui/loader/ui_bsxloader.cpp +++ /dev/null @@ -1,81 +0,0 @@ -bool BSXLoaderWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - if(id == ui::Message::Close) { - hide(); - return false; - } - - if(id == ui::Message::Clicked) { - if(control == &bbase) { - char fn[PATH_MAX]; - if(event::load_rom(fn) == true) tbase.set_text(fn); - } - - if(control == &bslot) { - char fn[PATH_MAX]; - if(event::load_rom(fn) == true) tslot.set_text(fn); - } - - if(control == &cbase) tbase.set_text(""); - if(control == &cslot) tslot.set_text(""); - - if(control == &load) { - char base[PATH_MAX], slot[PATH_MAX]; - tbase.get_text(base, PATH_MAX); - tslot.get_text(slot, PATH_MAX); - - if(mode == ModeBSX) { - 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(); - } - - if(control == &cancel) { - tbase.set_text(""); - tslot.set_text(""); - hide(); - } - } - - return true; -} - -void BSXLoaderWindow::setup() { - create(ui::Window::Center, 640, 200, "Load BS-X Cartridge"); - -uint bh = ui::Button::ideal_height; -uint eh = ui::Editbox::ideal_height; -uint lh = ui::Label::ideal_height; -uint mh = max(bh, eh); - -uint y = 5; - lbase.create(*this, 0, 5, y, 630, lh, "Base cartridge:"); - y += lh; - tbase.create(*this, 0, 5, y, 420, mh); - bbase.create(*this, 0, 430, y, 100, mh, "Browse ..."); - cbase.create(*this, 0, 535, y, 100, mh, "Clear"); - y += mh + 5; - - lslot.create(*this, 0, 5, y, 630, lh, "Slot cartridge:"); - y += lh; - tslot.create(*this, 0, 5, y, 420, mh); - bslot.create(*this, 0, 430, y, 100, mh, "Browse ..."); - cslot.create(*this, 0, 535, y, 100, mh, "Clear"); - y += mh + lh; - - load.create(*this, 0, 5, y, 312, mh, "Load"); - cancel.create(*this, 0, 323, y, 312, mh, "Cancel"); - y += mh + 5; - - resize(640, y); -} - -BSXLoaderWindow::BSXLoaderWindow() { - mode = ModeBSX; -} diff --git a/src/ui/lui/loader/ui_bsxloader.h b/src/ui/lui/loader/ui_bsxloader.h deleted file mode 100644 index 92c39207..00000000 --- a/src/ui/lui/loader/ui_bsxloader.h +++ /dev/null @@ -1,24 +0,0 @@ -class BSXLoaderWindow : public ui::Window { -public: - enum Mode { - ModeBSX, //BS-X cartridge - ModeBSC, //BS-X slotted cartridge - }; - - Mode mode; - - ui::Label lbase; - ui::Editbox tbase; - ui::Button bbase, cbase; - - ui::Label lslot; - ui::Editbox tslot; - ui::Button bslot, cslot; - - ui::Button load, cancel; - - bool message(uint id, uintptr_t param = 0); - void setup(); - - BSXLoaderWindow(); -} window_bsxloader; diff --git a/src/ui/lui/loader/ui_stloader.cpp b/src/ui/lui/loader/ui_stloader.cpp deleted file mode 100644 index 7a92c79c..00000000 --- a/src/ui/lui/loader/ui_stloader.cpp +++ /dev/null @@ -1,89 +0,0 @@ -bool STLoaderWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - if(id == ui::Message::Close) { - hide(); - return false; - } - - if(id == ui::Message::Clicked) { - if(control == &bbase) { - char fn[PATH_MAX]; - if(event::load_rom(fn) == true) tbase.set_text(fn); - } - - if(control == &bslotA) { - char fn[PATH_MAX]; - if(event::load_rom(fn) == true) tslotA.set_text(fn); - } - - if(control == &bslotB) { - char fn[PATH_MAX]; - if(event::load_rom(fn) == true) tslotB.set_text(fn); - } - - if(control == &cbase) tbase.set_text(""); - if(control == &cslotA) tslotA.set_text(""); - if(control == &cslotB) tslotB.set_text(""); - - if(control == &load) { - 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); - - config::path.st = base; - event::load_cart_st(base, slotA, slotB); - - tbase.set_text(""); - tslotA.set_text(""); - tslotB.set_text(""); - hide(); - } - - if(control == &cancel) { - tbase.set_text(""); - tslotA.set_text(""); - tslotB.set_text(""); - hide(); - } - } - - return true; -} - -void STLoaderWindow::setup() { - create(ui::Window::Center, 640, 200, "Load Sufami Turbo Cartridge"); - -uint bh = ui::Button::ideal_height; -uint eh = ui::Editbox::ideal_height; -uint lh = ui::Label::ideal_height; -uint mh = max(bh, eh); - -uint y = 5; - lbase.create(*this, 0, 5, y, 630, lh, "Base cartridge:"); - y += lh; - tbase.create(*this, 0, 5, y, 420, mh); - bbase.create(*this, 0, 430, y, 100, mh, "Browse ..."); - cbase.create(*this, 0, 535, y, 100, mh, "Clear"); - y += mh + 5; - - lslotA.create(*this, 0, 5, y, 630, lh, "Slot A cartridge:"); - y += lh; - tslotA.create(*this, 0, 5, y, 420, mh); - bslotA.create(*this, 0, 430, y, 100, mh, "Browse ..."); - cslotA.create(*this, 0, 535, y, 100, mh, "Clear"); - y += mh + 5; - - lslotB.create(*this, 0, 5, y, 630, lh, "Slot B cartridge:"); - y += lh; - tslotB.create(*this, 0, 5, y, 420, mh); - bslotB.create(*this, 0, 430, y, 100, mh, "Browse ..."); - cslotB.create(*this, 0, 535, y, 100, mh, "Clear"); - y += mh + lh; - - load.create(*this, 0, 5, y, 312, mh, "Load"); - cancel.create(*this, 0, 323, y, 312, mh, "Cancel"); - y += mh + 5; - - resize(640, y); -} diff --git a/src/ui/lui/loader/ui_stloader.h b/src/ui/lui/loader/ui_stloader.h deleted file mode 100644 index d9648781..00000000 --- a/src/ui/lui/loader/ui_stloader.h +++ /dev/null @@ -1,19 +0,0 @@ -class STLoaderWindow : public ui::Window { -public: - ui::Label lbase; - ui::Editbox tbase; - ui::Button bbase, cbase; - - ui::Label lslotA; - ui::Editbox tslotA; - ui::Button bslotA, cslotA; - - ui::Label lslotB; - ui::Editbox tslotB; - ui::Button bslotB, cslotB; - - ui::Button load, cancel; - - bool message(uint id, uintptr_t param = 0); - void setup(); -} window_stloader; diff --git a/src/ui/lui/settings/ui_advanced.cpp b/src/ui/lui/settings/ui_advanced.cpp deleted file mode 100644 index f971111f..00000000 --- a/src/ui/lui/settings/ui_advanced.cpp +++ /dev/null @@ -1,83 +0,0 @@ -bool AdvancedWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - if(id == ui::Message::Changed && control == &list) { - int pos = list.get_selection(); - set_val.enable(pos >= 0); - set_def.enable(pos >= 0); - if(pos >= 0 && pos < config::config().list_count) { - desc.set_text(string() << "(default = " << config::config().list[pos]->def << ")\n" << config::config().list[pos]->desc); - string val; - config::config().list[pos]->get(val); - edit_val.set_text(strptr(val)); - } - } else if(id == ui::Message::Clicked && control == &set_val) { - char t[4096]; - edit_val.get_text(t, sizeof(t)); - update(list.get_selection(), t); - } else if(id == ui::Message::Clicked && control == &set_def) { - update(list.get_selection(), 0); - } - - return true; -} - -void AdvancedWindow::read_config(uint pos, string &data) { - strcpy(data, "?|?|?"); - if(pos >= config::config().list_count)return; -string name, val; - name = config::config().list[pos]->name; - config::config().list[pos]->get(val); - if(val != config::config().list[pos]->def) { strcat(name, " (*)"); } - sprintf(data, "%s|%s|%s", - strptr(name), - config::config().list[pos]->type == Setting::String ? "String" : "Integer", - strptr(val) - ); -} - -void AdvancedWindow::update(uint pos, const char *data) { - if(pos >= config::config().list_count)return; - config::config().list[pos]->set(data ? data : config::config().list[pos]->def); -string val; - config::config().list[pos]->get(val); - edit_val.set_text(strptr(val)); - read_config(pos, val); - list.set_item(pos, strptr(val)); - list.autosize_columns(); -} - -void AdvancedWindow::setup() { - create(0, 475, 355); - -int x = 0, y = 0; -int bh = ui::Button::ideal_height; -int eh = ui::Editbox::ideal_height; - bh = max(bh, eh); //set both editbox and button to same size, as they are on the same line -int th = 80; -int lh = 355 - th - bh - 10; - list.create(*this, ui::Listbox::Header | ui::Listbox::VerticalScrollAlways, x, y, 475, lh, "Name|Type|Value"); - y += lh + 5; - - desc.create(*this, ui::Editbox::Multiline | ui::Editbox::Readonly, x, y, 475, th, - "\n" - "Warning: modifification of certain variables will not take effect until\n" - "bsnes is restarted, and corresponding UI elements will not be updated\n" - "to reflect changes here. (*) = modified" - ); - y += th + 5; - - edit_val.create(*this, 0, x, y, 265, bh, ""); - set_val.create(*this, 0, x + 270, y, 100, bh, "Set"); - set_def.create(*this, 0, x + 375, y, 100, bh, "Default"); - - for(int i = 0; i < config::config().list_count; i++) { - string val; - read_config(i, val); - list.add_item(strptr(val)); - } - - list.autosize_columns(); - - set_val.disable(); - set_def.disable(); -} diff --git a/src/ui/lui/settings/ui_advanced.h b/src/ui/lui/settings/ui_advanced.h deleted file mode 100644 index 5c9a97bc..00000000 --- a/src/ui/lui/settings/ui_advanced.h +++ /dev/null @@ -1,11 +0,0 @@ -class AdvancedWindow : public ui::Window { public: -ui::Listbox list; -ui::Editbox desc; -ui::Editbox edit_val; -ui::Button set_val; -ui::Button set_def; - bool message(uint id, uintptr_t param); - void read_config(uint pos, string &data); - void update(uint pos, const char *data); - void setup(); -} window_advanced; diff --git a/src/ui/lui/settings/ui_cheateditor.cpp b/src/ui/lui/settings/ui_cheateditor.cpp deleted file mode 100644 index cc68ad8a..00000000 --- a/src/ui/lui/settings/ui_cheateditor.cpp +++ /dev/null @@ -1,82 +0,0 @@ -void CheatEditorWindow::refresh() { - list.reset(); - - for(uint i = 0; i < cheat.count(); i++) { - bool enabled; - uint32 addr; - uint8 data; - char s_code[256], s_desc[256], s_result[1024]; - cheat.get(i, enabled, addr, data, s_code, s_desc); - sprintf(s_result, "%s|%s|%s", enabled ? "Enabled" : "Disabled", s_code, s_desc); - list.add_item(s_result); - } - - list.autosize_columns(); - -//enable controls only if cartridge is loaded -bool loaded = cartridge.loaded(); - add_code.enable(loaded); - toggle_code.enable(loaded); - delete_code.enable(loaded); -} - -bool CheatEditorWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - - if(id == ui::Message::Clicked && control == &add_code) { - char s_code[256], s_desc[256]; - code.get_text(s_code, sizeof s_code); - desc.get_text(s_desc, sizeof s_desc); - cheat.add(false, s_code, s_desc); //param 0 = new codes disabled by default - refresh(); - return true; - } - - if((id == ui::Message::Clicked && control == &toggle_code) || - (id == ui::Message::DoubleClicked && control == &list)) { - int index = list.get_selection(); - if(index >= 0 && index < cheat.count()) { - cheat.enabled(index) ? cheat.disable(index) : cheat.enable(index); - bool enabled; - uint32 addr; - uint8 data; - char s_code[256], s_desc[256], s_result[1024]; - cheat.get(index, enabled, addr, data, s_code, s_desc); - sprintf(s_result, "%s|%s|%s", enabled ? "Enabled" : "Disabled", s_code, s_desc); - list.set_item(index, s_result); - } - return true; - } - - if(id == ui::Message::Clicked && control == &delete_code) { - int index = list.get_selection(); - if(index >= 0 && index < cheat.count()) { - cheat.remove(index); - refresh(); - } - return true; - } - - return true; -} - -void CheatEditorWindow::setup() { - create(0, 475, 355); - -int x = 0, y = 0; -int bh = ui::Button::ideal_height; -int eh = ui::Editbox::ideal_height; -int lh = 355 - bh - eh - 10; - list.create(*this, ui::Listbox::Header | ui::Listbox::VerticalScrollAlways, x, y, 475, lh, "Status|Code|Description"); - y += lh + 5; - - add_code.create (*this, 0, x, y, 155, bh, "Add Code"); - toggle_code.create(*this, 0, x + 160, y, 155, bh, "Toggle Status"); - delete_code.create(*this, 0, x + 320, y, 155, bh, "Delete Code"); - y += bh + 5; - - code.create(*this, 0, x, y, 155, eh, ""); - desc.create(*this, 0, x + 160, y, 315, eh, ""); - - refresh(); -} diff --git a/src/ui/lui/settings/ui_cheateditor.h b/src/ui/lui/settings/ui_cheateditor.h deleted file mode 100644 index b6d2f26e..00000000 --- a/src/ui/lui/settings/ui_cheateditor.h +++ /dev/null @@ -1,12 +0,0 @@ -class CheatEditorWindow : public ui::Window { public: -ui::Listbox list; -ui::Button add_code; -ui::Button toggle_code; -ui::Button delete_code; -ui::Editbox code; -ui::Editbox desc; - bool message(uint id, uintptr_t param); - void setup(); - - void refresh(); -} window_cheat_editor; diff --git a/src/ui/lui/settings/ui_inputconfig.cpp b/src/ui/lui/settings/ui_inputconfig.cpp deleted file mode 100644 index 98739590..00000000 --- a/src/ui/lui/settings/ui_inputconfig.cpp +++ /dev/null @@ -1,211 +0,0 @@ -const char InputConfigWindow::list_index[][64] = { - "Joypad 1 Up", - "Joypad 1 Down", - "Joypad 1 Left", - "Joypad 1 Right", - "Joypad 1 A", - "Joypad 1 B", - "Joypad 1 X", - "Joypad 1 Y", - "Joypad 1 L", - "Joypad 1 R", - "Joypad 1 Select", - "Joypad 1 Start", - - "Joypad 2 Up", - "Joypad 2 Down", - "Joypad 2 Left", - "Joypad 2 Right", - "Joypad 2 A", - "Joypad 2 B", - "Joypad 2 X", - "Joypad 2 Y", - "Joypad 2 L", - "Joypad 2 R", - "Joypad 2 Select", - "Joypad 2 Start", -}; - -uint InputConfigWindow::get_value(uint index) { - switch(index) { - case 0: return keymap::find(config::input.joypad1.up); - case 1: return keymap::find(config::input.joypad1.down); - case 2: return keymap::find(config::input.joypad1.left); - case 3: return keymap::find(config::input.joypad1.right); - case 4: return keymap::find(config::input.joypad1.a); - case 5: return keymap::find(config::input.joypad1.b); - case 6: return keymap::find(config::input.joypad1.x); - case 7: return keymap::find(config::input.joypad1.y); - case 8: return keymap::find(config::input.joypad1.l); - case 9: return keymap::find(config::input.joypad1.r); - case 10: return keymap::find(config::input.joypad1.select); - case 11: return keymap::find(config::input.joypad1.start); - - case 12: return keymap::find(config::input.joypad2.up); - case 13: return keymap::find(config::input.joypad2.down); - case 14: return keymap::find(config::input.joypad2.left); - case 15: return keymap::find(config::input.joypad2.right); - case 16: return keymap::find(config::input.joypad2.a); - case 17: return keymap::find(config::input.joypad2.b); - case 18: return keymap::find(config::input.joypad2.x); - case 19: return keymap::find(config::input.joypad2.y); - case 20: return keymap::find(config::input.joypad2.l); - case 21: return keymap::find(config::input.joypad2.r); - case 22: return keymap::find(config::input.joypad2.select); - case 23: return keymap::find(config::input.joypad2.start); - } - - return keymap::none; -} - -void InputConfigWindow::set_value(uint index, uint16 value) { - switch(index) { - case 0: config::input.joypad1.up = keymap::find(value); break; - case 1: config::input.joypad1.down = keymap::find(value); break; - case 2: config::input.joypad1.left = keymap::find(value); break; - case 3: config::input.joypad1.right = keymap::find(value); break; - case 4: config::input.joypad1.a = keymap::find(value); break; - case 5: config::input.joypad1.b = keymap::find(value); break; - case 6: config::input.joypad1.x = keymap::find(value); break; - case 7: config::input.joypad1.y = keymap::find(value); break; - case 8: config::input.joypad1.l = keymap::find(value); break; - case 9: config::input.joypad1.r = keymap::find(value); break; - case 10: config::input.joypad1.select = keymap::find(value); break; - case 11: config::input.joypad1.start = keymap::find(value); break; - - case 12: config::input.joypad2.up = keymap::find(value); break; - case 13: config::input.joypad2.down = keymap::find(value); break; - case 14: config::input.joypad2.left = keymap::find(value); break; - case 15: config::input.joypad2.right = keymap::find(value); break; - case 16: config::input.joypad2.a = keymap::find(value); break; - case 17: config::input.joypad2.b = keymap::find(value); break; - case 18: config::input.joypad2.x = keymap::find(value); break; - case 19: config::input.joypad2.y = keymap::find(value); break; - case 20: config::input.joypad2.l = keymap::find(value); break; - case 21: config::input.joypad2.r = keymap::find(value); break; - case 22: config::input.joypad2.select = keymap::find(value); break; - case 23: config::input.joypad2.start = keymap::find(value); break; - } - - input_manager.bind(); -} - -void InputConfigWindow::refresh_list() { - for(uint i = 0; i < 24; i++) { - list.set_item(i, string() << list_index[i] << "|" << keymap::find(get_value(i))); - } - list.autosize_columns(); -} - -bool InputConfigWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - if(id == ui::Message::Changed && control == &list) { - int pos = list.get_selection(); - setkey.enable(pos >= 0); - clrkey.enable(pos >= 0); - return true; - } - - if((id == ui::Message::DoubleClicked && control == &list) || - (id == ui::Message::Clicked && control == &setkey)) { - int pos = list.get_selection(); - if(pos < 0) { return true; } - window_input_capture.index = pos; - window_input_capture.label.set_text(string() << "Please press a key to assign to " << list_index[pos] << " ..."); - window_input_capture.show(); - return true; - } - - if(id == ui::Message::Clicked && control == &clrkey) { - int pos = list.get_selection(); - if(pos < 0) { return true; } - set_value(pos, keymap::none); - refresh_list(); - return true; - } - - return true; -} - -void InputConfigWindow::setup() { - create(0, 475, 355); - -int x = 0, y = 0; -int lh = ui::Label::ideal_height; -int ch = ui::Combobox::ideal_height; -int bh = ui::Button::ideal_height; -int lbh = 355 - lh - ch - bh - 10; - lportA.create(*this, 0, x, y, 235, lh, "Controller Port A:"); - lportB.create(*this, 0, x + 240, y, 235, lh, "Controller Port B:"); - y += lh; - - portA.create (*this, 0, x, y, 235, ch); - portA.add_item("None"); - portA.add_item("Joypad 1"); - portA.add_item("Joypad 2"); - portA.set_selection(1); - portA.disable(); - - portB.create (*this, 0, x + 240, y, 235, ch); - portB.add_item("None"); - portB.add_item("Joypad 1"); - portB.add_item("Joypad 2"); - portB.set_selection(2); - portB.disable(); - y += ch + 5; - - list.create(*this, ui::Listbox::Header | ui::Listbox::VerticalScrollAlways, x, y, 475, lbh, "Name|Value"); - for(uint i = 0; i < 24; i++) { list.add_item("???|???"); } - y += lbh + 5; - - setkey.create(*this, 0, x, y, 235, bh, "Assign Key"); - clrkey.create(*this, 0, x + 240, y, 235, bh, "Unassign Key"); - - refresh_list(); - window_input_capture.setup(); - - setkey.disable(); - clrkey.disable(); -} - -// - -bool InputCaptureWindow::message(uint id, uintptr_t param) { - if(id == ui::Message::Close) { - hide(); - return false; - } - - return true; -} - -void InputCaptureWindow::show() { - uiInput->clear_input(); - -//enter and spacebar can be used to activate key capture, -//set lock on these keys if they are held down to prevent -//them from being instantly assigned to selected entry ... - uiInput->poll(); - key_lock = (uiInput->key_down(keymap::enter) || uiInput->key_down(keymap::space)); - Window::show(); - Window::focus(); - - while(_term_ == false && visible() == true) { - run(); - uint16 key = input_manager.scan(); - if(key == keymap::none) { key_lock = false; continue; } - if(key_lock && (key == keymap::enter || key == keymap::space)) { continue; } - hide(); - window_input_config.set_value(index, key); - window_input_config.refresh_list(); - break; - } - - uiInput->clear_input(); -} - -void InputCaptureWindow::setup() { -int lh = ui::Label::ideal_height; - create(ui::Window::Center, 350, lh * 3, "bsnes Key Capture"); - label.create(*this, 0, 5, lh, 340, lh); -} diff --git a/src/ui/lui/settings/ui_inputconfig.h b/src/ui/lui/settings/ui_inputconfig.h deleted file mode 100644 index 5d562228..00000000 --- a/src/ui/lui/settings/ui_inputconfig.h +++ /dev/null @@ -1,27 +0,0 @@ -class InputCaptureWindow : public ui::Window { public: -ui::Label label; -uint index; -bool key_lock; - bool message(uint id, uintptr_t param = 0); - void show(); - void setup(); - InputCaptureWindow() : index(0) {} -} window_input_capture; - -class InputConfigWindow : public ui::Window { public: -ui::Label lportA; -ui::Label lportB; -ui::Combobox portA; -ui::Combobox portB; -ui::Listbox list; -ui::Button setkey; -ui::Button clrkey; - -static const char list_index[][64]; - - bool message(uint id, uintptr_t param = 0); - uint get_value(uint index); - void set_value(uint index, uint16 value); - void refresh_list(); - void setup(); -} window_input_config; diff --git a/src/ui/lui/settings/ui_rastersettings.cpp b/src/ui/lui/settings/ui_rastersettings.cpp deleted file mode 100644 index 4c99f9b5..00000000 --- a/src/ui/lui/settings/ui_rastersettings.cpp +++ /dev/null @@ -1,119 +0,0 @@ -bool RasterSettingsWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - if(id == ui::Message::Changed) { - if(control == &contrast) { - if(config::snes.contrast != contrast.get_position() - 96) { - config::snes.contrast = contrast.get_position() - 96; - lcontrast.set_text(string() << "Contrast: " << config::snes.contrast); - snes.update_color_lookup_table(); - } - } else if(control == &brightness) { - if(config::snes.brightness != brightness.get_position() - 96) { - config::snes.brightness = brightness.get_position() - 96; - lbrightness.set_text(string() << "Brightness: " << config::snes.brightness); - snes.update_color_lookup_table(); - } - } else if(control == &gamma) { - if(config::snes.gamma != gamma.get_position() + 10) { - config::snes.gamma = gamma.get_position() + 10; - lgamma.set_text(string() << "Gamma: " << config::snes.gamma); //TODO: print gamma as "%0.2f" / 100.0 - snes.update_color_lookup_table(); - } - } - return true; - } - - if(id == ui::Message::Clicked) { - if(control == &gamma_ramp) { - if(config::snes.gamma_ramp != gamma_ramp.checked()) { - config::snes.gamma_ramp = gamma_ramp.checked(); - snes.update_color_lookup_table(); - } - } else if(control == &sepia) { - if(config::snes.sepia != sepia.checked()) { - config::snes.sepia = sepia.checked(); - snes.update_color_lookup_table(); - } - } else if(control == &grayscale) { - if(config::snes.grayscale != grayscale.checked()) { - config::snes.grayscale = grayscale.checked(); - snes.update_color_lookup_table(); - } - } else if(control == &invert) { - if(config::snes.invert != invert.checked()) { - config::snes.invert = invert.checked(); - snes.update_color_lookup_table(); - } - } else if(control == &preset_optimal) { - config::snes.contrast = 0; - config::snes.brightness = 0; - config::snes.gamma = 80; - config::snes.gamma_ramp = true; - config::snes.sepia = false; - config::snes.grayscale = false; - config::snes.invert = false; - sync_ui(); - } else if(control == &preset_standard) { - config::snes.contrast = 0; - config::snes.brightness = 0; - config::snes.gamma = 100; - config::snes.gamma_ramp = false; - config::snes.sepia = false; - config::snes.grayscale = false; - config::snes.invert = false; - sync_ui(); - } - return true; - } - - return true; -} - -//update all UI controls to match config file values ... -void RasterSettingsWindow::sync_ui() { - contrast.set_position(config::snes.contrast + 96); - lcontrast.set_text(string() << "Contrast: " << config::snes.contrast); - brightness.set_position(config::snes.brightness + 96); - lbrightness.set_text(string() << "Brightness: " << config::snes.brightness); - gamma.set_position(config::snes.gamma - 10); - lgamma.set_text(string() << "Gamma: " << config::snes.gamma); //TODO: print gamma as "%0.2f" / 100.0 - gamma_ramp.check(config::snes.gamma_ramp); - sepia.check(config::snes.sepia); - grayscale.check(config::snes.grayscale); - invert.check(config::snes.invert); - snes.update_color_lookup_table(); -} - -void RasterSettingsWindow::setup() { - create(0, 475, 355); - -int x = 0, y = 0; -int sh = ui::Slider::ideal_height; -int kh = ui::Checkbox::ideal_height; -int bh = ui::Button::ideal_height; - lcontrast.create(*this, 0, x, y, 100, sh); - contrast.create (*this, 0, x + 100, y, 375, sh, 192); - y += sh; - - lbrightness.create(*this, 0, x, y, 100, sh); - brightness.create (*this, 0, x + 100, y, 375, sh, 192); - y += sh; - - lgamma.create(*this, 0, x, y, 100, sh); - gamma.create (*this, 0, x + 100, y, 375, sh, 191); - y += sh; - - gamma_ramp.create(*this, 0, x, y, 235, kh, "Gamma ramp"); - sepia.create(*this, 0, x + 240, y, 235, kh, "Sepia"); - y += kh; - - grayscale.create(*this, 0, x, y, 235, kh, "Grayscale"); - invert.create(*this, 0, x + 240, y, 235, kh, "Invert colors"); - y += kh + 5; - - preset_optimal.create (*this, 0, x, y, 235, bh, "Optimal Preset"); - preset_standard.create(*this, 0, x + 240, y, 235, bh, "Standard Preset"); - y += bh; - - sync_ui(); -} diff --git a/src/ui/lui/settings/ui_rastersettings.h b/src/ui/lui/settings/ui_rastersettings.h deleted file mode 100644 index 46e4ba4d..00000000 --- a/src/ui/lui/settings/ui_rastersettings.h +++ /dev/null @@ -1,20 +0,0 @@ -class RasterSettingsWindow : public ui::Window { public: -ui::Label lcontrast; -ui::Label lbrightness; -ui::Label lgamma; -ui::Slider contrast; -ui::Slider brightness; -ui::Slider gamma; - -ui::Checkbox gamma_ramp; -ui::Checkbox sepia; -ui::Checkbox grayscale; -ui::Checkbox invert; - -ui::Button preset_optimal; -ui::Button preset_standard; - - bool message(uint id, uintptr_t param); - void setup(); - void sync_ui(); -} window_raster_settings; diff --git a/src/ui/lui/settings/ui_settings.cpp b/src/ui/lui/settings/ui_settings.cpp deleted file mode 100644 index 8bda1988..00000000 --- a/src/ui/lui/settings/ui_settings.cpp +++ /dev/null @@ -1,38 +0,0 @@ -void SettingsWindow::setup() { - create(ui::Window::Center, 640, 365, "bsnes Configuration Settings"); - panel_list.create(*this, 0, 5, 5, 150, 355); -//panel_list.add_item("Video Settings"); - panel_list.add_item("Raster Settings"); - panel_list.add_item("Input Configuration"); - panel_list.add_item("Cheat Code Editor"); - panel_list.add_item("Advanced"); - panel.create(*this, 0, 160, 5, 475, 355); - - panel_list.set_selection(0); -} - -void SettingsWindow::show() { - Window::show(); - panel_list.focus(); -} - -bool SettingsWindow::message(uint id, uintptr_t param) { - if(id == ui::Message::Close) { - hide(); - return false; - } - - if(id == ui::Message::Changed && (ui::Control*)param == &panel_list) { - switch(panel_list.get_selection()) { - //case 0: panel.attach(window_video_settings); break; - case 0: panel.attach(window_raster_settings); break; - case 1: panel.attach(window_input_config); break; - case 2: panel.attach(window_cheat_editor); break; - case 3: panel.attach(window_advanced); break; - } - panel_list.focus(); - return true; - } - - return true; -} diff --git a/src/ui/lui/settings/ui_settings.h b/src/ui/lui/settings/ui_settings.h deleted file mode 100644 index ff6b9eab..00000000 --- a/src/ui/lui/settings/ui_settings.h +++ /dev/null @@ -1,7 +0,0 @@ -class SettingsWindow : public ui::Window { public: -ui::Listbox panel_list; -ui::Panel panel; - bool message(uint id, uintptr_t param = 0); - void show(); - void setup(); -} window_settings; diff --git a/src/ui/lui/settings/ui_videosettings.cpp b/src/ui/lui/settings/ui_videosettings.cpp deleted file mode 100644 index 0fabc663..00000000 --- a/src/ui/lui/settings/ui_videosettings.cpp +++ /dev/null @@ -1,59 +0,0 @@ -bool VideoSettingsWindow::message(uint id, uintptr_t param) { - return true; -} - -void VideoSettingsWindow::setup() { - create(0, 475, 355); - -int x = 0, y = 0; -int lh = ui::Label::ideal_height; -int ch = ui::Combobox::ideal_height; -int kh = ui::Checkbox::ideal_height; -int eh = ui::Editbox::ideal_height; - label_select.create(*this, 0, x, y, 475, lh, "Select video mode to configure:"); - y += lh; - mode_select.create(*this, 0, x, y, 475, ch); - mode_select.add_item("Windowed mode"); - mode_select.add_item("Pseudo-fullscreen mode"); - mode_select.add_item("Fullscreen mode"); - y += ch + 5; - - label_region.create(*this, 0, x, y, 235, lh, "Region:"); - label_scalar.create(*this, 0, x + 240, y, 235, lh, "Scale:"); - y += lh; - region.create(*this, 0, x, y, 235, ch); - region.add_item("NTSC"); - region.add_item("PAL"); - scalar.create(*this, 0, x + 240, y, 235, ch); - scalar.add_item("100%"); - scalar.add_item("200%"); - scalar.add_item("300%"); - scalar.add_item("400%"); - scalar.add_item("500%"); - y += ch; - - label_hwfilter.create(*this, 0, x, y, 235, lh, "Hardware filter:"); - label_swfilter.create(*this, 0, x + 240, y, 235, lh, "Software filter:"); - y += lh; - hwfilter.create(*this, 0, x, y, 235, ch); - hwfilter.add_item("Point"); - hwfilter.add_item("Linear"); - swfilter.create(*this, 0, x + 240, y, 235, ch); - swfilter.add_item("None"); - swfilter.add_item("NTSC"); - swfilter.add_item("HQ2x"); - swfilter.add_item("Scale2x"); - y += ch + 5; - - aspect.create(*this, 0, x, y, 235, kh, "Correct aspect ratio"); - vsync.create(*this, 0, x + 240, y, 235, kh, "Sync to vertical retrace"); - y += kh + 5; - - label_fsmode.create(*this, 0, x, y, 475, lh, "Fullscreen mode (width x height x refresh rate):"); - y += lh; - - fs_width.create(*this, 0, x, y, 155, eh, ""); - fs_height.create(*this, 0, x + 160, y, 155, eh, ""); - fs_refresh.create(*this, 0, x + 320, y, 155, eh, ""); - y += eh + 5; -} diff --git a/src/ui/lui/settings/ui_videosettings.h b/src/ui/lui/settings/ui_videosettings.h deleted file mode 100644 index eb4fed9a..00000000 --- a/src/ui/lui/settings/ui_videosettings.h +++ /dev/null @@ -1,14 +0,0 @@ -class VideoSettingsWindow : public ui::Window { public: -ui::Label label_select; -ui::Combobox mode_select; - -ui::Label label_region, label_scalar, label_hwfilter, label_swfilter; -ui::Combobox region, scalar, hwfilter, swfilter; - -ui::Checkbox aspect, vsync; - -ui::Label label_fsmode; -ui::Editbox fs_width, fs_height, fs_refresh; - bool message(uint, uintptr_t); - void setup(); -} window_video_settings; diff --git a/src/ui/lui/ui.cpp b/src/ui/lui/ui.cpp deleted file mode 100644 index d9052325..00000000 --- a/src/ui/lui/ui.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "ui_main.cpp" -#include "ui_about.cpp" - -#include "loader/ui_bsxloader.cpp" -#include "loader/ui_stloader.cpp" - -#include "settings/ui_settings.cpp" -#include "settings/ui_videosettings.cpp" -#include "settings/ui_rastersettings.cpp" -#include "settings/ui_inputconfig.cpp" -#include "settings/ui_cheateditor.cpp" -#include "settings/ui_advanced.cpp" - -#if defined(PLATFORM_WIN) - #include "../video/d3d.h" - #include "../video/d3d.cpp" - #include "../video/ddraw.h" - #include "../video/ddraw.cpp" - #include "../video/gdi.cpp" - #include "../audio/dsound.h" - #include "../audio/dsound.cpp" - #include "../input/dinput.cpp" -#elif defined(PLATFORM_X) - #include "../video/xv.cpp" - #include "../video/gtk.cpp" - #include "../audio/ao.cpp" - #include "../input/xinput.cpp" -#endif - -void ui_init() { - window_main.setup(); - window_about.setup(); - - window_bsxloader.setup(); - window_stloader.setup(); - - window_video_settings.setup(); - window_raster_settings.setup(); - window_input_config.setup(); - window_cheat_editor.setup(); - window_advanced.setup(); - window_settings.setup(); - - event::update_video_settings(); //call first time to resize main window and update menubar - window_main.show(); - while(ui::events_pending()) { ui::run(); } - -#if defined(PLATFORM_WIN) - uiVideo = - config::system.video == "none" ? (Video*)new Video() : - config::system.video == "gdi" ? (Video*)new VideoGDI(window_main.view.handle()) : - config::system.video == "dd" ? (Video*)new VideoDD(window_main.view.handle()) : - (Video*)new VideoD3D(window_main.view.handle()); - uiAudio = - config::system.audio == "none" ? (Audio*)new Audio() : - (Audio*)new AudioDS(window_main.handle()); - uiInput = - config::system.input == "none" ? (Input*)new Input() : - (Input*)new InputDI(window_main.handle()); -#elif defined(PLATFORM_X) - uiVideo = - config::system.video == "none" ? (Video*)new Video() : - config::system.video == "gtk" ? (Video*)new VideoGTK(window_main.view.handle()) : - (Video*)new VideoXv((unsigned long)window_main.view.x_handle()); - uiAudio = - config::system.audio == "none" ? (Audio*)new Audio() : - (Audio*)new AudioAO(config::system.audio_flags); - uiInput = - config::system.input == "none" ? (Input*)new Input() : - (Input*)new InputX(); -#endif - - uiVideo->init(); - uiAudio->init(); - uiInput->init(); - - event::update_video_settings(); //call second time to update uiVideo->settings -} - -void ui_term() { - window_main.hide(); - - uiVideo->term(); - uiAudio->term(); - uiInput->term(); - - safe_delete(uiVideo); - safe_delete(uiAudio); - safe_delete(uiInput); -} diff --git a/src/ui/lui/ui_about.h b/src/ui/lui/ui_about.h deleted file mode 100644 index 11d2df03..00000000 --- a/src/ui/lui/ui_about.h +++ /dev/null @@ -1,6 +0,0 @@ -class AboutWindow : public ui::Window { public: -ui::Label about; -static const char about_text[4096]; - bool message(uint id, uintptr_t param = 0); - void setup(); -} window_about; diff --git a/src/ui/lui/ui_main.cpp b/src/ui/lui/ui_main.cpp deleted file mode 100644 index b0f2508b..00000000 --- a/src/ui/lui/ui_main.cpp +++ /dev/null @@ -1,304 +0,0 @@ -bool MainWindow::input_ready() { -//only allow input when main window is focused - return focused() == true; -} - -bool MainWindow::message(uint id, uintptr_t param) { -ui::Control *control = (ui::Control*)param; - if(id == ui::Message::Close) { - _term_ = true; - hide(); - return false; - } - - if(id == ui::Message::Block) { - if(uiAudio) { uiAudio->clear_audio(); } - return true; - } - - if(id == ui::Message::KeyDown) { - if(param == keymap::esc) { event::toggle_menu(); } - if(param == keymap::f11) { event::toggle_fullscreen(); } - return true; - } - - if(id == ui::Message::Clicked) { - if(control == &menu_file_load) { - event::load_rom(); - } - - if(control == &menu_file_load_bsx) { - window_bsxloader.mode = BSXLoaderWindow::ModeBSX; - window_bsxloader.set_text("Load BS-X Cartridge"); - window_bsxloader.tbase.set_text(config::path.bsx); - window_bsxloader.show(); - } - - if(control == &menu_file_load_bsc) { - window_bsxloader.mode = BSXLoaderWindow::ModeBSC; - window_bsxloader.set_text("Load BS-X Slotted Cartridge"); - window_bsxloader.tbase.set_text(""); - window_bsxloader.show(); - } - - if(control == &menu_file_load_st) { - window_stloader.tbase.set_text(config::path.st); - window_stloader.show(); - } - - if(control == &menu_file_unload) { - event::unload_rom(); - } - - if(control == &menu_file_reset) { - event::reset(); - } - - if(control == &menu_file_power) { - event::power(); - } - - if(control == &menu_file_exit) { - message(ui::Message::Close); - } - - if(locked == false) { - //set locked to true to update below menu item check statuses without triggering events - if(control == &menu_settings_videomode_1x) { event::update_multiplier(1); } - if(control == &menu_settings_videomode_2x) { event::update_multiplier(2); } - if(control == &menu_settings_videomode_3x) { event::update_multiplier(3); } - if(control == &menu_settings_videomode_4x) { event::update_multiplier(4); } - if(control == &menu_settings_videomode_5x) { event::update_multiplier(5); } - - if(control == &menu_settings_videomode_aspect_correction) { - event::update_aspect_correction(menu_settings_videomode_aspect_correction.checked()); - } - - if(control == &menu_settings_videomode_ntsc) { event::update_region(0); } - if(control == &menu_settings_videomode_pal) { event::update_region(1); } - - if(control == &menu_settings_videofilter_hwpoint) { event::update_hardware_filter(0); } - if(control == &menu_settings_videofilter_hwlinear) { event::update_hardware_filter(1); } - - if(control == &menu_settings_videofilter_swnone) { event::update_software_filter(0); } - if(control == &menu_settings_videofilter_swntsc) { event::update_software_filter(1); } - if(control == &menu_settings_videofilter_swhq2x) { event::update_software_filter(2); } - if(control == &menu_settings_videofilter_swscale2x) { event::update_software_filter(3); } - - if(control == &menu_settings_videoframeskip_0) { config::video.frameskip = 0; } - if(control == &menu_settings_videoframeskip_1) { config::video.frameskip = 1; } - if(control == &menu_settings_videoframeskip_2) { config::video.frameskip = 2; } - if(control == &menu_settings_videoframeskip_3) { config::video.frameskip = 3; } - if(control == &menu_settings_videoframeskip_4) { config::video.frameskip = 4; } - if(control == &menu_settings_videoframeskip_5) { config::video.frameskip = 5; } - if(control == &menu_settings_videoframeskip_6) { config::video.frameskip = 6; } - if(control == &menu_settings_videoframeskip_7) { config::video.frameskip = 7; } - if(control == &menu_settings_videoframeskip_8) { config::video.frameskip = 8; } - if(control == &menu_settings_videoframeskip_9) { config::video.frameskip = 9; } - - if(control == &menu_settings_mute) { - config::snes.mute = menu_settings_mute.checked(); - } - - if(control == &menu_settings_speedreg_enable) { - config::system.regulate_speed = menu_settings_speedreg_enable.checked(); - } - - if(control == &menu_settings_speedreg_slowest) { config::system.speed = 1; uiAudio->update_frequency(); } - if(control == &menu_settings_speedreg_slow) { config::system.speed = 2; uiAudio->update_frequency(); } - if(control == &menu_settings_speedreg_normal) { config::system.speed = 3; uiAudio->update_frequency(); } - if(control == &menu_settings_speedreg_fast) { config::system.speed = 4; uiAudio->update_frequency(); } - if(control == &menu_settings_speedreg_fastest) { config::system.speed = 5; uiAudio->update_frequency(); } - } - - if(control == &menu_settings_config) { window_settings.show(); } - - if(control == &menu_misc_logaudio) { - (menu_misc_logaudio.checked() == true) ? snes.log_audio_enable() : snes.log_audio_disable(); - } - - if(control == &menu_misc_showfps) { - config::misc.show_frame_counter = menu_misc_showfps.checked(); - if(config::misc.show_frame_counter == false) { - set_text(BSNES_TITLE); - } - } - - if(control == &menu_misc_about) { - window_about.focus(); - } - - return true; - } - - return true; -} - -void MainWindow::setup() { - snesinterface.input_ready = bind(&MainWindow::input_ready, this); - - locked = true; - -ui::ControlGroup group; - create(ui::Window::Center, 256, 224, BSNES_TITLE); - set_background_color(0, 0, 0); - - menu.create(*this); - menu_file.create(menu, "File"); - menu_file_load.create(menu_file, "Load Cartridge ..."); - menu_file_load_special.create(menu_file, "Load Special"); - menu_file_load_bsx.create(menu_file_load_special, "Load BS-X Cartridge ..."); - menu_file_load_bsc.create(menu_file_load_special, "Load BS-X Slotted Cartridge ..."); - menu_file_load_st.create(menu_file_load_special, "Load ST Cartridge ..."); - menu_file_load_special.finish(); - menu_file_unload.create(menu_file, "Unload Cartridge"); - menu_file_sep1.create(menu_file); - menu_file_reset.create(menu_file, "Reset System"); - menu_file_power.create(menu_file, "Power Cycle System"); - menu_file_sep2.create(menu_file); - menu_file_exit.create(menu_file, "Exit"); - menu_file.finish(); - - menu_settings.create(menu, "Settings"); - menu_settings_videomode.create(menu_settings, "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_1x.create(menu_settings_videomode, group, "Scale 1x"); - menu_settings_videomode_2x.create(menu_settings_videomode, group, "Scale 2x"); - menu_settings_videomode_3x.create(menu_settings_videomode, group, "Scale 3x"); - menu_settings_videomode_4x.create(menu_settings_videomode, group, "Scale 4x"); - menu_settings_videomode_5x.create(menu_settings_videomode, group, "Scale 5x"); - group.reset(); - menu_settings_videomode_sep1.create(menu_settings_videomode); - menu_settings_videomode_aspect_correction.create(menu_settings_videomode, "Correct Aspect Ratio"); - menu_settings_videomode_sep2.create(menu_settings_videomode); - group.add(menu_settings_videomode_ntsc); - group.add(menu_settings_videomode_pal); - menu_settings_videomode_ntsc.create(menu_settings_videomode, group, "NTSC"); - menu_settings_videomode_pal.create(menu_settings_videomode, group, "PAL"); - group.reset(); - menu_settings_videomode.finish(); - - menu_settings_videofilter.create(menu_settings, "Video Filter"); - group.add(menu_settings_videofilter_hwpoint); - group.add(menu_settings_videofilter_hwlinear); - menu_settings_videofilter_hwpoint.create(menu_settings_videofilter, group, "Point"); - menu_settings_videofilter_hwlinear.create(menu_settings_videofilter, group, "Linear"); - group.reset(); - menu_settings_videofilter_sep1.create(menu_settings_videofilter); - group.add(menu_settings_videofilter_swnone); - group.add(menu_settings_videofilter_swntsc); - group.add(menu_settings_videofilter_swhq2x); - group.add(menu_settings_videofilter_swscale2x); - menu_settings_videofilter_swnone.create(menu_settings_videofilter, group, "None"); - menu_settings_videofilter_swntsc.create(menu_settings_videofilter, group, "NTSC"); - menu_settings_videofilter_swhq2x.create(menu_settings_videofilter, group, "HQ2x"); - menu_settings_videofilter_swscale2x.create(menu_settings_videofilter, group, "Scale2x"); - group.reset(); - menu_settings_videofilter.finish(); - - menu_settings_videoframeskip.create(menu_settings, "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_0.create(menu_settings_videoframeskip, group, "0"); - menu_settings_videoframeskip_sep1.create(menu_settings_videoframeskip); - menu_settings_videoframeskip_1.create(menu_settings_videoframeskip, group, "1"); - menu_settings_videoframeskip_2.create(menu_settings_videoframeskip, group, "2"); - menu_settings_videoframeskip_3.create(menu_settings_videoframeskip, group, "3"); - menu_settings_videoframeskip_4.create(menu_settings_videoframeskip, group, "4"); - menu_settings_videoframeskip_5.create(menu_settings_videoframeskip, group, "5"); - menu_settings_videoframeskip_6.create(menu_settings_videoframeskip, group, "6"); - menu_settings_videoframeskip_7.create(menu_settings_videoframeskip, group, "7"); - menu_settings_videoframeskip_8.create(menu_settings_videoframeskip, group, "8"); - menu_settings_videoframeskip_9.create(menu_settings_videoframeskip, group, "9"); - group.reset(); - menu_settings_videoframeskip.finish(); - - menu_settings_sep1.create(menu_settings); - menu_settings_mute.create(menu_settings, "Mute Sound Output"); - menu_settings_sep2.create(menu_settings); - - menu_settings_speedreg.create(menu_settings, "Speed Regulation"); - menu_settings_speedreg_enable.create(menu_settings_speedreg, "Enable"); - menu_settings_speedreg_sep1.create(menu_settings_speedreg); - group.add(menu_settings_speedreg_slowest); - group.add(menu_settings_speedreg_slow); - group.add(menu_settings_speedreg_normal); - group.add(menu_settings_speedreg_fast); - group.add(menu_settings_speedreg_fastest); - menu_settings_speedreg_slowest.create(menu_settings_speedreg, group, "Slowest"); - menu_settings_speedreg_slow.create(menu_settings_speedreg, group, "Slow"); - menu_settings_speedreg_normal.create(menu_settings_speedreg, group, "Normal"); - menu_settings_speedreg_fast.create(menu_settings_speedreg, group, "Fast"); - menu_settings_speedreg_fastest.create(menu_settings_speedreg, group, "Fastest"); - group.reset(); - menu_settings_speedreg.finish(); - - menu_settings_sep3.create(menu_settings); - menu_settings_config.create(menu_settings, "Configuration ..."); - menu_settings.finish(); - - menu_misc.create(menu, "Misc"); - menu_misc_logaudio.create(menu_misc, "Log Audio Data"); - menu_misc_showfps.create(menu_misc, "Show FPS"); - menu_misc_sep1.create(menu_misc); - menu_misc_about.create(menu_misc, "About ..."); - menu_misc.finish(); - menu.finish(); - - view.create(*this, 0, 0, 0, 256, 224); - view.set_background_color(0, 0, 0); -} - -void MainWindow::update_menu_settings() { - locked = true; - - event::load_video_settings(); - - 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); - - 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_swntsc.check(); break; - case 2: menu_settings_videofilter_swhq2x.check(); break; - case 3: menu_settings_videofilter_swscale2x.check(); break; - } - - menu_settings_mute.check(config::snes.mute); - - menu_settings_speedreg_enable.check(config::system.regulate_speed); - menu_settings_speedreg_normal.check(); - - menu_misc_showfps.check(config::misc.show_frame_counter); - - locked = false; -} diff --git a/src/ui/lui/ui_main.h b/src/ui/lui/ui_main.h deleted file mode 100644 index 46c61fc5..00000000 --- a/src/ui/lui/ui_main.h +++ /dev/null @@ -1,74 +0,0 @@ -class MainWindow : public ui::Window { public: -ui::MenuGroup menu_file; - ui::MenuItem menu_file_load; - ui::MenuGroup menu_file_load_special; - ui::MenuItem menu_file_load_bsx; - ui::MenuItem menu_file_load_bsc; - ui::MenuItem menu_file_load_st; - ui::MenuItem menu_file_unload; - ui::MenuSeparator menu_file_sep1; - ui::MenuItem menu_file_reset; - ui::MenuItem menu_file_power; - ui::MenuSeparator menu_file_sep2; - ui::MenuItem menu_file_exit; -ui::MenuGroup menu_settings; - ui::MenuGroup menu_settings_videomode; - ui::MenuRadioItem menu_settings_videomode_1x; - ui::MenuRadioItem menu_settings_videomode_2x; - ui::MenuRadioItem menu_settings_videomode_3x; - ui::MenuRadioItem menu_settings_videomode_4x; - ui::MenuRadioItem menu_settings_videomode_5x; - ui::MenuSeparator menu_settings_videomode_sep1; - ui::MenuCheckItem menu_settings_videomode_aspect_correction; - ui::MenuSeparator menu_settings_videomode_sep2; - ui::MenuRadioItem menu_settings_videomode_ntsc; - ui::MenuRadioItem menu_settings_videomode_pal; - ui::MenuGroup menu_settings_videofilter; - ui::MenuRadioItem menu_settings_videofilter_hwpoint; - ui::MenuRadioItem menu_settings_videofilter_hwlinear; - ui::MenuSeparator menu_settings_videofilter_sep1; - ui::MenuRadioItem menu_settings_videofilter_swnone; - ui::MenuRadioItem menu_settings_videofilter_swntsc; - ui::MenuRadioItem menu_settings_videofilter_swhq2x; - ui::MenuRadioItem menu_settings_videofilter_swscale2x; - ui::MenuGroup menu_settings_videoframeskip; - ui::MenuRadioItem menu_settings_videoframeskip_0; - ui::MenuSeparator menu_settings_videoframeskip_sep1; - ui::MenuRadioItem menu_settings_videoframeskip_1; - ui::MenuRadioItem menu_settings_videoframeskip_2; - ui::MenuRadioItem menu_settings_videoframeskip_3; - ui::MenuRadioItem menu_settings_videoframeskip_4; - ui::MenuRadioItem menu_settings_videoframeskip_5; - ui::MenuRadioItem menu_settings_videoframeskip_6; - ui::MenuRadioItem menu_settings_videoframeskip_7; - ui::MenuRadioItem menu_settings_videoframeskip_8; - ui::MenuRadioItem menu_settings_videoframeskip_9; - ui::MenuSeparator menu_settings_sep1; - ui::MenuCheckItem menu_settings_mute; - ui::MenuSeparator menu_settings_sep2; - ui::MenuGroup menu_settings_speedreg; - ui::MenuCheckItem menu_settings_speedreg_enable; - ui::MenuSeparator menu_settings_speedreg_sep1; - ui::MenuRadioItem menu_settings_speedreg_slowest; - ui::MenuRadioItem menu_settings_speedreg_slow; - ui::MenuRadioItem menu_settings_speedreg_normal; - ui::MenuRadioItem menu_settings_speedreg_fast; - ui::MenuRadioItem menu_settings_speedreg_fastest; - ui::MenuSeparator menu_settings_sep3; - ui::MenuItem menu_settings_config; -ui::MenuGroup menu_misc; - ui::MenuCheckItem menu_misc_logaudio; - ui::MenuCheckItem menu_misc_showfps; - ui::MenuSeparator menu_misc_sep1; - ui::MenuItem menu_misc_about; - -ui::Container view; -// - - bool input_ready(); - -bool locked; - bool message(uint id, uintptr_t param = 0); - void setup(); - void update_menu_settings(); -} window_main; diff --git a/src/ui/main.cpp b/src/ui/main.cpp index acdb2fe3..7a8e43bd 100644 --- a/src/ui/main.cpp +++ b/src/ui/main.cpp @@ -1,7 +1,6 @@ #define INTERFACE_MAIN #include "../base.h" -#include "main.h" #include "config.cpp" void init_snes(); @@ -11,9 +10,13 @@ void term_snes(); * hardware abstraction layer *****/ -#include "video/video.cpp" -#include "audio/audio.cpp" -#include "input/input.cpp" +#include "vai/video.h" +#include "vai/audio.h" +#include "vai/input.h" + +Video *uiVideo; +Audio *uiAudio; +Input *uiInput; #include "inputmgr.cpp" #include "interface.cpp" @@ -22,12 +25,10 @@ void term_snes(); * platform abstraction layer *****/ -#if defined(UI_LUI) - #include "lui/main.cpp" -#elif defined(UI_WIN) - #include "win/main.cpp" -#elif defined(UI_SDL) - #include "sdl/main.cpp" +#if defined(UI_MIU) + #include "../lib/miu.h" + using namespace ns_miu; + #include "miu/main.cpp" #else #error "unsupported platform" #endif diff --git a/src/ui/main.h b/src/ui/main.h deleted file mode 100644 index a05798f9..00000000 --- a/src/ui/main.h +++ /dev/null @@ -1 +0,0 @@ -#include "../lib/libkeymap.h" diff --git a/src/ui/lui/event.cpp b/src/ui/miu/event.cpp similarity index 67% rename from src/ui/lui/event.cpp rename to src/ui/miu/event.cpp index 8ed45970..70a10036 100644 --- a/src/ui/lui/event.cpp +++ b/src/ui/miu/event.cpp @@ -24,44 +24,57 @@ void load_video_settings() { 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; + 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(uint multiplier) { switch(config::video.mode) { default: - case 0: config::video.windowed.multiplier = multiplier; break; - case 1: config::video.fullscreen.multiplier = multiplier; break; + case 0: config::video.windowed.multiplier = multiplier; break; + case 1: config::video.fullscreen.multiplier = multiplier; break; } update_video_settings(); } void update_region(uint region) { switch(config::video.mode) { default: - case 0: config::video.windowed.region = region; break; - case 1: config::video.fullscreen.region = region; break; + case 0: config::video.windowed.region = region; break; + case 1: config::video.fullscreen.region = region; break; } update_video_settings(); } void update_hardware_filter(uint 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; + 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(uint 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; + 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_speed_regulation(uint speed) { + config::system.speed = max(1, min(speed, 5)); + if(uiAudio && uiAudio->cap(Audio::Frequency)) { + switch(config::system.speed) { + case 1: uiAudio->set(Audio::Frequency, 16000); break; + case 2: uiAudio->set(Audio::Frequency, 24000); break; + case 3: uiAudio->set(Audio::Frequency, 32000); break; + case 4: uiAudio->set(Audio::Frequency, 48000); break; + case 5: uiAudio->set(Audio::Frequency, 64000); break; + } + } +} + void update_frame_counter() { if(ppu.status.frames_updated) { ppu.status.frames_updated = false; @@ -88,39 +101,40 @@ uint multiplier = minmax<1, 5>(video_settings.multiplier); } switch(video_settings.mode) { default: - case 0: //windowed - window_main.unfullscreen(); - window_main.resize(width, height); - window_main.view.move(0, 0); - window_main.view.resize(width, height); - break; - case 1: //fullscreen - window_main.fullscreen(); - window_main.view.move((ui::get_screen_width() - width) / 2, (ui::get_screen_height() - height) / 2); - window_main.view.resize(width, height); - break; + case 0: { //windowed + window_main.unfullscreen(); + window_main.resize(width, height); + window_main.move(window_main.view, 0, 0); + window_main.view.resize(width, height); + } break; + case 1: { //fullscreen + window_main.fullscreen(); + window_main.move(window_main.view, + (miu().screen_width() - width) / 2, + (miu().screen_height() - height) / 2); + window_main.view.resize(width, height); + } break; } uint filter, standard; switch(video_settings.software_filter) { default: - case 0: filter = VIDEOFILTER_DIRECT; break; - case 1: filter = VIDEOFILTER_NTSC; break; - case 2: filter = VIDEOFILTER_HQ2X; break; - case 3: filter = VIDEOFILTER_SCALE2X; break; + case 0: filter = VIDEOFILTER_DIRECT; break; + case 1: filter = VIDEOFILTER_NTSC; break; + case 2: filter = VIDEOFILTER_HQ2X; break; + case 3: filter = VIDEOFILTER_SCALE2X; break; } switch(video_settings.region) { default: - case 0: standard = SNES::VIDEOSTANDARD_NTSC; break; - case 1: standard = SNES::VIDEOSTANDARD_PAL; break; + case 0: standard = SNES::VIDEOSTANDARD_NTSC; break; + case 1: standard = SNES::VIDEOSTANDARD_PAL; break; } snes.set_video_filter(filter); snes.set_video_standard(standard); if(uiVideo) { - uiVideo->settings.synchronize = video_settings.synchronize; - uiVideo->settings.filter = video_settings.hardware_filter; - uiVideo->update_settings(); + uiVideo->set(Video::Synchronize, video_settings.synchronize); + uiVideo->set(Video::Filter, video_settings.hardware_filter); } //update main window video mode checkbox settings @@ -128,7 +142,7 @@ uint filter, standard; } void toggle_menu() { - window_main.menu.show(!window_main.menu.visible()); + window_main.menu_show(!window_main.menu_visible()); update_video_settings(); } @@ -144,21 +158,21 @@ void toggle_fullscreen() { // bool load_rom(char *fn) { -stringarray dir; +lstring dir; strcpy(fn, ""); - strcpy(dir, config::path.rom); - replace(dir, "\\", "/"); - if(strlen(dir) && !strend(dir, "/")) { strcat(dir, "/"); } + strcpy(dir[0], config::path.rom); + replace(dir[0], "\\", "/"); + if(strlen(dir[0]) && !strend(dir[0], "/")) strcat(dir[0], "/"); //append base path if rom path is relative - if(strbegin(dir, "./")) { - strltrim(dir, "./"); + if(strbegin(dir[0], "./")) { + ltrim(dir[0], "./"); strcpy(dir[1], dir[0]); strcpy(dir[0], config::path.base); strcat(dir[0], dir[1]); } - return ui::file_load(0, fn, + return miu().file_load(0, fn, "SNES images;*.smc,*.sfc,*.swc,*.fig,*.bs,*.st" #if defined(GZIP_SUPPORT) ",*.gz,*.z,*.zip" @@ -167,7 +181,7 @@ stringarray dir; ",*.jma" #endif "|All files;*.*", - strptr(dir)); + dir[0]); } void load_rom() { diff --git a/src/ui/lui/event.h b/src/ui/miu/event.h similarity index 90% rename from src/ui/lui/event.h rename to src/ui/miu/event.h index e9bb2646..250f414f 100644 --- a/src/ui/lui/event.h +++ b/src/ui/miu/event.h @@ -11,13 +11,14 @@ struct VideoSettings { } video_settings; void load_video_settings(); -//change video settings for active video mode void update_aspect_correction(bool); void update_multiplier(uint); void update_region(uint); void update_hardware_filter(uint); void update_software_filter(uint); +void update_speed_regulation(uint); + void update_frame_counter(); void update_video_settings(); void toggle_menu(); diff --git a/src/ui/miu/loader/ui_bsxloader.cpp b/src/ui/miu/loader/ui_bsxloader.cpp new file mode 100644 index 00000000..00853038 --- /dev/null +++ b/src/ui/miu/loader/ui_bsxloader.cpp @@ -0,0 +1,92 @@ +uintptr_t BSXLoaderWindow::close(Event) { + hide(); + return false; +} + +uintptr_t BSXLoaderWindow::bbase_tick(Event) { +char fn[PATH_MAX]; + if(event::load_rom(fn) == true) tbase.set_text(fn); + return true; +} + +uintptr_t BSXLoaderWindow::cbase_tick(Event) { + tbase.set_text(""); + return true; +} + +uintptr_t BSXLoaderWindow::bslot_tick(Event) { +char fn[PATH_MAX]; + if(event::load_rom(fn) == true) tslot.set_text(fn); + return true; +} + +uintptr_t BSXLoaderWindow::cslot_tick(Event) { + tslot.set_text(""); + return true; +} + +uintptr_t BSXLoaderWindow::load_tick(Event) { +char base[PATH_MAX], slot[PATH_MAX]; + tbase.get_text(base, PATH_MAX); + tslot.get_text(slot, PATH_MAX); + + if(mode == ModeBSX) { + 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) { + tbase.set_text(""); + tslot.set_text(""); + hide(); + return true; +} + +void BSXLoaderWindow::setup() { + create(Window::AutoCenter, 640, 150, "Load BS-X Cartridge"); + + lbase.create(0, 630, 20, "Base cartridge:"); + tbase.create(0, 420, 30); + bbase.create(0, 100, 30, "Browse ..."); + cbase.create(0, 100, 30, "Clear"); + + lslot.create(0, 630, 20, "Slot cartridge:"); + tslot.create(0, 420, 30); + bslot.create(0, 100, 30, "Browse ..."); + cslot.create(0, 100, 30, "Clear"); + + load.create (0, 312, 30, "Load"); + cancel.create(0, 312, 30, "Cancel"); + +uint y = 5; + attach(lbase, 5, y); y += 20; + attach(tbase, 5, y); + attach(bbase, 430, y); + attach(cbase, 535, y); y += 30 + 5; + attach(lslot, 5, y); y += 20; + attach(tslot, 5, y); + attach(bslot, 430, y); + attach(cslot, 535, y); y += 30 + 5; + attach(load, 5, y); + attach(cancel, 323, y); y += 30 + 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/miu/loader/ui_bsxloader.h b/src/ui/miu/loader/ui_bsxloader.h new file mode 100644 index 00000000..e5d7e3c4 --- /dev/null +++ b/src/ui/miu/loader/ui_bsxloader.h @@ -0,0 +1,28 @@ +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); + uintptr_t bbase_tick(Event); + uintptr_t cbase_tick(Event); + uintptr_t bslot_tick(Event); + uintptr_t cslot_tick(Event); + uintptr_t load_tick(Event); + uintptr_t cancel_tick(Event); + + BSXLoaderWindow(); +} window_bsxloader; diff --git a/src/ui/miu/loader/ui_stloader.cpp b/src/ui/miu/loader/ui_stloader.cpp new file mode 100644 index 00000000..a133b5ad --- /dev/null +++ b/src/ui/miu/loader/ui_stloader.cpp @@ -0,0 +1,109 @@ +uintptr_t STLoaderWindow::close(Event) { + hide(); + return false; +} + +uintptr_t STLoaderWindow::bbase_tick(Event) { +char fn[PATH_MAX]; + if(event::load_rom(fn) == true) tbase.set_text(fn); + return true; +} + +uintptr_t STLoaderWindow::cbase_tick(Event) { + tbase.set_text(""); + return true; +} + +uintptr_t STLoaderWindow::bslotA_tick(Event) { +char fn[PATH_MAX]; + if(event::load_rom(fn) == true) tslotA.set_text(fn); + return true; +} + +uintptr_t STLoaderWindow::cslotA_tick(Event) { + tslotA.set_text(""); + return true; +} + +uintptr_t STLoaderWindow::bslotB_tick(Event) { +char fn[PATH_MAX]; + if(event::load_rom(fn) == true) tslotB.set_text(fn); + return true; +} + +uintptr_t STLoaderWindow::cslotB_tick(Event) { + tslotB.set_text(""); + return true; +} + +uintptr_t STLoaderWindow::load_tick(Event) { +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); + + 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) { + tbase.set_text(""); + tslotA.set_text(""); + tslotB.set_text(""); + hide(); + return true; +} + +void STLoaderWindow::setup() { + create(Window::AutoCenter, 640, 205, "Load Sufami Turbo Cartridge"); + + lbase.create(0, 630, 20, "Base cartridge:"); + tbase.create(0, 420, 30); + bbase.create(0, 100, 30, "Browse ..."); + cbase.create(0, 100, 30, "Clear"); + + lslotA.create(0, 630, 20, "Slot A cartridge:"); + tslotA.create(0, 420, 30); + bslotA.create(0, 100, 30, "Browse ..."); + cslotA.create(0, 100, 30, "Clear"); + + lslotB.create(0, 630, 20, "Slot B cartridge:"); + tslotB.create(0, 420, 30); + bslotB.create(0, 100, 30, "Browse ..."); + cslotB.create(0, 100, 30, "Clear"); + + load.create (0, 312, 30, "Load"); + cancel.create(0, 312, 30, "Cancel"); + +uint y = 5; + attach(lbase, 5, y); y += 20; + attach(tbase, 5, y); + attach(bbase, 430, y); + attach(cbase, 535, y); y += 30 + 5; + attach(lslotA, 5, y); y += 20; + attach(tslotA, 5, y); + attach(bslotA, 430, y); + attach(cslotA, 535, y); y += 30 + 5; + attach(lslotB, 5, y); y += 20; + attach(tslotB, 5, y); + attach(bslotB, 430, y); + attach(cslotB, 535, y); y += 30 + 5; + attach(load, 5, y); + attach(cancel, 323, y); y += 30 + 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/miu/loader/ui_stloader.h b/src/ui/miu/loader/ui_stloader.h new file mode 100644 index 00000000..3d8dd476 --- /dev/null +++ b/src/ui/miu/loader/ui_stloader.h @@ -0,0 +1,27 @@ +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); + uintptr_t bbase_tick(Event); + uintptr_t cbase_tick(Event); + uintptr_t bslotA_tick(Event); + uintptr_t cslotA_tick(Event); + uintptr_t bslotB_tick(Event); + uintptr_t cslotB_tick(Event); + uintptr_t load_tick(Event); + uintptr_t cancel_tick(Event); +} window_stloader; diff --git a/src/ui/lui/main.cpp b/src/ui/miu/main.cpp similarity index 82% rename from src/ui/lui/main.cpp rename to src/ui/miu/main.cpp index c7c0452b..e3cfc836 100644 --- a/src/ui/lui/main.cpp +++ b/src/ui/miu/main.cpp @@ -1,15 +1,4 @@ void run(); - -#if defined(PLATFORM_WIN) - #include "../../lib/libui_win.h" -#elif defined(PLATFORM_X) - #include "../../lib/libui_gtk.h" -#else - #error "unsupported platform" -#endif - -namespace ui = libui; - bool _term_ = false; #include "ui.h" @@ -68,21 +57,23 @@ char full_name[PATH_MAX] = ""; string t = full_name; if(strlen(t) != 0) { //remove program name + //TODO: rewrite this to be cleaner ... replace(t, "\\", "/"); for(int i = strlen(t) - 1; i >= 0; i--) { - if(strptr(t)[i] == '/' || strptr(t)[i] == '\\') { - strptr(t)[i] = 0; + if(t()[i] == '/' || t()[i] == '\\') { + t()[i] = 0; break; } } } if(strend(t, "/") == false) { strcat(t, "/"); } - config::path.base = strptr(t); + config::path.base = t; } void run() { - while(ui::events_pending() == true) { ui::run(); } + while(miu().pending()) miu().run(); + if(cartridge.loaded() == true) { snes.runtoframe(); event::update_frame_counter(); @@ -107,7 +98,7 @@ int main(int argc, char *argv[]) { set_config_filename(); get_base_path(argv[0]); - ui::init(); + miu().init(); config::config().load(config::filename); if(fexists(config::filename) == false) { //in case program crashes on first run, save config file @@ -131,6 +122,6 @@ int main(int argc, char *argv[]) { config::config().save(config::filename); snes.term(); ui_term(); - ui::term(); + miu().term(); return 0; } diff --git a/src/ui/miu/settings/ui_advanced.cpp b/src/ui/miu/settings/ui_advanced.cpp new file mode 100644 index 00000000..2a49cd2d --- /dev/null +++ b/src/ui/miu/settings/ui_advanced.cpp @@ -0,0 +1,85 @@ +uintptr_t AdvancedWindow::list_change(Event) { +int pos = list.get_selection(); + set_val.enable(pos >= 0); + set_def.enable(pos >= 0); + if(pos >= 0 && pos < config::config().list_count) { + desc.set_text(string() << "(default = " << config::config().list[pos]->def << ")\n" << config::config().list[pos]->desc); + string val; + config::config().list[pos]->get(val); + edit_val.set_text(val); + } +} + +uintptr_t AdvancedWindow::setval_tick(Event) { +char t[4096]; + edit_val.get_text(t, sizeof t); + update(list.get_selection(), t); +} + +uintptr_t AdvancedWindow::setdef_tick(Event) { + update(list.get_selection(), 0); + return true; +} + +void AdvancedWindow::read_config(uint pos, string &data) { + data = "?\t?\t?"; + if(pos >= config::config().list_count) return; + +string name, val; + name = config::config().list[pos]->name; + config::config().list[pos]->get(val); + if(val != config::config().list[pos]->def) { strcat(name, " (*)"); } + data = string() + << name << "\t" + << (config::config().list[pos]->type == Setting::String ? "String" : "Integer") << "\t" + << val; +} + +void AdvancedWindow::update(uint pos, const char *data) { + if(pos >= config::config().list_count) return; + + config::config().list[pos]->set(data ? data : config::config().list[pos]->def); +string val; + config::config().list[pos]->get(val); + edit_val.set_text(val); + read_config(pos, val); + list.set_item(pos, val); + list.autosize_columns(); +} + +void AdvancedWindow::setup() { + create(0, 475, 355); + + list.create(Listbox::Header | Listbox::VerticalScrollAlways, 475, 235, "Name\tType\tValue"); + desc.create(Editbox::Multiline | Editbox::VerticalScrollAlways | Editbox::Readonly, 475, 80, + "\n" + "Warning: modifification of certain variables will not take effect until\n" + "bsnes is restarted, and corresponding UI elements will not be updated\n" + "to reflect changes here. (*) = modified" + ); + edit_val.create(0, 265, 30, ""); + set_val.create (0, 100, 30, "Set"); + set_def.create (0, 100, 30, "Default"); + +uint y = 0; + attach(list, 0, y); y += 235 + 5; + attach(desc, 0, y); y += 80 + 5; + attach(edit_val, 0, y); + attach(set_val, 270, y); + attach(set_def, 375, y); y += 30 + 5; + + for(int i = 0; i < config::config().list_count; i++) { + string val; + read_config(i, val); + list.add_item(val); + } + + list.autosize_columns(); + + set_val.disable(); + set_def.disable(); + + list.on_change = bind(&AdvancedWindow::list_change, this); + set_val.on_tick = bind(&AdvancedWindow::setval_tick, this); + set_def.on_tick = bind(&AdvancedWindow::setdef_tick, this); +} diff --git a/src/ui/miu/settings/ui_advanced.h b/src/ui/miu/settings/ui_advanced.h new file mode 100644 index 00000000..561d0514 --- /dev/null +++ b/src/ui/miu/settings/ui_advanced.h @@ -0,0 +1,15 @@ +class AdvancedWindow : public Window { +public: + Listbox list; + Editbox desc; + Editbox edit_val; + Button set_val; + Button set_def; + + void read_config(uint pos, string &data); + void update(uint pos, const char *data); + void setup(); + uintptr_t list_change(Event); + uintptr_t setval_tick(Event); + uintptr_t setdef_tick(Event); +} window_advanced; diff --git a/src/ui/miu/settings/ui_cheateditor.cpp b/src/ui/miu/settings/ui_cheateditor.cpp new file mode 100644 index 00000000..ea1ce934 --- /dev/null +++ b/src/ui/miu/settings/ui_cheateditor.cpp @@ -0,0 +1,91 @@ +void CheatEditorWindow::setup() { + create(0, 475, 355); + + list.create(Listbox::Header | Listbox::VerticalScrollAlways, 475, 285, "Status\tCode\tDescription"); + add_code.create (0, 155, 30, "Add Code"); + toggle_code.create(0, 155, 30, "Toggle Status"); + delete_code.create(0, 155, 30, "Delete Code"); + code.create(0, 155, 30, ""); + desc.create(0, 315, 30, ""); + +uint y = 0; + attach(list, 0, y); y += 285 + 5; + attach(add_code, 0, y); + attach(toggle_code, 160, y); + attach(delete_code, 320, y); y += 30 + 5; + attach(code, 0, y); + attach(desc, 160, y); y += 30 + 5; + + list.on_activate = bind(&CheatEditorWindow::toggle_event, this); + add_code.on_tick = bind(&CheatEditorWindow::add_tick, this); + toggle_code.on_tick = bind(&CheatEditorWindow::toggle_event, this); + delete_code.on_tick = bind(&CheatEditorWindow::delete_tick, this); + + refresh(); +} + +void CheatEditorWindow::refresh() { + list.reset(); + + for(uint i = 0; i < cheat.count(); i++) { + bool enabled; + uint32 addr; + uint8 data; + char s_code[256], s_desc[256]; + cheat.get(i, enabled, addr, data, s_code, s_desc); + list.add_item(string() + << (enabled ? "Enabled" : "Disabled") << "\t" + << s_code << "\t" + << s_desc); + } + + list.autosize_columns(); + +//enable controls only if cartridge is loaded +bool loaded = cartridge.loaded(); + add_code.enable(loaded); + toggle_code.enable(loaded); + delete_code.enable(loaded); +} + +uintptr_t CheatEditorWindow::toggle_event(Event) { +int index = list.get_selection(); + if(index >= 0 && index < cheat.count()) { + cheat.enabled(index) ? cheat.disable(index) : cheat.enable(index); + bool enabled; + uint32 addr; + uint8 data; + char s_code[256], s_desc[256]; + cheat.get(index, enabled, addr, data, s_code, s_desc); + list.set_item(index, string() + << (enabled ? "Enabled" : "Disabled") << "\t" + << s_code << "\t" + << s_desc); + } + return true; +} + +uintptr_t CheatEditorWindow::add_tick(Event) { +char s_code[256], s_desc[256]; + code.get_text(s_code, sizeof s_code); + desc.get_text(s_desc, sizeof s_desc); + cheat.add(false, s_code, s_desc); //param 0 = false, meaning: new codes disabled by default + refresh(); + return true; +} + +uintptr_t CheatEditorWindow::delete_tick(Event) { +int index = list.get_selection(); + if(index >= 0 && index < cheat.count()) { + cheat.remove(index); + refresh(); + } + return true; +} + +/* +bool CheatEditorWindow::message(uint id, uintptr_t param) { + if((id == ui::Message::Clicked && control == &toggle_code) || + (id == ui::Message::DoubleClicked && control == &list)) {} +} +*/ diff --git a/src/ui/miu/settings/ui_cheateditor.h b/src/ui/miu/settings/ui_cheateditor.h new file mode 100644 index 00000000..c385e61c --- /dev/null +++ b/src/ui/miu/settings/ui_cheateditor.h @@ -0,0 +1,16 @@ +class CheatEditorWindow : public Window { +public: + Listbox list; + Button add_code; + Button toggle_code; + Button delete_code; + Editbox code; + Editbox desc; + + void setup(); + void refresh(); + + uintptr_t toggle_event(Event); + uintptr_t add_tick(Event); + uintptr_t delete_tick(Event); +} window_cheat_editor; diff --git a/src/ui/miu/settings/ui_inputconfig.cpp b/src/ui/miu/settings/ui_inputconfig.cpp new file mode 100644 index 00000000..d201e42c --- /dev/null +++ b/src/ui/miu/settings/ui_inputconfig.cpp @@ -0,0 +1,214 @@ +/* InputConfigWindow */ + +void InputConfigWindow::setup() { + create(0, 475, 355); + + lportA.create(0, 235, 20, "Controller Port A:"); + lportB.create(0, 235, 20, "Controller Port B:"); + + portA.create(0, 235, 30); + portA.add_item("None"); + portA.add_item("Joypad 1"); + portA.add_item("Joypad 2"); + portA.set_selection(1); + portA.disable(); + + portB.create(0, 235, 30); + portB.add_item("None"); + portB.add_item("Joypad 1"); + portB.add_item("Joypad 2"); + portB.set_selection(2); + portB.disable(); + + list.create(Listbox::Header | Listbox::VerticalScrollAlways, 475, 265, "Name\tValue"); + setkey.create(0, 235, 30, "Assign Key"); + setkey.disable(); + clrkey.create(0, 235, 30, "Unassign Key"); + clrkey.disable(); + +uint y = 0; + attach(lportA, 0, y); + attach(lportB, 240, y); y += 20; + attach(portA, 0, y); + attach(portB, 240, y); y += 30 + 5; + attach(list, 0, y); y += 265 + 5; + attach(setkey, 0, y); + attach(clrkey, 240, y); y += 30 + 5; + + 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); + + for(uint i = 0; i < 24; i++) list.add_item("???\t???"); + refresh_list(); + window_input_capture.setup(); +} + +void InputConfigWindow::refresh_list() { + for(uint i = 0; i < 24; i++) { + list.set_item(i, string() << list_index[i] << "\t" << keymap::find(get_value(i))); + } + list.autosize_columns(); +} + +uintptr_t InputConfigWindow::list_change(Event) { +int pos = list.get_selection(); + setkey.enable(pos >= 0); + clrkey.enable(pos >= 0); + return true; +} + +uintptr_t InputConfigWindow::set_tick(Event) { +int pos = list.get_selection(); + if(pos < 0) return true; + window_input_capture.index = pos; + window_input_capture.label.set_text(string() << "Press a key to assign to " << list_index[pos] << " ..."); + window_input_capture.show(); + return true; +} + +uintptr_t InputConfigWindow::clr_tick(Event) { +int pos = list.get_selection(); + if(pos < 0) return true; + set_value(pos, keymap::none); + refresh_list(); + return true; +} + +/* InputCaptureWindow */ + +void InputCaptureWindow::setup() { + create(Window::AutoCenter, 350, 100, "bsnes Key Capture"); + label.create(0, 340, 90); + attach(label, 5, 5); + on_close = bind(&InputCaptureWindow::close, this); +} + +void InputCaptureWindow::show() { + uiInput->clear_input(); + +//enter and spacebar can be used to activate key capture, +//set lock on these keys if they are held down to prevent +//them from being instantly assigned to selected entry ... + uiInput->poll(); + key_lock = (uiInput->key_down(keymap::enter) || uiInput->key_down(keymap::space)); + Window::focus(); + + while(_term_ == false && visible() == true) { + run(); + uint16 key = input_manager.scan(); + if(key == keymap::none) { key_lock = false; continue; } + if(key_lock && (key == keymap::enter || key == keymap::space)) { continue; } + hide(); + window_input_config.set_value(index, key); + window_input_config.refresh_list(); + break; + } + + uiInput->clear_input(); +} + +uintptr_t InputCaptureWindow::close(Event) { + hide(); + return false; +} + +InputCaptureWindow::InputCaptureWindow() { + index = 0; + key_lock = false; +} + +/* Misc */ + +const char InputConfigWindow::list_index[][64] = { + "Joypad 1 Up", + "Joypad 1 Down", + "Joypad 1 Left", + "Joypad 1 Right", + "Joypad 1 A", + "Joypad 1 B", + "Joypad 1 X", + "Joypad 1 Y", + "Joypad 1 L", + "Joypad 1 R", + "Joypad 1 Select", + "Joypad 1 Start", + + "Joypad 2 Up", + "Joypad 2 Down", + "Joypad 2 Left", + "Joypad 2 Right", + "Joypad 2 A", + "Joypad 2 B", + "Joypad 2 X", + "Joypad 2 Y", + "Joypad 2 L", + "Joypad 2 R", + "Joypad 2 Select", + "Joypad 2 Start", +}; + +uint InputConfigWindow::get_value(uint index) { + switch(index) { + case 0: return keymap::find(config::input.joypad1.up); + case 1: return keymap::find(config::input.joypad1.down); + case 2: return keymap::find(config::input.joypad1.left); + case 3: return keymap::find(config::input.joypad1.right); + case 4: return keymap::find(config::input.joypad1.a); + case 5: return keymap::find(config::input.joypad1.b); + case 6: return keymap::find(config::input.joypad1.x); + case 7: return keymap::find(config::input.joypad1.y); + case 8: return keymap::find(config::input.joypad1.l); + case 9: return keymap::find(config::input.joypad1.r); + case 10: return keymap::find(config::input.joypad1.select); + case 11: return keymap::find(config::input.joypad1.start); + + case 12: return keymap::find(config::input.joypad2.up); + case 13: return keymap::find(config::input.joypad2.down); + case 14: return keymap::find(config::input.joypad2.left); + case 15: return keymap::find(config::input.joypad2.right); + case 16: return keymap::find(config::input.joypad2.a); + case 17: return keymap::find(config::input.joypad2.b); + case 18: return keymap::find(config::input.joypad2.x); + case 19: return keymap::find(config::input.joypad2.y); + case 20: return keymap::find(config::input.joypad2.l); + case 21: return keymap::find(config::input.joypad2.r); + case 22: return keymap::find(config::input.joypad2.select); + case 23: return keymap::find(config::input.joypad2.start); + } + + return keymap::none; +} + +void InputConfigWindow::set_value(uint index, uint16 value) { + switch(index) { + case 0: config::input.joypad1.up = keymap::find(value); break; + case 1: config::input.joypad1.down = keymap::find(value); break; + case 2: config::input.joypad1.left = keymap::find(value); break; + case 3: config::input.joypad1.right = keymap::find(value); break; + case 4: config::input.joypad1.a = keymap::find(value); break; + case 5: config::input.joypad1.b = keymap::find(value); break; + case 6: config::input.joypad1.x = keymap::find(value); break; + case 7: config::input.joypad1.y = keymap::find(value); break; + case 8: config::input.joypad1.l = keymap::find(value); break; + case 9: config::input.joypad1.r = keymap::find(value); break; + case 10: config::input.joypad1.select = keymap::find(value); break; + case 11: config::input.joypad1.start = keymap::find(value); break; + + case 12: config::input.joypad2.up = keymap::find(value); break; + case 13: config::input.joypad2.down = keymap::find(value); break; + case 14: config::input.joypad2.left = keymap::find(value); break; + case 15: config::input.joypad2.right = keymap::find(value); break; + case 16: config::input.joypad2.a = keymap::find(value); break; + case 17: config::input.joypad2.b = keymap::find(value); break; + case 18: config::input.joypad2.x = keymap::find(value); break; + case 19: config::input.joypad2.y = keymap::find(value); break; + case 20: config::input.joypad2.l = keymap::find(value); break; + case 21: config::input.joypad2.r = keymap::find(value); break; + case 22: config::input.joypad2.select = keymap::find(value); break; + case 23: config::input.joypad2.start = keymap::find(value); break; + } + + input_manager.bind(); +} diff --git a/src/ui/miu/settings/ui_inputconfig.h b/src/ui/miu/settings/ui_inputconfig.h new file mode 100644 index 00000000..cb2b05a0 --- /dev/null +++ b/src/ui/miu/settings/ui_inputconfig.h @@ -0,0 +1,36 @@ +class InputConfigWindow : public Window { +public: + Label lportA; + Label lportB; + Combobox portA; + Combobox portB; + Listbox list; + Button setkey; + Button clrkey; + + void setup(); + void refresh_list(); + + uintptr_t list_change(Event); + uintptr_t set_tick(Event); + uintptr_t clr_tick(Event); + + static const char list_index[][64]; + uint get_value(uint index); + void set_value(uint index, uint16 value); +} window_input_config; + +class InputCaptureWindow : public Window { +public: + Label label; + + uint index; + bool key_lock; + + void setup(); + void show(); + + uintptr_t close(Event); + + InputCaptureWindow(); +} window_input_capture; diff --git a/src/ui/miu/settings/ui_rastersettings.cpp b/src/ui/miu/settings/ui_rastersettings.cpp new file mode 100644 index 00000000..edd35b3d --- /dev/null +++ b/src/ui/miu/settings/ui_rastersettings.cpp @@ -0,0 +1,140 @@ +void RasterSettingsWindow::setup() { + create(0, 475, 355); + + lcontrast.create (0, 475, 20); + contrast.create (0, 475, 30, 192); + lbrightness.create (0, 475, 20); + brightness.create (0, 475, 30, 192); + lgamma.create (0, 475, 20); + gamma.create (0, 475, 30, 191); + gamma_ramp.create (0, 235, 20, "Gamma ramp"); + sepia.create (0, 235, 20, "Sepia"); + grayscale.create (0, 235, 20, "Grayscale"); + invert.create (0, 235, 20, "Invert colors"); + preset_optimal.create (0, 235, 30, "Optimal Preset"); + preset_standard.create(0, 235, 30, "Standard Preset"); + sync_ui(); + +uint y = 0; + attach(lcontrast, 0, y); y += 20; + attach(contrast, 0, y); y += 30; + attach(lbrightness, 0, y); y += 20; + attach(brightness, 0, y); y += 30; + attach(lgamma, 0, y); y += 20; + attach(gamma, 0, y); y += 30; + attach(gamma_ramp, 0, y); + attach(sepia, 240, y); y += 20; + attach(grayscale, 0, y); + attach(invert, 240, y); y += 20; + attach(preset_optimal, 0, y); + attach(preset_standard, 240, y); y += 30; + + contrast.on_change = bind(&RasterSettingsWindow::contrast_change, this); + brightness.on_change = bind(&RasterSettingsWindow::brightness_change, this); + gamma.on_change = bind(&RasterSettingsWindow::gamma_change, this); + gamma_ramp.on_tick = bind(&RasterSettingsWindow::gammaramp_tick, this); + sepia.on_tick = bind(&RasterSettingsWindow::sepia_tick, this); + grayscale.on_tick = bind(&RasterSettingsWindow::grayscale_tick, this); + invert.on_tick = bind(&RasterSettingsWindow::invert_tick, this); + preset_optimal.on_tick = bind(&RasterSettingsWindow::optimal_tick, this); + preset_standard.on_tick = bind(&RasterSettingsWindow::standard_tick, this); +} + +//update all UI controls to match config file values ... +void RasterSettingsWindow::sync_ui() { + ui_lock = true; //supress event messages while syncing UI elements, prevents infinite recursion + contrast.set_position(config::snes.contrast + 96); + lcontrast.set_text(string() << "Contrast: " << config::snes.contrast); + brightness.set_position(config::snes.brightness + 96); + lbrightness.set_text(string() << "Brightness: " << config::snes.brightness); + gamma.set_position(config::snes.gamma - 10); + lgamma.set_text(string() << "Gamma: " << config::snes.gamma); //TODO: print gamma as "%0.2f" / 100.0 + gamma_ramp.check(config::snes.gamma_ramp); + sepia.check(config::snes.sepia); + grayscale.check(config::snes.grayscale); + invert.check(config::snes.invert); + snes.update_color_lookup_table(); + ui_lock = false; +} + +uintptr_t RasterSettingsWindow::contrast_change(Event) { + if(!ui_lock && config::snes.contrast != contrast.get_position() - 96) { + config::snes.contrast = contrast.get_position() - 96; + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::brightness_change(Event) { + if(!ui_lock && config::snes.brightness != brightness.get_position() - 96) { + config::snes.brightness = brightness.get_position() - 96; + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::gamma_change(Event) { + if(!ui_lock && config::snes.gamma != gamma.get_position() + 10) { + config::snes.gamma = gamma.get_position() + 10; + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::gammaramp_tick(Event) { + if(!ui_lock && config::snes.gamma_ramp != gamma_ramp.checked()) { + config::snes.gamma_ramp = gamma_ramp.checked(); + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::sepia_tick(Event) { + if(!ui_lock && config::snes.sepia != sepia.checked()) { + config::snes.sepia = sepia.checked(); + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::grayscale_tick(Event) { + if(!ui_lock && config::snes.grayscale != grayscale.checked()) { + config::snes.grayscale = grayscale.checked(); + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::invert_tick(Event) { + if(!ui_lock && config::snes.invert != invert.checked()) { + config::snes.invert = invert.checked(); + sync_ui(); + } + return true; +} + +uintptr_t RasterSettingsWindow::optimal_tick(Event) { + config::snes.contrast = 0; + config::snes.brightness = 0; + config::snes.gamma = 80; + config::snes.gamma_ramp = true; + config::snes.sepia = false; + config::snes.grayscale = false; + config::snes.invert = false; + sync_ui(); +} + +uintptr_t RasterSettingsWindow::standard_tick(Event) { + config::snes.contrast = 0; + config::snes.brightness = 0; + config::snes.gamma = 100; + config::snes.gamma_ramp = false; + config::snes.sepia = false; + config::snes.grayscale = false; + config::snes.invert = false; + sync_ui(); +} + +RasterSettingsWindow::RasterSettingsWindow() { + ui_lock = false; +} diff --git a/src/ui/miu/settings/ui_rastersettings.h b/src/ui/miu/settings/ui_rastersettings.h new file mode 100644 index 00000000..9d924efd --- /dev/null +++ b/src/ui/miu/settings/ui_rastersettings.h @@ -0,0 +1,33 @@ +class RasterSettingsWindow : public Window { +public: + Label lcontrast; + Label lbrightness; + Label lgamma; + Slider contrast; + Slider brightness; + Slider gamma; + + Checkbox gamma_ramp; + Checkbox sepia; + Checkbox grayscale; + Checkbox invert; + + Button preset_optimal; + Button preset_standard; + + void setup(); + void sync_ui(); + + bool ui_lock; + uintptr_t contrast_change(Event); + uintptr_t brightness_change(Event); + uintptr_t gamma_change(Event); + uintptr_t gammaramp_tick(Event); + uintptr_t sepia_tick(Event); + uintptr_t grayscale_tick(Event); + uintptr_t invert_tick(Event); + uintptr_t optimal_tick(Event); + uintptr_t standard_tick(Event); + + RasterSettingsWindow(); +} window_raster_settings; diff --git a/src/ui/miu/settings/ui_settings.cpp b/src/ui/miu/settings/ui_settings.cpp new file mode 100644 index 00000000..f88a3eae --- /dev/null +++ b/src/ui/miu/settings/ui_settings.cpp @@ -0,0 +1,47 @@ +void SettingsWindow::setup() { + create(Window::AutoCenter, 640, 365, "bsnes Configuration Settings"); + + panel_list.create(0, 150, 355); + panel_list.add_item("Raster Settings"); + panel_list.add_item("Input Configuration"); + panel_list.add_item("Cheat Code Editor"); + panel_list.add_item("Advanced"); + + attach(panel_list, 5, 5); + attach(window_raster_settings, 160, 5); + attach(window_input_config, 160, 5); + attach(window_cheat_editor, 160, 5); + attach(window_advanced, 160, 5); + + on_close = bind(&SettingsWindow::close, this); + panel_list.on_change = bind(&SettingsWindow::list_change, this); + + panel_list.set_selection(0); +} + +uintptr_t SettingsWindow::close(Event) { + hide(); + return false; +} + +uintptr_t SettingsWindow::list_change(Event) { + window_raster_settings.hide(); + window_input_config.hide(); + window_cheat_editor.hide(); + window_advanced.hide(); + + switch(panel_list.get_selection()) { + case 0: window_raster_settings.show(); break; + case 1: window_input_config.show(); break; + case 2: window_cheat_editor.show(); break; + case 3: window_advanced.show(); break; + } + + panel_list.focus(); + return true; +} + +void SettingsWindow::show() { + Window::show(); + panel_list.focus(); +} diff --git a/src/ui/miu/settings/ui_settings.h b/src/ui/miu/settings/ui_settings.h new file mode 100644 index 00000000..968ee741 --- /dev/null +++ b/src/ui/miu/settings/ui_settings.h @@ -0,0 +1,9 @@ +class SettingsWindow : public Window { +public: + Listbox panel_list; + + void setup(); + void show(); + uintptr_t close(Event); + uintptr_t list_change(Event); +} window_settings; diff --git a/src/ui/miu/ui.cpp b/src/ui/miu/ui.cpp new file mode 100644 index 00000000..93bb4e5c --- /dev/null +++ b/src/ui/miu/ui.cpp @@ -0,0 +1,114 @@ +#include "ui_main.cpp" +#include "ui_about.cpp" + +#include "loader/ui_bsxloader.cpp" +#include "loader/ui_stloader.cpp" + +#include "settings/ui_settings.cpp" +#include "settings/ui_rastersettings.cpp" +#include "settings/ui_inputconfig.cpp" +#include "settings/ui_cheateditor.cpp" +#include "settings/ui_advanced.cpp" + +#if defined(PLATFORM_WIN) + #include "../vai/video/video.direct3d.h" + #include "../vai/video/video.directdraw.h" + #include "../vai/video/video.gdi.h" + #include "../vai/audio/audio.directsound.h" + #include "../vai/input/input.directinput.h" +#elif defined(PLATFORM_X) + #include "../vai/video/video.xv.h" + #include "../vai/video/video.gtk.h" + #include "../vai/audio/audio.ao.h" + #include "../vai/input/input.x.h" +#endif + +void ui_init() { + window_main.setup(); + window_about.setup(); + + window_bsxloader.setup(); + window_stloader.setup(); + + window_raster_settings.setup(); + window_input_config.setup(); + window_cheat_editor.setup(); + window_advanced.setup(); + window_settings.setup(); + + event::update_video_settings(); //call first time to resize main window and update menubar + window_main.show(); + while(miu().pending()) miu().run(); + +#if defined(PLATFORM_WIN) + if(config::system.video == "none") { + uiVideo = new Video(); + } else if(config::system.video == "gdi") { + uiVideo = new VideoGDI(); + } else if(config::system.video == "directdraw") { + uiVideo = new VideoDD(); + } else { + uiVideo = new VideoD3D(); + } + + if(config::system.audio == "none") { + uiAudio = new Audio(); + } else { + uiAudio = new AudioDS(); + } + + if(config::system.input == "none") { + uiInput = new Input(); + } else { + uiInput = new InputDI(); + } +#elif defined(PLATFORM_X) + if(config::system.video == "none") { + uiVideo = new Video(); + } else if(config::system.video == "gtk") { + uiVideo = new VideoGTK(); + } else { + uiVideo = new VideoXv(); + } + + if(config::system.audio == "none") { + uiAudio = new Audio(); + } else { + uiAudio = new AudioAO(); + } + + if(config::system.input == "none") { + uiInput = new Input(); + } else { + uiInput = new InputX(); + } +#endif + +//needed only by VideoGDI (default is RGB565) + if(config::system.video == "gdi") snes.set_video_pixel_format(SNES::PIXELFORMAT_RGB555); + + uiVideo->set(Video::Handle, window_main.view.handle()); + uiVideo->set(Video::Synchronize, false); + uiAudio->set(Audio::Handle, window_main.handle()); + uiAudio->set(Audio::Synchronize, config::system.regulate_speed); + uiAudio->set(Audio::Frequency, 32000); + uiInput->set(Input::Handle, window_main.handle()); + + uiVideo->init(); + uiAudio->init(); + uiInput->init(); + + event::update_video_settings(); //call second time to update uiVideo->settings +} + +void ui_term() { + window_main.hide(); + + uiVideo->term(); + uiAudio->term(); + uiInput->term(); + + safe_delete(uiVideo); + safe_delete(uiAudio); + safe_delete(uiInput); +} diff --git a/src/ui/lui/ui.h b/src/ui/miu/ui.h similarity index 85% rename from src/ui/lui/ui.h rename to src/ui/miu/ui.h index eb1470e8..983ad5ea 100644 --- a/src/ui/lui/ui.h +++ b/src/ui/miu/ui.h @@ -5,7 +5,6 @@ #include "loader/ui_stloader.h" #include "settings/ui_settings.h" -#include "settings/ui_videosettings.h" #include "settings/ui_rastersettings.h" #include "settings/ui_inputconfig.h" #include "settings/ui_cheateditor.h" diff --git a/src/ui/lui/ui_about.cpp b/src/ui/miu/ui_about.cpp similarity index 53% rename from src/ui/lui/ui_about.cpp rename to src/ui/miu/ui_about.cpp index 5be7bdad..51742a19 100644 --- a/src/ui/lui/ui_about.cpp +++ b/src/ui/miu/ui_about.cpp @@ -7,17 +7,15 @@ const char AboutWindow::about_text[4096] = "" " anomie, blargg, DMV27, GIGO, kode54, Nach,\n" " Overload, Richard Bannister, TRAC, zones"; +uintptr_t AboutWindow::close(Event) { + hide(); + return false; +} + void AboutWindow::setup() { - create(ui::Window::Center, 400, 200, "About bsnes ..."); + create(Window::AutoCenter, 400, 200, "About bsnes ..."); + about.create(0, 390, 190, about_text); + attach(about, 5, 5); - about.create(*this, 0, 5, 5, 390, 190, about_text); -} - -bool AboutWindow::message(uint id, uintptr_t param) { - if(id == ui::Message::Close) { - hide(); - return false; - } - - return true; + on_close = bind(&AboutWindow::close, this); } diff --git a/src/ui/miu/ui_about.h b/src/ui/miu/ui_about.h new file mode 100644 index 00000000..04707d76 --- /dev/null +++ b/src/ui/miu/ui_about.h @@ -0,0 +1,8 @@ +class AboutWindow : public Window { +public: + Label about; + static const char about_text[4096]; + + void setup(); + uintptr_t close(Event); +} window_about; diff --git a/src/ui/miu/ui_main.cpp b/src/ui/miu/ui_main.cpp new file mode 100644 index 00000000..9015ecb8 --- /dev/null +++ b/src/ui/miu/ui_main.cpp @@ -0,0 +1,343 @@ +bool MainWindow::input_ready() { + return focused() == true; //only allow SNES to recognize input when main window is focused +} + +uintptr_t MainWindow::event(Event e) { + if(e.type == Event::Close) { + _term_ = true; + hide(); + return false; + } + + if(e.type == Event::Tick) { + if(e.widget == &menu_file_load) { + event::load_rom(); + } + + if(e.widget == &menu_file_load_bsx) { + window_bsxloader.mode = BSXLoaderWindow::ModeBSX; + window_bsxloader.set_text("Load BS-X Cartridge"); + window_bsxloader.tbase.set_text(config::path.bsx); + window_bsxloader.focus(); + } + + if(e.widget == &menu_file_load_bsc) { + window_bsxloader.mode = BSXLoaderWindow::ModeBSC; + window_bsxloader.set_text("Load BS-X Slotted Cartridge"); + window_bsxloader.tbase.set_text(""); + window_bsxloader.focus(); + } + + if(e.widget == &menu_file_load_st) { + window_stloader.tbase.set_text(config::path.st); + window_stloader.focus(); + } + + if(e.widget == &menu_file_unload) { + event::unload_rom(); + } + + if(e.widget == &menu_file_reset) { + event::reset(); + } + + if(e.widget == &menu_file_power) { + event::power(); + } + + if(e.widget == &menu_file_exit) { + event(Event(Event::Close)); + } + + if(locked == false) { + //set locked to true to update below menu item check statuses without triggering events + 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_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_swntsc) { event::update_software_filter(1); } + if(e.widget == &menu_settings_videofilter_swhq2x) { event::update_software_filter(2); } + if(e.widget == &menu_settings_videofilter_swscale2x) { event::update_software_filter(3); } + + if(e.widget == &menu_settings_videoframeskip_0) { config::video.frameskip = 0; } + if(e.widget == &menu_settings_videoframeskip_1) { config::video.frameskip = 1; } + if(e.widget == &menu_settings_videoframeskip_2) { config::video.frameskip = 2; } + if(e.widget == &menu_settings_videoframeskip_3) { config::video.frameskip = 3; } + if(e.widget == &menu_settings_videoframeskip_4) { config::video.frameskip = 4; } + if(e.widget == &menu_settings_videoframeskip_5) { config::video.frameskip = 5; } + if(e.widget == &menu_settings_videoframeskip_6) { config::video.frameskip = 6; } + if(e.widget == &menu_settings_videoframeskip_7) { config::video.frameskip = 7; } + if(e.widget == &menu_settings_videoframeskip_8) { config::video.frameskip = 8; } + if(e.widget == &menu_settings_videoframeskip_9) { config::video.frameskip = 9; } + + if(e.widget == &menu_settings_mute) { + config::snes.mute = menu_settings_mute.checked(); + } + + if(e.widget == &menu_settings_speedreg_enable) { + config::system.regulate_speed = menu_settings_speedreg_enable.checked(); + if(uiAudio) uiAudio->set(Audio::Synchronize, config::system.regulate_speed); + } + + if(e.widget == &menu_settings_speedreg_slowest) { event::update_speed_regulation(1); } + if(e.widget == &menu_settings_speedreg_slow) { event::update_speed_regulation(2); } + if(e.widget == &menu_settings_speedreg_normal) { event::update_speed_regulation(3); } + if(e.widget == &menu_settings_speedreg_fast) { event::update_speed_regulation(4); } + if(e.widget == &menu_settings_speedreg_fastest) { event::update_speed_regulation(5); } + } + + if(e.widget == &menu_settings_config) { window_settings.show(); } + + if(e.widget == &menu_misc_logaudio) { + (menu_misc_logaudio.checked() == true) ? snes.log_audio_enable() : snes.log_audio_disable(); + } + + if(e.widget == &menu_misc_showfps) { + config::misc.show_frame_counter = menu_misc_showfps.checked(); + if(config::misc.show_frame_counter == false) { + set_text(BSNES_TITLE); + } + } + + if(e.widget == &menu_misc_about) { + window_about.focus(); + } + } + + return true; +} + +uintptr_t MainWindow::block(Event) { + if(uiAudio) uiAudio->clear_audio(); + return true; +} + +uintptr_t MainWindow::keydown(Event e) { + if(e.param == keymap::esc) { event::toggle_menu(); } + if(e.param == keymap::f11) { event::toggle_fullscreen(); } +} + +void MainWindow::setup() { + snesinterface.input_ready = bind(&MainWindow::input_ready, this); + locked = true; + + create(Window::AutoCenter, 256, 224, BSNES_TITLE); + set_background_color(0, 0, 0); + +MenuRadioItemGroup group; + attach(menu_file.create("File")); + menu_file.attach(menu_file_load.create("Load Cartridge ...")); + menu_file.attach(menu_file_load_special.create("Load Special")); + menu_file_load_special.attach(menu_file_load_bsx.create("Load BS-X Cartridge ...")); + menu_file_load_special.attach(menu_file_load_bsc.create("Load BS-X Slotted Cartridge ...")); + menu_file_load_special.attach(menu_file_load_st.create("Load ST Cartridge ...")); + menu_file.attach(menu_file_unload.create("Unload Cartridge")); + menu_file.attach(menu_file_sep1.create()); + menu_file.attach(menu_file_reset.create("Reset System")); + menu_file.attach(menu_file_power.create("Power Cycle System")); + menu_file.attach(menu_file_sep2.create()); + menu_file.attach(menu_file_exit.create("Exit")); + + attach(menu_settings.create("Settings")); + menu_settings.attach(menu_settings_videomode.create("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, "Scale 1x")); + menu_settings_videomode.attach(menu_settings_videomode_2x.create(group, "Scale 2x")); + menu_settings_videomode.attach(menu_settings_videomode_3x.create(group, "Scale 3x")); + menu_settings_videomode.attach(menu_settings_videomode_4x.create(group, "Scale 4x")); + menu_settings_videomode.attach(menu_settings_videomode_5x.create(group, "Scale 5x")); + group.reset(); + menu_settings_videomode.attach(menu_settings_videomode_sep1.create()); + menu_settings_videomode.attach(menu_settings_videomode_aspect_correction.create("Correct Aspect Ratio")); + 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, "NTSC")); + menu_settings_videomode.attach(menu_settings_videomode_pal.create(group, "PAL")); + group.reset(); + + menu_settings.attach(menu_settings_videofilter.create("Video Filter")); + group.add(&menu_settings_videofilter_hwpoint); + group.add(&menu_settings_videofilter_hwlinear); + menu_settings_videofilter.attach(menu_settings_videofilter_hwpoint.create(group, "Point")); + menu_settings_videofilter.attach(menu_settings_videofilter_hwlinear.create(group, "Linear")); + group.reset(); + menu_settings_videofilter.attach(menu_settings_videofilter_sep1.create()); + group.add(&menu_settings_videofilter_swnone); + group.add(&menu_settings_videofilter_swntsc); + group.add(&menu_settings_videofilter_swhq2x); + group.add(&menu_settings_videofilter_swscale2x); + menu_settings_videofilter.attach(menu_settings_videofilter_swnone.create(group, "None")); + menu_settings_videofilter.attach(menu_settings_videofilter_swntsc.create(group, "NTSC")); + menu_settings_videofilter.attach(menu_settings_videofilter_swhq2x.create(group, "HQ2x")); + menu_settings_videofilter.attach(menu_settings_videofilter_swscale2x.create(group, "Scale2x")); + group.reset(); + + menu_settings.attach(menu_settings_videoframeskip.create("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, "0")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_sep1.create()); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_1.create(group, "1")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_2.create(group, "2")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_3.create(group, "3")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_4.create(group, "4")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_5.create(group, "5")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_6.create(group, "6")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_7.create(group, "7")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_8.create(group, "8")); + menu_settings_videoframeskip.attach(menu_settings_videoframeskip_9.create(group, "9")); + group.reset(); + + menu_settings.attach(menu_settings_sep1.create()); + menu_settings.attach(menu_settings_mute.create("Mute Sound Output")); + menu_settings.attach(menu_settings_sep2.create()); + + menu_settings.attach(menu_settings_speedreg.create("Speed Regulation")); + menu_settings_speedreg.attach(menu_settings_speedreg_enable.create("Enable")); + menu_settings_speedreg.attach(menu_settings_speedreg_sep1.create()); + group.add(&menu_settings_speedreg_slowest); + group.add(&menu_settings_speedreg_slow); + group.add(&menu_settings_speedreg_normal); + group.add(&menu_settings_speedreg_fast); + group.add(&menu_settings_speedreg_fastest); + menu_settings_speedreg.attach(menu_settings_speedreg_slowest.create(group, "Slowest")); + menu_settings_speedreg.attach(menu_settings_speedreg_slow.create(group, "Slow")); + menu_settings_speedreg.attach(menu_settings_speedreg_normal.create(group, "Normal")); + menu_settings_speedreg.attach(menu_settings_speedreg_fast.create(group, "Fast")); + menu_settings_speedreg.attach(menu_settings_speedreg_fastest.create(group, "Fastest")); + group.reset(); + + menu_settings.attach(menu_settings_sep3.create()); + menu_settings.attach(menu_settings_config.create("Configuration ...")); + + attach(menu_misc.create("Misc")); + menu_misc.attach(menu_misc_logaudio.create("Log Audio Data")); + menu_misc.attach(menu_misc_showfps.create("Show FPS")); + menu_misc.attach(menu_misc_sep1.create()); + menu_misc.attach(menu_misc_about.create("About ...")); + + view.create(0, 256, 224); + attach(view, 0, 0); + + on_close = bind(&MainWindow::event, this); + on_block = bind(&MainWindow::block, this); + on_keydown = bind(&MainWindow::keydown, this); + + menu_file_load.on_tick = + menu_file_load_bsx.on_tick = + menu_file_load_bsc.on_tick = + menu_file_load_st.on_tick = + menu_file_unload.on_tick = + menu_file_reset.on_tick = + menu_file_power.on_tick = + menu_file_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_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_swntsc.on_tick = + menu_settings_videofilter_swhq2x.on_tick = + menu_settings_videofilter_swscale2x.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_speedreg_enable.on_tick = + menu_settings_speedreg_slowest.on_tick = + menu_settings_speedreg_slow.on_tick = + menu_settings_speedreg_normal.on_tick = + menu_settings_speedreg_fast.on_tick = + menu_settings_speedreg_fastest.on_tick = + menu_settings_config.on_tick = + + menu_misc_logaudio.on_tick = + menu_misc_showfps.on_tick = + menu_misc_about.on_tick = + + bind(&MainWindow::event, this); +} + +void MainWindow::update_menu_settings() { + locked = true; + event::load_video_settings(); + + 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); + + 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_swntsc.check(); break; + case 2: menu_settings_videofilter_swhq2x.check(); break; + case 3: menu_settings_videofilter_swscale2x.check(); break; + } + + menu_settings_mute.check(config::snes.mute); + + menu_settings_speedreg_enable.check(config::system.regulate_speed); + menu_settings_speedreg_normal.check(); + + menu_misc_showfps.check(config::misc.show_frame_counter); + + locked = false; +} diff --git a/src/ui/miu/ui_main.h b/src/ui/miu/ui_main.h new file mode 100644 index 00000000..c47f1e83 --- /dev/null +++ b/src/ui/miu/ui_main.h @@ -0,0 +1,78 @@ +class MainWindow : public Window { +public: + MenuGroup menu_file; + MenuItem menu_file_load; + MenuGroup menu_file_load_special; + MenuItem menu_file_load_bsx; + MenuItem menu_file_load_bsc; + MenuItem menu_file_load_st; + MenuItem menu_file_unload; + MenuSeparator menu_file_sep1; + MenuItem menu_file_reset; + MenuItem menu_file_power; + MenuSeparator menu_file_sep2; + MenuItem menu_file_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; + 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_swntsc; + MenuRadioItem menu_settings_videofilter_swhq2x; + MenuRadioItem menu_settings_videofilter_swscale2x; + MenuGroup menu_settings_videoframeskip; + MenuRadioItem menu_settings_videoframeskip_0; + MenuSeparator menu_settings_videoframeskip_sep1; + 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_speedreg; + MenuCheckItem menu_settings_speedreg_enable; + MenuSeparator menu_settings_speedreg_sep1; + MenuRadioItem menu_settings_speedreg_slowest; + MenuRadioItem menu_settings_speedreg_slow; + MenuRadioItem menu_settings_speedreg_normal; + MenuRadioItem menu_settings_speedreg_fast; + MenuRadioItem menu_settings_speedreg_fastest; + MenuSeparator menu_settings_sep3; + MenuItem menu_settings_config; + + MenuGroup menu_misc; + MenuCheckItem menu_misc_logaudio; + MenuCheckItem menu_misc_showfps; + MenuSeparator menu_misc_sep1; + MenuItem menu_misc_about; + + Canvas view; + + bool locked; + + bool input_ready(); + void setup(); + void update_menu_settings(); + uintptr_t event(Event); + uintptr_t block(Event); + uintptr_t keydown(Event); +} window_main; diff --git a/src/ui/sdl/bsnes.cpp b/src/ui/sdl/bsnes.cpp deleted file mode 100644 index ea4d5f87..00000000 --- a/src/ui/sdl/bsnes.cpp +++ /dev/null @@ -1,66 +0,0 @@ -void bSNES::set_status(uint32 new_status) { run_status = new_status; } -uint32 bSNES::get_status() { return run_status; } - -void bSNES::run() { - switch(run_status) { - case RUN: - SNES::runtoframe(); - return; - case STOP: - break; - } -} - -void bSNES::video_run() { - if(r_ppu->status.frames_updated) { - char s[512], t[512]; - r_ppu->status.frames_updated = false; - sprintf(s, "%s : %d fps", BSNES_TITLE, r_ppu->status.frames_executed); - SDL_WM_SetCaption(s, 0); - } - - render(); -} - -void bSNES::sound_run(uint32 data) { - uiAudio->run(data); -} - -uint16 *bSNES::video_lock(uint &pitch) { - if(SDL_MUSTLOCK(screen)) { - SDL_LockSurface(screen); - } - if(SDL_MUSTLOCK(backbuffer)) { - SDL_LockSurface(backbuffer); - } - - pitch = backbuffer->pitch; - return (uint16*)backbuffer->pixels; -} - -void bSNES::video_unlock() { - if(SDL_MUSTLOCK(backbuffer)) { - SDL_UnlockSurface(backbuffer); - } - if(SDL_MUSTLOCK(screen)) { - SDL_UnlockSurface(screen); - } -} - -/*********************** - *** Input functions *** - ***********************/ - -void bSNES::poll_input(uint8 type) { - uiInput->poll(); -} - -bool bSNES::get_input_status(uint8 device, uint8 button) { - return uiInput->get_status(device, button); -} - -void bSNES::notify(uint32 message, uint32 param1, uint32 param2) {} - -bSNES::bSNES() { - run_status = RUN; -} diff --git a/src/ui/sdl/bsnes.h b/src/ui/sdl/bsnes.h deleted file mode 100644 index 75abfa7c..00000000 --- a/src/ui/sdl/bsnes.h +++ /dev/null @@ -1,23 +0,0 @@ -class bSNES : public SNES { -private: -uint32 run_status; - -public: -enum { STOP = 0, RUN }; - void run(); - void video_run(); - void sound_run(uint32 data); - - uint16 *video_lock(uint &data); - void video_unlock(); - - void set_status(uint32 new_status); - uint32 get_status(); - -//input functions - void poll_input(uint8 type); - bool get_input_status(uint8 device, uint8 button); - - void notify(uint32 message, uint32 param1 = 0, uint32 param2 = 0); - bSNES(); -} bsnes; diff --git a/src/ui/sdl/main.cpp b/src/ui/sdl/main.cpp deleted file mode 100644 index af7ea1d4..00000000 --- a/src/ui/sdl/main.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "main.h" - -#include "bsnes.h" -#include "render.cpp" -#include "bsnes.cpp" - -#include "../video/sdl.h" -#include "../video/sdl.cpp" - -#if defined(PLATFORM_WIN) - #include "../audio/dsound.h" - #include "../audio/dsound.cpp" -#elif defined(PLATFORM_X) - #include "../audio/ao.h" - #include "../audio/ao.cpp" -#endif - -#include "../input/sdl.h" -#include "../input/sdl.cpp" - -void alert(char *s, ...) { -char str[4096]; -va_list args; - va_start(args, s); - vsprintf(str, s, args); - va_end(args); -#ifdef PLATFORM_WIN - MessageBox(0, str, "bsnes", MB_OK); -#else - fprintf(stdout, "%s\r\n", str); -#endif -} - -void dprintf(char *s, ...) { -char str[4096]; -va_list args; - va_start(args, s); - vsprintf(str, s, args); - va_end(args); - fprintf(stdout, "%s\r\n", str); -} - -void dprintf(uint source, char *s, ...) { -char str[4096]; -va_list args; - va_start(args, s); - vsprintf(str, s, args); - va_end(args); - fprintf(stdout, "[%d]: %s\r\n", source, str); -} - -void center_window() { -#ifdef PLATFORM_WIN -HWND hwnd; -RECT rc; -int x, y; - hwnd = FindWindow(0, BSNES_TITLE); - GetWindowRect(hwnd, &rc); - x = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) >> 1; - y = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) >> 1; - SetWindowPos(hwnd, HWND_TOPMOST, x, y, 0, 0, SWP_NOSIZE); -#endif -} - -#ifdef PLATFORM_WIN -int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { -int argc = __argc; -char **argv = __argv; - SDL_SetModuleHandle(GetModuleHandle(0)); -#else -int main(int argc, char *argv[]) { -#endif - -SDL_Event event; - - if(argc < 2) { - alert("Usage: bsnes_sdl "); - return 0; - } - - config_file.load("bsnes_sdl.cfg"); - - init_snes(); - - uiVideo = new VideoSDL(); -#if defined(PLATFORM_WIN) - uiAudio = new AudioDS(); -#elif defined(PLATFORM_X) - uiAudio = new AudioAO(); - ((AudioAO*)uiAudio)->set_driver("oss"); -#endif - uiInput = new InputSDL(); - - uiVideo->init(); - uiAudio->init(); - uiInput->init(); - - cartridge.load_begin(Cartridge::CART_NORMAL); - cartridge.load(argv[1]); - cartridge.load_end(); - - SDL_Init(SDL_INIT_VIDEO); - atexit(SDL_Quit); - - screen_rect.x = 0; - screen_rect.y = 0; - screen_rect.w = 256; - screen_rect.h = 224; - - screen = SDL_SetVideoMode(screen_rect.w, screen_rect.h, 16, - SDL_HWSURFACE | (0 ? SDL_FULLSCREEN : 0)); - if(!screen) { alert("Failed to initialize SDL"); goto _end; } - - backbuffer = SDL_CreateRGBSurface(SDL_HWSURFACE, 512, 448, 16, 0xf800, 0x07e0, 0x001f, 0x0000); - if(!backbuffer) { alert("Failed to initialize SDL"); goto _end; } - - SDL_WM_SetCaption(BSNES_TITLE, 0); - center_window(); - - snes.power(); - bsnes.set_status(bSNES::RUN); - -int cursor_status; - while(1) { - bsnes.run(); - while(SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_KEYUP: - switch(event.key.keysym.sym) { - case SDLK_ESCAPE: - goto _end; - case SDLK_BACKSPACE: - //snes->capture_screenshot(); - break; - case SDLK_F10: //toggle cursor display - cursor_status = (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) ? SDL_DISABLE : SDL_ENABLE; - SDL_ShowCursor(cursor_status); - break; - case SDLK_F11: //only supported on X11 - SDL_WM_ToggleFullScreen(screen); - break; - } - break; - case SDL_QUIT: - goto _end; - } - } - } - -_end: - config_file.save("bsnes_sdl.cfg"); - cartridge.unload(); - uiVideo->term(); - uiAudio->term(); - uiInput->term(); - safe_delete(uiVideo); - safe_delete(uiAudio); - safe_delete(uiInput); - term_snes(); - - return 0; -} diff --git a/src/ui/sdl/main.h b/src/ui/sdl/main.h deleted file mode 100644 index ff22ab8a..00000000 --- a/src/ui/sdl/main.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef PLATFORM_WIN - #include -#endif - -#include "SDL.h" - -SDL_Surface *screen, *backbuffer; -SDL_Rect screen_rect; diff --git a/src/ui/sdl/render.cpp b/src/ui/sdl/render.cpp deleted file mode 100644 index 3c28d180..00000000 --- a/src/ui/sdl/render.cpp +++ /dev/null @@ -1,18 +0,0 @@ -void render() { -SNES::video_info vi; - snes.get_video_info(&vi); - -SDL_Rect rect; - rect.x = 0; - rect.y = (vi.height == 224) ? 1 : 2; - rect.w = vi.width; - rect.h = (vi.height == 224) ? 223 : 446; - -//documentation says not to use this, but it's rather ridiculous that a graphics -//library wouldn't support simple image scaling... so let's use it anyway and see -//what happens... - SDL_SoftStretch(backbuffer, &rect, screen, &screen_rect); -//SDL_BlitSurface(backbuffer, &rect, screen, &screen_rect); - - SDL_UpdateRect(screen, screen_rect.x, screen_rect.y, screen_rect.w, screen_rect.h); -} diff --git a/src/ui/vai/audio.h b/src/ui/vai/audio.h new file mode 100644 index 00000000..8d42a948 --- /dev/null +++ b/src/ui/vai/audio.h @@ -0,0 +1,27 @@ +#ifndef AUDIO_H +#define AUDIO_H + +#include "../../lib/bbase.h" + +class Audio { +public: + enum Setting { + Handle, + Synchronize, + Frequency, + }; + + virtual bool cap(Setting) { return false; } + virtual uintptr_t get(Setting) { return false; } + virtual bool set(Setting, uintptr_t) { return false; } + + virtual void sample(uint16 left, uint16 right) {} + virtual void clear_audio() {} + virtual void init() {} + virtual void term() {} + + Audio() {} + virtual ~Audio() {} +}; + +#endif //ifndef AUDIO_H diff --git a/src/ui/vai/audio/audio.ao.cpp b/src/ui/vai/audio/audio.ao.cpp new file mode 100644 index 00000000..caca1c22 --- /dev/null +++ b/src/ui/vai/audio/audio.ao.cpp @@ -0,0 +1,85 @@ +#include "audio.ao.h" + +#include + +class pAudioAO { +public: + AudioAO &self; + int driver_id; + ao_sample_format driver_format; + ao_device *audio_device; + + struct { + uint frequency; + } settings; + + bool cap(Audio::Setting setting) { + if(setting == Audio::Frequency) return true; + return false; + } + + uintptr_t get(Audio::Setting setting) { + if(setting == Audio::Frequency) return settings.frequency; + return false; + } + + bool set(Audio::Setting setting, uintptr_t param) { + if(setting == Audio::Frequency) { + settings.frequency = param; + if(audio_device) { + term(); + init(); + } + return true; + } + return false; + } + + void sample(uint16 l_sample, uint16 r_sample) { + uint32 samp = (l_sample << 0) + (r_sample << 16); + ao_play(audio_device, (char*)&samp, 4); //This may need to be byte swapped for Big Endian + } + + void init() { + driver_id = ao_default_driver_id(); //ao_driver_id((const char*)driver) + if(driver_id < 0) driver_id = ao_default_driver_id(); //fallback on default if driver doesn't exist + driver_format.bits = 16; + driver_format.channels = 2; + driver_format.rate = settings.frequency; + driver_format.byte_format = AO_FMT_LITTLE; + + audio_device = ao_open_live(driver_id, &driver_format, 0); + if(audio_device) { + ao_info *di = ao_driver_info(driver_id); + } else { + printf("libao: failed to open audio device.\n"); + } + } + + void term() { + if(audio_device) { + ao_close(audio_device); + audio_device = 0; + } + } + + pAudioAO(AudioAO &self_) : self(self_) { + settings.frequency = 22050; + audio_device = 0; + ao_initialize(); + } + + ~pAudioAO() { + term(); + //ao_shutdown(); //FIXME: this is causing a segfault for some reason when called ... + } +}; + +bool AudioAO::cap(Setting setting) { return p.cap(setting); } +uintptr_t AudioAO::get(Setting setting) { return p.get(setting); } +bool AudioAO::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +void AudioAO::sample(uint16 l_sample, uint16 r_sample) { p.sample(l_sample, r_sample); } +void AudioAO::init() { p.init(); } +void AudioAO::term() { p.term(); } +AudioAO::AudioAO() : p(*new pAudioAO(*this)) {} +AudioAO::~AudioAO() { delete &p; } diff --git a/src/ui/vai/audio/audio.ao.h b/src/ui/vai/audio/audio.ao.h new file mode 100644 index 00000000..2037ea4f --- /dev/null +++ b/src/ui/vai/audio/audio.ao.h @@ -0,0 +1,25 @@ +#ifndef AUDIO_AO_H +#define AUDIO_AO_H + +#include "../audio.h" + +class pAudioAO; + +class AudioAO : public Audio { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + void sample(uint16 left, uint16 right); + void init(); + void term(); + + AudioAO(); + ~AudioAO(); + +private: + pAudioAO &p; +}; + +#endif //ifndef AUDIO_AO_H diff --git a/src/ui/vai/audio/audio.directsound.cpp b/src/ui/vai/audio/audio.directsound.cpp new file mode 100644 index 00000000..a27eed9b --- /dev/null +++ b/src/ui/vai/audio/audio.directsound.cpp @@ -0,0 +1,177 @@ +#include "audio.directsound.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +class pAudioDS { +public: + AudioDS &self; + LPDIRECTSOUND ds; + LPDIRECTSOUNDBUFFER dsb_p, dsb_b; + DSBUFFERDESC dsbd; + WAVEFORMATEX wfx; + + struct { + uint32 *buffer; + uint buffer_pos, ring_pos; + uint buffer_size, ring_size; + } data; + + struct { + HWND handle; + bool synchronize; + uint frequency; + uint latency; + } settings; + + bool cap(Audio::Setting setting) { + if(setting == Audio::Handle) return true; + if(setting == Audio::Synchronize) return true; + if(setting == Audio::Frequency) return true; + return false; + } + + uintptr_t get(Audio::Setting setting) { + if(setting == Audio::Handle) return (uintptr_t)settings.handle; + if(setting == Audio::Synchronize) return settings.synchronize; + if(setting == Audio::Frequency) return settings.frequency; + return false; + } + + bool set(Audio::Setting setting, uintptr_t param) { + if(setting == Audio::Handle) { + settings.handle = (HWND)param; + return true; + } + if(setting == Audio::Synchronize) { + settings.synchronize = param; + return true; + } + if(setting == Audio::Frequency) { + settings.frequency = param; + settings.latency = param / 40; + if(ds) init(); //reinitialize only if previously initialized + return true; + } + return false; + } + + void sample(uint16 l_sample, uint16 r_sample) { + data.buffer[data.buffer_pos++] = (l_sample << 0) + (r_sample << 16); + if(data.buffer_pos < settings.latency) return; + + DWORD ring_pos, pos, size; + for(;;) { + dsb_b->GetCurrentPosition(&pos, 0); + ring_pos = pos / data.ring_size; + if(settings.synchronize == false || ring_pos != data.ring_pos) break; + Sleep(1); + } + + data.ring_pos = ring_pos; + void *output; + if(dsb_b->Lock(((data.ring_pos + 2) % 3) * data.ring_size, data.ring_size, + &output, &size, 0, 0, 0) == DS_OK) { + memcpy(output, data.buffer, data.ring_size); + dsb_b->Unlock(output, size, 0, 0); + } + + data.buffer_pos = 0; + } + + void clear_audio() { + data.buffer_pos = 0; + data.ring_pos = 0; + if(data.buffer) memset(data.buffer, 0, data.buffer_size); + if(!dsb_b) return; + + dsb_b->Stop(); + dsb_b->SetCurrentPosition(0); + + DWORD size; + void *output; + dsb_b->Lock(0, data.ring_size * 3, &output, &size, 0, 0, 0); + memset(output, 0, size); + dsb_b->Unlock(output, size, 0, 0); + + dsb_b->Play(0, 0, DSBPLAY_LOOPING); + } + + void init() { + clear_audio(); + term(); + + data.ring_size = settings.latency * sizeof(uint32); + data.buffer_size = data.ring_size * 16; + data.buffer = (uint32*)malloc(data.buffer_size); + data.buffer_pos = 0; + + DirectSoundCreate(0, &ds, 0); + ds->SetCooperativeLevel(settings.handle, DSSCL_PRIORITY); + + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = 0; + ds->CreateSoundBuffer(&dsbd, &dsb_p, 0); + + memset(&wfx, 0, sizeof(wfx)); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; + wfx.nSamplesPerSec = settings.frequency; + wfx.wBitsPerSample = 16; + wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + dsb_p->SetFormat(&wfx); + + memset(&dsbd, 0, sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY | + DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE; + dsbd.dwBufferBytes = data.ring_size * 3; + dsbd.guid3DAlgorithm = GUID_NULL; + dsbd.lpwfxFormat = &wfx; + ds->CreateSoundBuffer(&dsbd, &dsb_b, 0); + dsb_b->SetFrequency(settings.frequency); + dsb_b->SetCurrentPosition(0); + + clear_audio(); + } + + void term() { + safe_free(data.buffer); + + if(dsb_b) { dsb_b->Stop(); dsb_b->Release(); dsb_b = 0; } + if(dsb_p) { dsb_p->Stop(); dsb_p->Release(); dsb_p = 0; } + if(ds) { ds->Release(); ds = 0; } + } + + pAudioDS(AudioDS &self_) : self(self_) { + ds = 0; + dsb_p = 0; + dsb_b = 0; + + data.buffer = 0; + data.buffer_pos = 0; + data.ring_pos = 0; + data.buffer_size = 0; + data.ring_size = 0; + + settings.handle = GetDesktopWindow(); + settings.synchronize = false; + settings.frequency = 22050; + settings.latency = settings.frequency / 40; + } +}; + +bool AudioDS::cap(Setting setting) { return p.cap(setting); } +uintptr_t AudioDS::get(Setting setting) { return p.get(setting); } +bool AudioDS::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +void AudioDS::sample(uint16 l_sample, uint16 r_sample) { p.sample(l_sample, r_sample); } +void AudioDS::clear_audio() { p.clear_audio(); } +void AudioDS::init() { p.init(); } +void AudioDS::term() { p.term(); } +AudioDS::AudioDS() : p(*new pAudioDS(*this)) {} +AudioDS::~AudioDS() { delete &p; } diff --git a/src/ui/vai/audio/audio.directsound.h b/src/ui/vai/audio/audio.directsound.h new file mode 100644 index 00000000..0d2e4f41 --- /dev/null +++ b/src/ui/vai/audio/audio.directsound.h @@ -0,0 +1,26 @@ +#ifndef AUDIO_DIRECTSOUND_H +#define AUDIO_DIRECTSOUND_H + +#include "../audio.h" + +class pAudioDS; + +class AudioDS : public Audio { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + void sample(uint16 left, uint16 right); + void clear_audio(); + void init(); + void term(); + + AudioDS(); + ~AudioDS(); + +private: + pAudioDS &p; +}; + +#endif //ifndef AUDIO_DIRECTSOUND_H diff --git a/src/ui/vai/input.h b/src/ui/vai/input.h new file mode 100644 index 00000000..fd9d4199 --- /dev/null +++ b/src/ui/vai/input.h @@ -0,0 +1,29 @@ +#ifndef INPUT_H +#define INPUT_H + +#include "../../lib/bbase.h" +#include "../../lib/bkeymap.h" + +class Input { +public: + enum Setting { + Handle, + }; + + virtual bool cap(Setting) { return false; } + virtual uintptr_t get(Setting) { return false; } + virtual bool set(Setting, uintptr_t) { return false; } + + virtual bool key_down(uint16 key) { return false; } + virtual bool key_up (uint16 key) { return !key_down(key); } + + virtual void clear_input() {} + virtual void poll() {} + virtual void init() {} + virtual void term() {} + + Input() {} + virtual ~Input() {} +}; + +#endif //ifndef INPUT_H diff --git a/src/ui/vai/input/input.directinput.cpp b/src/ui/vai/input/input.directinput.cpp new file mode 100644 index 00000000..ff1b5899 --- /dev/null +++ b/src/ui/vai/input/input.directinput.cpp @@ -0,0 +1,293 @@ +#include "input.directinput.h" + +#define WIN32_LEAN_AND_MEAN +#include + +#define DIRECTINPUT_VERSION 0x0800 +#define DIRECTINPUT_JOYMAX 16 +#include + +BOOL CALLBACK DI_EnumJoypadsCallback(const DIDEVICEINSTANCE *instance, void *p); + +class pInputDI { +public: + InputDI &self; + uint8 keystate[65536]; + LPDIRECTINPUT8 di; + LPDIRECTINPUTDEVICE8 di_key, di_joy[DIRECTINPUT_JOYMAX]; + uint32 di_joy_count; + + struct { + HWND handle; + } settings; + + bool cap(Input::Setting setting) { + if(setting == Input::Handle) 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; + } + + void clear_input() { + memset(keystate, 0, sizeof keystate); + } + + void poll() { + clear_input(); + + HRESULT hr; + DIJOYSTATE2 js; + if(di_key) { + hr = di_key->GetDeviceState(256, keystate); + if(FAILED(hr)) { + di_key->Acquire(); + hr = di_key->GetDeviceState(256, keystate); + } + } + + for(int i = 0; i < di_joy_count; i++) { + if(!di_joy[i])continue; + + memset(js.rgbButtons, 0, 128); + + hr = di_joy[i]->Poll(); + if(FAILED(hr)) { + di_joy[i]->Acquire(); + di_joy[i]->Poll(); + } + di_joy[i]->GetDeviceState(sizeof(DIJOYSTATE2), &js); + + uint index = keymap::joypad_flag | (i << 8); //joypad index + memcpy(keystate + index, js.rgbButtons, 128); + + //map d-pad axes + int resistance = 75; //config::input.axis_resistance; + if(resistance < 1)resistance = 1; + if(resistance > 99)resistance = 99; + resistance = int32(double(resistance) * 32768.0 / 100.0); + int resistance_lo = 0x7fff - resistance; + int resistance_hi = 0x8000 + resistance; + keystate[index + keymap::joypad_up] = (js.lY <= resistance_lo) ? 0x80 : 0x00; + keystate[index + keymap::joypad_down] = (js.lY >= resistance_hi) ? 0x80 : 0x00; + keystate[index + keymap::joypad_left] = (js.lX <= resistance_lo) ? 0x80 : 0x00; + keystate[index + keymap::joypad_right] = (js.lX >= resistance_hi) ? 0x80 : 0x00; + + //map analog POV (analog directional pad) as well + uint pov = js.rgdwPOV[0]; + keystate[index + keymap::joypad_up] |= (pov == 0 || pov == 31500 || pov == 4500) ? 0x80 : 0x00; + keystate[index + keymap::joypad_down] |= (pov == 18000 || pov == 13500 || pov == 22500) ? 0x80 : 0x00; + keystate[index + keymap::joypad_left] |= (pov == 27000 || pov == 22500 || pov == 31500) ? 0x80 : 0x00; + keystate[index + keymap::joypad_right] |= (pov == 9000 || pov == 4500 || pov == 13500) ? 0x80 : 0x00; + } + } + + bool enum_joypads(const DIDEVICEINSTANCE *instance) { + HRESULT hr = di->CreateDevice(instance->guidInstance, &di_joy[di_joy_count], 0); + if(FAILED(hr)) { + return DIENUM_CONTINUE; + } + + di_joy[di_joy_count]->SetDataFormat(&c_dfDIJoystick2); + di_joy[di_joy_count]->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + + if(++di_joy_count >= DIRECTINPUT_JOYMAX) { + //too many joypads? + return DIENUM_STOP; + } + + return DIENUM_CONTINUE; + } + + void init() { + di_key = 0; + for(int i = 0; i < DIRECTINPUT_JOYMAX; i++)di_joy[i] = 0; + di = 0; + di_joy_count = 0; + + DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, + IID_IDirectInput8, (void**)&di, 0); + di->CreateDevice(GUID_SysKeyboard, &di_key, 0); + + di_key->SetDataFormat(&c_dfDIKeyboard); + di_key->SetCooperativeLevel(settings.handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + di_key->Acquire(); + + di->EnumDevices(DI8DEVCLASS_GAMECTRL, DI_EnumJoypadsCallback, (void*)this, DIEDFL_ATTACHEDONLY); + } + + void term() { + if(di_key) { di_key->Unacquire(); di_key->Release(); di_key = 0; } + for(int i = 0; i < DIRECTINPUT_JOYMAX; i++) { + if(di_joy[i]) { di_joy[i]->Unacquire(); di_joy[i]->Release(); di_joy[i] = 0; } + } + if(di) { di->Release(); di = 0; } + di_joy_count = 0; + } + + bool key_down(uint16 key) { + return keystate[translate(key)] & 0x80; + } + + //translate keymap code to DirectInput code, to lookup key status in DI status table + uint16 translate(uint16 key) { + //DI joypad codes share 1:1 mapping with keymap codes + if(key & keymap::joypad_flag) { return key; } + + switch(key) { + case keymap::esc: return 0x01; + + case keymap::f1: return 0x3b; + case keymap::f2: return 0x3c; + case keymap::f3: return 0x3d; + case keymap::f4: return 0x3e; + case keymap::f5: return 0x3f; + case keymap::f6: return 0x40; + case keymap::f7: return 0x41; + case keymap::f8: return 0x42; + case keymap::f9: return 0x43; + case keymap::f10: return 0x44; + case keymap::f11: return 0x57; + case keymap::f12: return 0x58; + + case keymap::print_screen: return 0xb7; + case keymap::scroll_lock: return 0x46; + case keymap::pause: return 0xc5; + + case keymap::grave: return 0x29; + + case keymap::num_1: return 0x02; + case keymap::num_2: return 0x03; + case keymap::num_3: return 0x04; + case keymap::num_4: return 0x05; + case keymap::num_5: return 0x06; + case keymap::num_6: return 0x07; + case keymap::num_7: return 0x08; + case keymap::num_8: return 0x09; + case keymap::num_9: return 0x0a; + case keymap::num_0: return 0x0b; + + case keymap::minus: return 0x0c; + case keymap::equal: return 0x0d; + case keymap::backspace: return 0x0e; + + case keymap::ins: return 0xd2; + case keymap::del: return 0xd3; + case keymap::home: return 0xc7; + case keymap::end: return 0xcf; + case keymap::page_up: return 0xc9; + case keymap::page_down: return 0xd1; + + case keymap::a: return 0x1e; + case keymap::b: return 0x30; + case keymap::c: return 0x2e; + case keymap::d: return 0x20; + case keymap::e: return 0x12; + case keymap::f: return 0x21; + case keymap::g: return 0x22; + case keymap::h: return 0x23; + case keymap::i: return 0x17; + case keymap::j: return 0x24; + case keymap::k: return 0x25; + case keymap::l: return 0x26; + case keymap::m: return 0x32; + case keymap::n: return 0x31; + case keymap::o: return 0x18; + case keymap::p: return 0x19; + case keymap::q: return 0x10; + case keymap::r: return 0x13; + case keymap::s: return 0x1f; + case keymap::t: return 0x14; + case keymap::u: return 0x16; + case keymap::v: return 0x2f; + case keymap::w: return 0x11; + case keymap::x: return 0x2d; + case keymap::y: return 0x15; + case keymap::z: return 0x2c; + + case keymap::lbracket: return 0x1a; + case keymap::rbracket: return 0x1b; + case keymap::backslash: return 0x2b; + case keymap::semicolon: return 0x27; + case keymap::apostrophe: return 0x28; + case keymap::comma: return 0x33; + case keymap::period: return 0x34; + case keymap::slash: return 0x35; + + case keymap::kp_1: return 0x4f; + case keymap::kp_2: return 0x50; + case keymap::kp_3: return 0x51; + case keymap::kp_4: return 0x4b; + case keymap::kp_5: return 0x4c; + case keymap::kp_6: return 0x4d; + case keymap::kp_7: return 0x47; + case keymap::kp_8: return 0x48; + case keymap::kp_9: return 0x49; + case keymap::kp_0: return 0x52; + case keymap::kp_decimal: return 0x53; + + case keymap::kp_plus: return 0x4e; + case keymap::kp_minus: return 0x4a; + case keymap::kp_mul: return 0x37; + case keymap::kp_div: return 0xb5; + case keymap::kp_enter: return 0x9c; + + case keymap::num_lock : return 0x45; + case keymap::caps_lock: return 0x3a; + + case keymap::up: return 0xc8; + case keymap::down: return 0xd0; + case keymap::left: return 0xcb; + case keymap::right: return 0xcd; + + case keymap::tab: return 0x0f; + case keymap::enter: return 0x1c; + case keymap::space: return 0x39; + + case keymap::lctrl : return 0x1d; + case keymap::rctrl : return 0x9d; + case keymap::lalt : return 0x38; + case keymap::ralt : return 0xb8; + case keymap::lshift: return 0x2a; + case keymap::rshift: return 0x36; + case keymap::lsuper: return 0xdb; + case keymap::rsuper: return 0xdc; + case keymap::menu: return 0xdd; + } + + return 0x00; + } + + pInputDI(InputDI &self_) : self(self_) { + di = 0; + di_key = 0; + for(int i = 0; i < DIRECTINPUT_JOYMAX; i++) di_joy[i] = 0; + } + + ~pInputDI() { term(); } +}; + +BOOL CALLBACK DI_EnumJoypadsCallback(const DIDEVICEINSTANCE *instance, void *p) { + return ((pInputDI*)p)->enum_joypads(instance); +} + +bool InputDI::cap(Setting setting) { return p.cap(setting); } +uintptr_t InputDI::get(Setting setting) { return p.get(setting); } +bool InputDI::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool InputDI::key_down(uint16 key) { return p.key_down(key); } +void InputDI::clear_input() { p.clear_input(); } +void InputDI::poll() { p.poll(); } +void InputDI::init() { p.init(); } +void InputDI::term() { p.term(); } +InputDI::InputDI() : p(*new pInputDI(*this)) {} +InputDI::~InputDI() { delete &p; } diff --git a/src/ui/vai/input/input.directinput.h b/src/ui/vai/input/input.directinput.h new file mode 100644 index 00000000..e7efd819 --- /dev/null +++ b/src/ui/vai/input/input.directinput.h @@ -0,0 +1,28 @@ +#ifndef INPUT_DIRECTINPUT_H +#define INPUT_DIRECTINPUT_H + +#include "../input.h" + +class pInputDI; + +class InputDI : public Input { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + bool key_down(uint16 key); + + void clear_input(); + void poll(); + void init(); + void term(); + + InputDI(); + ~InputDI(); + +private: + pInputDI &p; +}; + +#endif //ifndef INPUT_DIRECTINPUT_H diff --git a/src/ui/vai/input/input.x.cpp b/src/ui/vai/input/input.x.cpp new file mode 100644 index 00000000..2cf9ddde --- /dev/null +++ b/src/ui/vai/input/input.x.cpp @@ -0,0 +1,168 @@ +#include "input.x.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class pInputX { +public: + InputX &self; + Display *display; + char keymap[32]; + + bool key_down(uint16 key) { + #define map(i) (keymap[i >> 3] & (1 << (i & 7))) + + switch(key) { + case keymap::esc: return map(0x09); + + case keymap::f1: return map(0x43); + case keymap::f2: return map(0x44); + case keymap::f3: return map(0x45); + case keymap::f4: return map(0x46); + case keymap::f5: return map(0x47); + case keymap::f6: return map(0x48); + case keymap::f7: return map(0x49); + case keymap::f8: return map(0x4a); + case keymap::f9: return map(0x4b); + case keymap::f10: return map(0x4c); + case keymap::f11: return map(0x5f); + case keymap::f12: return map(0x60); + + case keymap::print_screen: return map(0x6f); + case keymap::scroll_lock: return map(0x4e); + case keymap::pause: return map(0x6e); + + case keymap::grave: return map(0x31); + + case keymap::num_1: return map(0x0a); + case keymap::num_2: return map(0x0b); + case keymap::num_3: return map(0x0c); + case keymap::num_4: return map(0x0d); + case keymap::num_5: return map(0x0e); + case keymap::num_6: return map(0x0f); + case keymap::num_7: return map(0x10); + case keymap::num_8: return map(0x11); + case keymap::num_9: return map(0x12); + case keymap::num_0: return map(0x13); + + case keymap::minus: return map(0x14); + case keymap::equal: return map(0x15); + case keymap::backspace: return map(0x16); + + case keymap::ins: return map(0x6a); + case keymap::del: return map(0x6b); + case keymap::home: return map(0x61); + case keymap::end: return map(0x67); + case keymap::page_up: return map(0x63); + case keymap::page_down: return map(0x69); + + case keymap::a: return map(0x26); + case keymap::b: return map(0x38); + case keymap::c: return map(0x36); + case keymap::d: return map(0x28); + case keymap::e: return map(0x1a); + case keymap::f: return map(0x29); + case keymap::g: return map(0x2a); + case keymap::h: return map(0x2b); + case keymap::i: return map(0x1f); + case keymap::j: return map(0x2c); + case keymap::k: return map(0x2d); + case keymap::l: return map(0x2e); + case keymap::m: return map(0x3a); + case keymap::n: return map(0x39); + case keymap::o: return map(0x20); + case keymap::p: return map(0x21); + case keymap::q: return map(0x18); + case keymap::r: return map(0x1b); + case keymap::s: return map(0x27); + case keymap::t: return map(0x1c); + case keymap::u: return map(0x1e); + case keymap::v: return map(0x37); + case keymap::w: return map(0x19); + case keymap::x: return map(0x35); + case keymap::y: return map(0x1d); + case keymap::z: return map(0x34); + + case keymap::lbracket: return map(0x22); + case keymap::rbracket: return map(0x23); + case keymap::backslash: return map(0x33); + case keymap::semicolon: return map(0x2f); + case keymap::apostrophe: return map(0x30); + case keymap::comma: return map(0x3b); + case keymap::period: return map(0x3c); + case keymap::slash: return map(0x3d); + + case keymap::kp_1: return map(0x57); + case keymap::kp_2: return map(0x58); + case keymap::kp_3: return map(0x59); + case keymap::kp_4: return map(0x53); + case keymap::kp_5: return map(0x54); + case keymap::kp_6: return map(0x55); + case keymap::kp_7: return map(0x4f); + case keymap::kp_8: return map(0x50); + case keymap::kp_9: return map(0x51); + + case keymap::kp_plus: return map(0x56); + case keymap::kp_minus: return map(0x52); + case keymap::kp_mul: return map(0x3f); + case keymap::kp_div: return map(0x70); + case keymap::kp_enter: return map(0x6c); + + case keymap::num_lock: return map(0x4d); + case keymap::caps_lock: return map(0x42); + + case keymap::up: return map(0x62); + case keymap::down: return map(0x68); + case keymap::left: return map(0x64); + case keymap::right: return map(0x66); + + case keymap::tab: return map(0x17); + case keymap::enter: return map(0x24); + case keymap::space: return map(0x41); + + case keymap::lctrl: return map(0x25); + case keymap::rctrl: return map(0x6d); + case keymap::lalt: return map(0x40); + case keymap::ralt: return map(0x71); + case keymap::lshift: return map(0x32); + case keymap::rshift: return map(0x3e); + case keymap::lsuper: return map(0x73); + case keymap::rsuper: return map(0x74); + case keymap::menu: return map(0x75); + } + + #undef map + return false; + } + + void clear_input() { + memset(keymap, 0, sizeof keymap); + } + + void poll() { + XQueryKeymap(display, keymap); + } + + void init() { + display = XOpenDisplay(0); + } + + void term() { + } + + pInputX(InputX &self_) : self(self_) {} +}; + +bool InputX::key_down(uint16 key) { return p.key_down(key); } +void InputX::clear_input() { p.clear_input(); } +void InputX::poll() { p.poll(); } +void InputX::init() { p.init(); } +void InputX::term() { p.term(); } +InputX::InputX() : p(*new pInputX(*this)) {} +InputX::~InputX() { delete &p; } diff --git a/src/ui/vai/input/input.x.h b/src/ui/vai/input/input.x.h new file mode 100644 index 00000000..3ff94b29 --- /dev/null +++ b/src/ui/vai/input/input.x.h @@ -0,0 +1,24 @@ +#ifndef INPUT_X_H +#define INPUT_X_H + +#include "../input.h" + +class pInputX; + +class InputX : public Input { +public: + bool key_down(uint16 key); + + void clear_input(); + void poll(); + void init(); + void term(); + + InputX(); + ~InputX(); + +private: + pInputX &p; +}; + +#endif //ifndef INPUT_X_H diff --git a/src/ui/vai/video.h b/src/ui/vai/video.h new file mode 100644 index 00000000..d01fa216 --- /dev/null +++ b/src/ui/vai/video.h @@ -0,0 +1,35 @@ +#ifndef VIDEO_H +#define VIDEO_H + +#include "../../lib/bbase.h" + +class Video { +public: + enum Setting { + Handle, + Synchronize, + Filter, + }; + + enum Filter { + FilterPoint, + FilterLinear, + }; + + virtual bool cap(Setting) { return false; } + virtual uintptr_t get(Setting) { return false; } + virtual bool set(Setting, uintptr_t) { return false; } + + virtual bool lock(uint16 *&data, uint &pitch) { return false; } + virtual void unlock() {} + + virtual void clear_video() {} + virtual void refresh(uint width, uint height) {} + virtual void init() {} + virtual void term() {} + + Video() {} + virtual ~Video() {} +}; + +#endif //ifndef VIDEO_H diff --git a/src/ui/vai/video/video.direct3d.cpp b/src/ui/vai/video/video.direct3d.cpp new file mode 100644 index 00000000..951bcb8f --- /dev/null +++ b/src/ui/vai/video/video.direct3d.cpp @@ -0,0 +1,352 @@ +#include "video.direct3d.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#define D3DVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1) + +class pVideoD3D { +public: + VideoD3D &self; + + LPDIRECT3D9 lpd3d; + LPDIRECT3DDEVICE9 device; + LPDIRECT3DVERTEXBUFFER9 vertex_buffer, *vertex_ptr; + D3DPRESENT_PARAMETERS presentation; + D3DSURFACE_DESC d3dsd; + D3DLOCKED_RECT d3dlr; + D3DRASTER_STATUS d3drs; + D3DCAPS9 d3dcaps; + LPDIRECT3DTEXTURE9 texture; + LPDIRECT3DSURFACE9 surface; + + struct d3dvertex { + float x, y, z, rhw; //screen coords + uint32 color; //diffuse color + float u, v; //texture coords + }; + + struct { + uint32 t_usage, v_usage; + uint32 t_pool, v_pool; + uint32 lock; + uint32 filter; + } flags; + + struct { + bool dynamic; //device supports dynamic textures + bool addresswrap; //device supports texture address (u,v) wrapping + bool stretchrect; //device supports StretchRect + } caps; + + struct { + HWND handle; + bool synchronize; + uint filter; + } settings; + + bool cap(Video::Setting setting) { + if(setting == Video::Handle) return true; + if(setting == Video::Synchronize) return true; + if(setting == Video::Filter) return true; + return false; + } + + uintptr_t get(Video::Setting setting) { + if(setting == Video::Handle) return (uintptr_t)settings.handle; + if(setting == Video::Synchronize) return settings.synchronize; + if(setting == Video::Filter) return settings.filter; + return false; + } + + bool set(Video::Setting setting, uintptr_t param) { + if(setting == Video::Handle) { + settings.handle = (HWND)param; + return true; + } + if(setting == Video::Synchronize) { + settings.synchronize = param; + return true; + } + if(setting == Video::Filter) { + settings.filter = param; + update_filter(); + return true; + } + return false; + } + + bool update_video_mode() { + HRESULT hr; + term(); + + lpd3d = Direct3DCreate9(D3D_SDK_VERSION); + if(!lpd3d) { + printf("VideoD3D: failed to create Direct3D9 interface"); + return false; + } + + memset(&presentation, 0, sizeof(presentation)); + presentation.Flags = D3DPRESENTFLAG_VIDEO; + presentation.SwapEffect = D3DSWAPEFFECT_FLIP; + presentation.hDeviceWindow = settings.handle; + presentation.BackBufferCount = 1; + presentation.MultiSampleType = D3DMULTISAMPLE_NONE; + presentation.MultiSampleQuality = 0; + presentation.EnableAutoDepthStencil = false; + presentation.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + presentation.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + presentation.Windowed = true; + presentation.BackBufferFormat = D3DFMT_UNKNOWN; + presentation.BackBufferWidth = 0; + presentation.BackBufferHeight = 0; + + if(lpd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, settings.handle, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device) != D3D_OK) { + printf("VideoD3D: failed to create Direct3D9 device"); + return false; + } + + //detect device capabilities + device->GetDeviceCaps(&d3dcaps); + if(d3dcaps.MaxTextureWidth < 1024 || d3dcaps.MaxTextureWidth < 1024) { + printf("VideoD3D: renderer requires that the video card supports textures up to 1024x1024.\n" + "However, this display adapter only supports %dx%d-sized textures.\n" + "", d3dcaps.MaxTextureWidth, d3dcaps.MaxTextureHeight); + return false; + } + caps.dynamic = bool(d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES); + caps.addresswrap = bool(d3dcaps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP); + caps.stretchrect = (d3dcaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) && + (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT) && + (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) && + (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) && + (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR); + + if(caps.dynamic == true) { + flags.t_usage = D3DUSAGE_DYNAMIC; + flags.v_usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; + flags.t_pool = D3DPOOL_DEFAULT; + flags.v_pool = D3DPOOL_DEFAULT; + flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; + } else { + flags.t_usage = 0; + flags.v_usage = D3DUSAGE_WRITEONLY; + flags.t_pool = D3DPOOL_MANAGED; + flags.v_pool = D3DPOOL_MANAGED; + flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; + } + + device->SetDialogBoxMode(false); + + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + + device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + if(caps.addresswrap == true) { + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + } + + device->SetRenderState(D3DRS_LIGHTING, false); + device->SetRenderState(D3DRS_ZENABLE, false); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); + + device->SetVertexShader(NULL); + device->SetFVF(D3DVERTEX); + + update_filter(); + + if(caps.stretchrect == true) { + device->CreateOffscreenPlainSurface(1024, 1024, D3DFMT_R5G6B5, + D3DPOOL_DEFAULT, &surface, NULL); + } else { + device->CreateTexture(1024, 1024, 1, flags.t_usage, D3DFMT_R5G6B5, + static_cast(flags.t_pool), &texture, NULL); + } + + device->CreateVertexBuffer(sizeof(d3dvertex) * 4, flags.v_usage, D3DVERTEX, + static_cast(flags.v_pool), &vertex_buffer, NULL); + + clear_video(); + return true; + } + + void update_filter() { + if(!device) return; + + switch(settings.filter) { default: + case Video::FilterPoint: flags.filter = D3DTEXF_POINT; break; + case Video::FilterLinear: flags.filter = D3DTEXF_LINEAR; break; + } + + device->SetSamplerState(0, D3DSAMP_MINFILTER, flags.filter); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, flags.filter); + } + + /* Vertex format: + + 0----------1 + | /| + | / | + | / | + | / | + | / | + 2----------3 + + (x,y) screen coords, in pixels (-0.5 for texel / pixel correction) + (u,v) texture coords, betweeen 0.0 (top, left) to 1.0 (bottom, right) + */ + void set_vertex(uint32 px, uint32 py, uint32 pw, uint32 ph, + uint32 tw, uint32 th, uint32 x, uint32 y, uint32 w, uint32 h) { + d3dvertex vertex[4]; + vertex[0].x = vertex[2].x = (float)(x ) - 0.5; + vertex[1].x = vertex[3].x = (float)(x + w) - 0.5; + vertex[0].y = vertex[1].y = (float)(y ) - 0.5; + vertex[2].y = vertex[3].y = (float)(y + h) - 0.5; + + //unused + vertex[0].z = vertex[1].z = 1.0; + vertex[2].z = vertex[3].z = 1.0; + vertex[0].rhw = vertex[1].rhw = 1.0; + vertex[2].rhw = vertex[3].rhw = 1.0; + + //setup a gradient fade for when pause is enabled + vertex[0].color = 0x80000000; + vertex[1].color = 0xa8000000; + vertex[2].color = 0xa8000000; + vertex[3].color = 0xd0000000; + + float rw = (float)w / (float)pw * (float)tw; + float rh = (float)h / (float)ph * (float)th; + vertex[0].u = vertex[2].u = (float)(px ) / rw; + vertex[1].u = vertex[3].u = (float)(px + w) / rw; + vertex[0].v = vertex[1].v = (float)(py ) / rh; + vertex[2].v = vertex[3].v = (float)(py + h) / rh; + + vertex_buffer->Lock(0, sizeof(d3dvertex) * 4, (void**)&vertex_ptr, 0); + memcpy(vertex_ptr, vertex, sizeof(d3dvertex) * 4); + vertex_buffer->Unlock(); + + device->SetStreamSource(0, vertex_buffer, 0, sizeof(d3dvertex)); + } + + void clear_video() { + if(!device) return; + if(caps.stretchrect == false && !texture) return; + + if(caps.stretchrect == false) { + texture->GetLevelDesc(0, &d3dsd); + texture->GetSurfaceLevel(0, &surface); + } + + if(surface) { + device->ColorFill(surface, 0, D3DCOLOR_XRGB(0x00, 0x00, 0x00)); + if(caps.stretchrect == false) { + surface->Release(); + } + } + + //clear primary display and all backbuffers + for(int i = 0; i < 3; i++) { + device->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00, 0x00, 0x00), 1.0f, 0); + device->Present(0, 0, 0, 0); + } + } + + bool lock(uint16 *&data, uint &pitch) { + if(caps.stretchrect == false) { + texture->GetLevelDesc(0, &d3dsd); + texture->GetSurfaceLevel(0, &surface); + } + surface->LockRect(&d3dlr, 0, flags.lock); + pitch = d3dlr.Pitch; + data = (uint16*)d3dlr.pBits; + return data; + } + + void unlock() { + surface->UnlockRect(); + if(caps.stretchrect == false)surface->Release(); + } + + void refresh(uint r_width, uint r_height) { + if(!device) return; + + device->BeginScene(); + + if(caps.stretchrect == true) { + RECT rs; + SetRect(&rs, 0, 0, r_width, r_height); + LPDIRECT3DSURFACE9 temp; + device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &temp); + device->StretchRect(surface, &rs, temp, 0, static_cast(flags.filter)); + temp->Release(); + } else { + RECT rd; + GetClientRect(settings.handle, &rd); + set_vertex(0, 0, r_width, r_height, 1024, 1024, 0, 0, rd.right, rd.bottom); + device->SetTexture(0, texture); + device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } + + device->EndScene(); + + if(settings.synchronize) { + D3DRASTER_STATUS status; + for(;;) { + device->GetRasterStatus(0, &status); + if(bool(status.InVBlank) == true) break; + //Sleep(1); + } + } + + device->Present(0, 0, 0, 0); + } + + void init() { + term(); + update_video_mode(); + } + + void term() { + safe_release(vertex_buffer); + safe_release(surface); + safe_release(texture); + safe_release(device); + safe_release(lpd3d); + } + + pVideoD3D(VideoD3D &self_) : self(self_) { + vertex_buffer = 0; + surface = 0; + texture = 0; + device = 0; + lpd3d = 0; + + settings.handle = 0; + settings.synchronize = false; + settings.filter = Video::FilterLinear; + } +}; + +bool VideoD3D::cap(Setting setting) { return p.cap(setting); } +uintptr_t VideoD3D::get(Setting setting) { return p.get(setting); } +bool VideoD3D::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool VideoD3D::lock(uint16 *&data, uint &pitch) { return p.lock(data, pitch); } +void VideoD3D::unlock() { p.unlock(); } +void VideoD3D::clear_video() { p.clear_video(); } +void VideoD3D::refresh(uint width, uint height) { p.refresh(width, height); } +void VideoD3D::init() { p.init(); } +void VideoD3D::term() { p.term(); } +VideoD3D::VideoD3D() : p(*new pVideoD3D(*this)) {} +VideoD3D::~VideoD3D() { delete &p; } diff --git a/src/ui/vai/video/video.direct3d.h b/src/ui/vai/video/video.direct3d.h new file mode 100644 index 00000000..e2cdc7ce --- /dev/null +++ b/src/ui/vai/video/video.direct3d.h @@ -0,0 +1,29 @@ +#ifndef VIDEO_DIRECT3D_H +#define VIDEO_DIRECT3D_H + +#include "../video.h" + +class pVideoD3D; + +class VideoD3D : public Video { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + bool lock(uint16 *&data, uint &pitch); + void unlock(); + + void clear_video(); + void refresh(uint width, uint height); + void init(); + void term(); + + VideoD3D(); + ~VideoD3D(); + +private: + pVideoD3D &p; +}; + +#endif //ifndef VIDEO_DIRECT3D_H diff --git a/src/ui/vai/video/video.directdraw.cpp b/src/ui/vai/video/video.directdraw.cpp new file mode 100644 index 00000000..c26a1bed --- /dev/null +++ b/src/ui/vai/video/video.directdraw.cpp @@ -0,0 +1,177 @@ +#include "video.directdraw.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +class pVideoDD { +public: + VideoDD &self; + + LPDIRECTDRAW lpdd; + LPDIRECTDRAW7 lpdd7; + LPDIRECTDRAWSURFACE7 screen, raster; + LPDIRECTDRAWCLIPPER clipper; + DDSURFACEDESC2 ddsd; + DDSCAPS2 ddscaps; + + struct { + HWND handle; + bool synchronize; + } settings; + + bool cap(Video::Setting setting) { + if(setting == Video::Handle) return true; + if(setting == Video::Synchronize) return true; + return false; + } + + uintptr_t get(Video::Setting setting) { + if(setting == Video::Handle) return (uintptr_t)settings.handle; + if(setting == Video::Synchronize) return settings.synchronize; + return false; + } + + bool set(Video::Setting setting, uintptr_t param) { + if(setting == Video::Handle) { + settings.handle = (HWND)param; + return true; + } + if(setting == Video::Synchronize) { + settings.synchronize = param; + return true; + } + return false; + } + + void clear_video() { + DDBLTFX fx; + fx.dwSize = sizeof(DDBLTFX); + fx.dwFillColor = 0x00000000; + screen->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); + raster->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); + } + + bool lock(uint16 *&data, uint &pitch) { + if(raster->Lock(0, &ddsd, DDLOCK_WAIT, 0) != DD_OK) return false; + pitch = ddsd.lPitch; + data = (uint16*)ddsd.lpSurface; + return data; + } + + void unlock() { + raster->Unlock(0); + } + + void refresh(uint r_width, uint r_height) { + if(settings.synchronize) { + for(;;) { + BOOL in_vblank; + lpdd7->GetVerticalBlankStatus(&in_vblank); + if(bool(in_vblank) == true) break; + //Sleep(1); + } + } + + HRESULT hr; + RECT rd, rs; + SetRect(&rs, 0, 0, r_width, r_height); + + POINT p = { 0, 0 }; + ClientToScreen(settings.handle, &p); + GetClientRect(settings.handle, &rd); + OffsetRect(&rd, p.x, p.y); + + if(screen->Blt(&rd, raster, &rs, DDBLT_WAIT, 0) == DDERR_SURFACELOST) { + screen->Restore(); + raster->Restore(); + } + } + + void init() { + term(); + + DirectDrawCreate(0, &lpdd, 0); + lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7); + safe_release(lpdd); + + lpdd7->SetCooperativeLevel(settings.handle, DDSCL_NORMAL); + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + lpdd7->CreateSurface(&ddsd, &screen, 0); + + lpdd7->CreateClipper(0, &clipper, 0); + clipper->SetHWnd(0, settings.handle); + screen->SetClipper(clipper); + + create_raster(); + clear_video(); + } + + void create_raster() { + int depth; + screen->GetSurfaceDesc(&ddsd); + depth = ddsd.ddpfPixelFormat.dwRGBBitCount; + if(depth == 15 || depth == 16) goto try_native_surface; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; //DDSCAPS_SYSTEMMEMORY + ddsd.dwWidth = 1024; + ddsd.dwHeight = 1024; + + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = 16; + ddsd.ddpfPixelFormat.dwRBitMask = 0xf800; + ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0; + ddsd.ddpfPixelFormat.dwBBitMask = 0x001f; + + if(lpdd7->CreateSurface(&ddsd, &raster, 0) == DD_OK) return; + + try_native_surface: + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; //DDSCAPS_SYSTEMMEMORY + ddsd.dwWidth = 1024; + ddsd.dwHeight = 1024; + + lpdd7->CreateSurface(&ddsd, &raster, 0); + } + + void term() { + safe_release(clipper); + safe_release(raster); + safe_release(screen); + safe_release(lpdd7); + safe_release(lpdd); + } + + pVideoDD(VideoDD &self_) : self(self_) { + lpdd = 0; + lpdd7 = 0; + screen = 0; + raster = 0; + clipper = 0; + + settings.handle = 0; + } +}; + +bool VideoDD::cap(Setting setting) { return p.cap(setting); } +uintptr_t VideoDD::get(Setting setting) { return p.get(setting); } +bool VideoDD::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool VideoDD::lock(uint16 *&data, uint &pitch) { return p.lock(data, pitch); } +void VideoDD::unlock() { p.unlock(); } +void VideoDD::clear_video() { p.clear_video(); } +void VideoDD::refresh(uint width, uint height) { p.refresh(width, height); } +void VideoDD::init() { p.init(); } +void VideoDD::term() { p.term(); } +VideoDD::VideoDD() : p(*new pVideoDD(*this)) {} +VideoDD::~VideoDD() { delete &p; } diff --git a/src/ui/vai/video/video.directdraw.h b/src/ui/vai/video/video.directdraw.h new file mode 100644 index 00000000..304f123b --- /dev/null +++ b/src/ui/vai/video/video.directdraw.h @@ -0,0 +1,29 @@ +#ifndef VIDEO_DIRECTDRAW_H +#define VIDEO_DIRECTDRAW_H + +#include "../video.h" + +class pVideoDD; + +class VideoDD : public Video { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + bool lock(uint16 *&data, uint &pitch); + void unlock(); + + void clear_video(); + void refresh(uint width, uint height); + void init(); + void term(); + + VideoDD(); + ~VideoDD(); + +private: + pVideoDD &p; +}; + +#endif //ifndef VIDEO_DIRECTDRAW_H diff --git a/src/ui/vai/video/video.gdi.cpp b/src/ui/vai/video/video.gdi.cpp new file mode 100644 index 00000000..0863d1b8 --- /dev/null +++ b/src/ui/vai/video/video.gdi.cpp @@ -0,0 +1,98 @@ +#include "video.gdi.h" + +#define WIN32_LEAN_AND_MEAN +#include + +class pVideoGDI { +public: + VideoGDI &self; + + uint16 *buffer; + HBITMAP bitmap; + HDC bitmapdc; + BITMAPINFO bmi; + + struct { + HWND handle; + } settings; + + bool cap(Video::Setting setting) { + if(setting == Video::Handle) return true; + return false; + } + + uintptr_t get(Video::Setting setting) { + if(setting == Video::Handle) return (uintptr_t)settings.handle; + return false; + } + + bool set(Video::Setting setting, uintptr_t param) { + if(setting == Video::Handle) { + settings.handle = (HWND)param; + return true; + } + return false; + } + + bool lock(uint16 *&data, uint &pitch) { + pitch = 2048; + data = buffer; + return data; + } + + void unlock() {} + + void refresh(uint r_width, uint r_height) { + RECT rc; + GetClientRect(settings.handle, &rc); + + SetDIBits(bitmapdc, bitmap, 0, r_height, (void*)buffer, &bmi, DIB_RGB_COLORS); + HDC hdc = GetDC(settings.handle); + StretchBlt(hdc, rc.left, rc.top, rc.right, rc.bottom, bitmapdc, 0, 1024 - r_height, r_width, r_height, SRCCOPY); + ReleaseDC(settings.handle, hdc); + } + + void init() { + HDC hdc = GetDC(settings.handle); + bitmapdc = CreateCompatibleDC(hdc); + assert(bitmapdc); + bitmap = CreateCompatibleBitmap(hdc, 1024, 1024); + assert(bitmap); + SelectObject(bitmapdc, bitmap); + ReleaseDC(settings.handle, hdc); + + memset(&bmi, 0, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = 1024; + bmi.bmiHeader.biHeight = -1024; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 16; //biBitCount of 15 is invalid, biBitCount of 16 is really RGB555 + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 1024 * 1024 * sizeof(uint16); + } + + void term() { + DeleteObject(bitmap); + DeleteDC(bitmapdc); + } + + pVideoGDI(VideoGDI &self_) : self(self_) { + buffer = (uint16*)malloc(1024 * 1024 * sizeof(uint16)); + settings.handle = 0; + } + + ~pVideoGDI() { + if(buffer) free(buffer); + } +}; + +bool VideoGDI::cap(Setting setting) { return p.cap(setting); } +uintptr_t VideoGDI::get(Setting setting) { return p.get(setting); } +bool VideoGDI::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool VideoGDI::lock(uint16 *&data, uint &pitch) { return p.lock(data, pitch); } +void VideoGDI::unlock() { p.unlock(); } +void VideoGDI::refresh(uint width, uint height) { p.refresh(width, height); } +void VideoGDI::init() { p.init(); } +void VideoGDI::term() { p.term(); } +VideoGDI::VideoGDI() : p(*new pVideoGDI(*this)) {} +VideoGDI::~VideoGDI() { delete &p; } diff --git a/src/ui/video/gdi.h b/src/ui/vai/video/video.gdi.h similarity index 53% rename from src/ui/video/gdi.h rename to src/ui/vai/video/video.gdi.h index e8fbb616..4399c257 100644 --- a/src/ui/video/gdi.h +++ b/src/ui/vai/video/video.gdi.h @@ -1,15 +1,16 @@ #ifndef VIDEO_GDI_H #define VIDEO_GDI_H -class VideoGDI : public Video { -private: -HWND hwnd; -uint16 *buffer; -HBITMAP bitmap; -HDC bitmapdc; -BITMAPINFO bmi; +#include "../video.h" +class pVideoGDI; + +class VideoGDI : public Video { public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + bool lock(uint16 *&data, uint &pitch); void unlock(); @@ -17,8 +18,11 @@ public: void init(); void term(); - VideoGDI(HWND handle); + VideoGDI(); ~VideoGDI(); + +private: + pVideoGDI &p; }; -#endif +#endif //ifndef VIDEO_GDI_H diff --git a/src/ui/vai/video/video.gtk.cpp b/src/ui/vai/video/video.gtk.cpp new file mode 100644 index 00000000..7e862e61 --- /dev/null +++ b/src/ui/vai/video/video.gtk.cpp @@ -0,0 +1,120 @@ +#include "video.gtk.h" + +#include +#include +#include +#include + +class pVideoGTK { +public: + VideoGTK &self; + GtkWidget *widget; + uint16 *buffer; + uint8 *gdkbuffer; + + struct { + Window handle; + } settings; + + bool cap(Video::Setting setting) { + if(setting == Video::Handle) return false; + return false; + } + + uintptr_t get(Video::Setting setting) { + if(setting == Video::Handle) return settings.handle; + return false; + } + + bool set(Video::Setting setting, uintptr_t param) { + if(setting == Video::Handle) { + settings.handle = param; + return false; + } + return false; + } + + bool lock(uint16 *&data, uint &pitch) { + pitch = 1024 * 2; + return data = buffer; + } + + void unlock() { + } + + void refresh(uint r_width, uint r_height) { + for(uint y = 0; y < r_height; y++) { + uint8 *dest = gdkbuffer + y * 1024 * 3; + uint16 *src = buffer + y * 1024; + for(uint x = 0; x < r_width; x++) { + uint32 p = *src++; + uint32 pix = ((p & 0xf800) << 8) | ((p & 0x07e0) << 5) | ((p & 0x001f) << 3); + *dest++ = pix >> 16; + *dest++ = pix >> 8; + *dest++ = pix; + } + } + + gdk_draw_rgb_image(GDK_DRAWABLE(widget->window), + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + 0, 0, r_width, r_height, + GDK_RGB_DITHER_NONE, gdkbuffer, 1024 * 3); + } + + void init_no_handle() { + GdkColor color; + color.pixel = color.red = color.green = color.blue = 0; + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "video.gtk"); + gtk_window_set_resizable(GTK_WINDOW(window), false); + gtk_widget_set_size_request(window, 512, 480); + GtkWidget *container = gtk_fixed_new(); + gtk_widget_set_size_request(container, 512, 480); + gtk_container_add(GTK_CONTAINER(window), container); + widget = gtk_drawing_area_new(); + gtk_fixed_put(GTK_FIXED(container), widget, 0, 0); + gtk_widget_set_size_request(widget, 512, 480); + gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &color); + gtk_widget_modify_bg(container, GTK_STATE_NORMAL, &color); + gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); + gtk_widget_show(widget); + gtk_widget_show(container); + gtk_widget_show(window); + + if(settings.handle) { + /* below does not work, sadly ... + XReparentWindow( + GDK_WINDOW_XDISPLAY(window->window), + GDK_WINDOW_XWINDOW(window->window), + settings.handle, 0, 0); + */ + } + } + + void init() { + buffer = (uint16*)malloc(1024 * 1024 * 2); + gdkbuffer = (uint8*) malloc(1024 * 1024 * 3); + + init_no_handle(); + } + + void term() { + safe_free(buffer); + safe_free(gdkbuffer); + } + + pVideoGTK(VideoGTK &self_) : self(self_) { + settings.handle = 0; + } +}; + +bool VideoGTK::cap(Setting setting) { return p.cap(setting); } +uintptr_t VideoGTK::get(Setting setting) { return p.get(setting); } +bool VideoGTK::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool VideoGTK::lock(uint16 *&data, uint &pitch) { return p.lock(data, pitch); } +void VideoGTK::unlock() { p.unlock(); } +void VideoGTK::refresh(uint width, uint height) { p.refresh(width, height); } +void VideoGTK::init() { p.init(); } +void VideoGTK::term() { p.term(); } +VideoGTK::VideoGTK() : p(*new pVideoGTK(*this)) {} +VideoGTK::~VideoGTK() { delete &p; } diff --git a/src/ui/vai/video/video.gtk.h b/src/ui/vai/video/video.gtk.h new file mode 100644 index 00000000..3014e7b5 --- /dev/null +++ b/src/ui/vai/video/video.gtk.h @@ -0,0 +1,28 @@ +#ifndef VIDEO_GTK_H +#define VIDEO_GTK_H + +#include "../video.h" + +class pVideoGTK; + +class VideoGTK : public Video { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + bool lock(uint16 *&data, uint &pitch); + void unlock(); + + void refresh(uint width, uint height); + void init(); + void term(); + + VideoGTK(); + ~VideoGTK(); + +private: + pVideoGTK &p; +}; + +#endif //ifndef VIDEO_GTK_H diff --git a/src/ui/vai/video/video.xv.cpp b/src/ui/vai/video/video.xv.cpp new file mode 100644 index 00000000..24937908 --- /dev/null +++ b/src/ui/vai/video/video.xv.cpp @@ -0,0 +1,195 @@ +#include "video.xv.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" XvImage* XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*); + +class pVideoXv { +public: + VideoXv &self; + uint16 *buffer; + XvImage *xvimage; + GC gc; + Display *display; + int screen, xv_port; + XShmSegmentInfo shminfo; + uint8 *ytable, *utable, *vtable; + + struct { + Window handle; + } settings; + + bool cap(Video::Setting setting) { + if(setting == Video::Handle) return true; + return false; + } + + uintptr_t get(Video::Setting setting) { + if(setting == Video::Handle) return settings.handle; + return false; + } + + bool set(Video::Setting setting, uintptr_t param) { + if(setting == Video::Handle) { + settings.handle = param; + return true; + } + return false; + } + + bool lock(uint16 *&data, uint &pitch) { + pitch = 1024 * 2; + data = buffer; + return data; + } + + void unlock() { + } + + void clear_video() { + memset(buffer, 0, 1024 * 1024 * sizeof(uint16)); + //clear twice in case video is double buffered ... + refresh(1024, 1024); + refresh(1024, 1024); + } + + void refresh(uint r_width, uint r_height) { + Window dw; + int d0, d1; + uint d2, d3; + uint width, height; + XGetGeometry(display, settings.handle, &dw, &d0, &d1, &width, &height, &d2, &d3); + + uint16 *input = (uint16*)buffer; + uint16 *output = (uint16*)xvimage->data; + for(int y = 0; y < r_height; y++) { + for(int x = 0; x < r_width >> 1; x++) { + uint16 p0 = *input++; + uint16 p1 = *input++; + + uint8 u = (utable[p0] + utable[p1]) >> 1; + uint8 v = (vtable[p0] + vtable[p1]) >> 1; + + *output++ = (u << 8) | ytable[p0]; + *output++ = (v << 8) | ytable[p1]; + } + input += 1024 - r_width; + output += 1024 - r_width; + } + + XvShmPutImage(display, xv_port, settings.handle, gc, xvimage, + 0, 0, r_width, r_height, + 0, 0, width, height, + true); + } + + void init() { + buffer = (uint16*)malloc(1024 * 1024 * sizeof(uint16)); + display = XOpenDisplay(0); + screen = DefaultScreen(display); + gc = XCreateGC(display, settings.handle, 0, 0); + + XVisualInfo visual_info; + if(XMatchVisualInfo(display, screen, 24, TrueColor, &visual_info)) { + } else if(XMatchVisualInfo(display, screen, 16, TrueColor, &visual_info)) { + } else if(XMatchVisualInfo(display, screen, 15, TrueColor, &visual_info)) { + } else if(XMatchVisualInfo(display, screen, 8, PseudoColor, &visual_info)) { + } else if(XMatchVisualInfo(display, screen, 8, GrayScale, &visual_info)) { + } else if(XMatchVisualInfo(display, screen, 8, StaticGray, &visual_info)) { + } else if(XMatchVisualInfo(display, screen, 1, StaticGray, &visual_info)) { + } else { + printf("VideoXv: unable to find suitable video display.\n"); + } + + if(!XShmQueryExtension(display)) printf("VideoXv: XShm extension not found.\n"); + + xv_port = -1; + XvAdaptorInfo *adaptor_info; + uint adaptor_count; + XvQueryAdaptors(display, DefaultRootWindow(display), &adaptor_count, &adaptor_info); + for(uint i = 0; i < adaptor_count; i++) { + //find adaptor that supports both input (memory->drawable) and image (drawable->screen) masks + if(adaptor_info[i].type & XvInputMask && adaptor_info[i].type & XvImageMask) { + xv_port = adaptor_info[i].base_id; + break; + } + } + XvFreeAdaptorInfo(adaptor_info); + if(xv_port == -1) printf("VideoXv: failed to find valid XvPort.\n"); + + //set colorkey to auto paint, so that Xv video output is always visible + const Atom atom = XInternAtom(display, "XV_AUTOPAINT_COLORKEY", true); + if(atom != None) XvSetPortAttribute(display, xv_port, atom, 1); + + //0x00000003 = 32-bit X8R8G8B8 [xRGB] (few drivers support this mode) + //0x32595559 = 16-bit Y8U8,Y8V8 [YUY2] (most drivers support this mode) + xvimage = XvShmCreateImage(display, xv_port, 0x32595559, 0, 1024, 1024, &shminfo); + if(!xvimage) printf("VideoXv: XShmCreateImage failed.\n"); + shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777); + shminfo.shmaddr = xvimage->data = (char*)shmat(shminfo.shmid, 0, 0); + shminfo.readOnly = false; + if(!XShmAttach(display, &shminfo)) printf("VideoXv: XShmAttach failed.\n"); + + init_yuv_tables(); + clear_video(); + } + + void term() { + XShmDetach(display, &shminfo); + free(ytable); + free(utable); + free(vtable); + } + + void init_yuv_tables() { + ytable = (uint8*)malloc(65536); + utable = (uint8*)malloc(65536); + vtable = (uint8*)malloc(65536); + + for(int i = 0; i < 65536; i++) { + //extract RGB565 color data from i + uint8 r = (i >> 11) & 31, g = (i >> 5) & 63, b = (i) & 31; + r = (r << 3) | (r >> 2); //R5->R8 + g = (g << 2) | (g >> 4); //G6->G8 + b = (b << 3) | (b >> 2); //B5->B8 + + //RGB->YUV conversion + int y = int( +(double(r) * 0.257) + (double(g) * 0.504) + (double(b) * 0.098) + 16.0 ); + int u = int( -(double(r) * 0.148) - (double(g) * 0.291) + (double(b) * 0.439) + 128.0 ); + int v = int( +(double(r) * 0.439) - (double(g) * 0.368) - (double(b) * 0.071) + 128.0 ); + + //RGB->YCbCr conversion + //double lr = 0.2126, lb = 0.0722, lg = (1.0 - lr - lb); + //int y = int( double(r) * lr + double(g) * lg + double(b) * lb ); + //int u = int( (double(b) - y) / (2.0 - 2.0 * lb) + 128.0 ); + //int v = int( (double(r) - y) / (2.0 - 2.0 * lr) + 128.0 ); + + ytable[i] = y < 0 ? 0 : y > 255 ? 255 : y; + utable[i] = u < 0 ? 0 : u > 255 ? 255 : u; + vtable[i] = v < 0 ? 0 : v > 255 ? 255 : v; + } + } + + pVideoXv(VideoXv &self_) : self(self_) { + settings.handle = 0; + } +}; + +bool VideoXv::cap(Setting setting) { return p.cap(setting); } +uintptr_t VideoXv::get(Setting setting) { return p.get(setting); } +bool VideoXv::set(Setting setting, uintptr_t param) { return p.set(setting, param); } +bool VideoXv::lock(uint16 *&data, uint &pitch) { return p.lock(data, pitch); } +void VideoXv::unlock() { p.unlock(); } +void VideoXv::clear_video() { p.clear_video(); } +void VideoXv::refresh(uint width, uint height) { p.refresh(width, height); } +void VideoXv::init() { p.init(); } +void VideoXv::term() { p.term(); } +VideoXv::VideoXv() : p(*new pVideoXv(*this)) {} +VideoXv::~VideoXv() { delete &p; } diff --git a/src/ui/vai/video/video.xv.h b/src/ui/vai/video/video.xv.h new file mode 100644 index 00000000..816a587e --- /dev/null +++ b/src/ui/vai/video/video.xv.h @@ -0,0 +1,29 @@ +#ifndef VIDEO_XV_H +#define VIDEO_XV_H + +#include "../video.h" + +class pVideoXv; + +class VideoXv : public Video { +public: + bool cap(Setting); + uintptr_t get(Setting); + bool set(Setting, uintptr_t); + + bool lock(uint16 *&data, uint &pitch); + void unlock(); + + void clear_video(); + void refresh(uint width, uint height); + void init(); + void term(); + + VideoXv(); + ~VideoXv(); + +private: + pVideoXv &p; +}; + +#endif //ifndef VIDEO_XV_H diff --git a/src/ui/video/d3d.cpp b/src/ui/video/d3d.cpp deleted file mode 100644 index 1c8e509d..00000000 --- a/src/ui/video/d3d.cpp +++ /dev/null @@ -1,271 +0,0 @@ -#define D3DVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1) - -bool VideoD3D::update_video_mode() { -HRESULT hr; - term(); - - lpd3d = Direct3DCreate9(D3D_SDK_VERSION); - if(!lpd3d) { - alert("Failed to create Direct3D9 interface"); - return false; - } - - memset(&presentation, 0, sizeof(presentation)); - presentation.Flags = D3DPRESENTFLAG_VIDEO; - presentation.SwapEffect = D3DSWAPEFFECT_FLIP; - presentation.hDeviceWindow = hwnd; - presentation.BackBufferCount = 1; - presentation.MultiSampleType = D3DMULTISAMPLE_NONE; - presentation.MultiSampleQuality = 0; - presentation.EnableAutoDepthStencil = false; - presentation.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentation.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - presentation.Windowed = true; - presentation.BackBufferFormat = D3DFMT_UNKNOWN; - presentation.BackBufferWidth = 0; - presentation.BackBufferHeight = 0; - - if(lpd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device) != D3D_OK) { - alert("Failed to create Direct3D9 device"); - return false; - } - -//detect device capabilities - device->GetDeviceCaps(&d3dcaps); - if(d3dcaps.MaxTextureWidth < 1024 || d3dcaps.MaxTextureWidth < 1024) { - alert("Error: Direct3D renderer requires that the video card supports textures up to 1024x1024.\n" - "However, this display adapter only supports %dx%d-sized textures.\n" - "", d3dcaps.MaxTextureWidth, d3dcaps.MaxTextureHeight); - return false; - } - caps.dynamic = bool(d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES); - caps.addresswrap = bool(d3dcaps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP); - caps.stretchrect = (d3dcaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) && - (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT) && - (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) && - (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) && - (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR); - - if(config::video.use_vram == true && caps.dynamic == true) { - flags.t_usage = D3DUSAGE_DYNAMIC; - flags.v_usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; - flags.t_pool = D3DPOOL_DEFAULT; - flags.v_pool = D3DPOOL_DEFAULT; - flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; - } else { - flags.t_usage = 0; - flags.v_usage = D3DUSAGE_WRITEONLY; - flags.t_pool = D3DPOOL_MANAGED; - flags.v_pool = D3DPOOL_MANAGED; - flags.lock = D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD; - } - - device->SetDialogBoxMode(false); - - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - - device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - - if(caps.addresswrap == true) { - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); - } - - device->SetRenderState(D3DRS_LIGHTING, false); - device->SetRenderState(D3DRS_ZENABLE, false); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - - device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); - - device->SetVertexShader(NULL); - device->SetFVF(D3DVERTEX); - - update_settings(); - - if(caps.stretchrect == true) { - device->CreateOffscreenPlainSurface(1024, 1024, D3DFMT_R5G6B5, - D3DPOOL_DEFAULT, &surface, NULL); - } else { - device->CreateTexture(1024, 1024, 1, flags.t_usage, D3DFMT_R5G6B5, - static_cast(flags.t_pool), &texture, NULL); - } - - device->CreateVertexBuffer(sizeof(d3dvertex) * 4, flags.v_usage, D3DVERTEX, - static_cast(flags.v_pool), &vertex_buffer, NULL); - - clear_video(); - return true; -} - -void VideoD3D::update_settings() { - if(!device)return; - - switch(settings.filter) { - case Video::FilterPoint: - flags.filter = D3DTEXF_POINT; - break; - case Video::FilterLinear: - default: - flags.filter = D3DTEXF_LINEAR; - break; - } - - device->SetSamplerState(0, D3DSAMP_MINFILTER, flags.filter); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, flags.filter); -} - -/* Vertex format: - - 0----------1 - | /| - | / | - | / | - | / | - | / | - 2----------3 - - (x,y) screen coords, in pixels (-0.5 for texel / pixel correction) - (u,v) texture coords, betweeen 0.0 (top, left) to 1.0 (bottom, right) -*/ - -void VideoD3D::set_vertex(uint32 px, uint32 py, uint32 pw, uint32 ph, -uint32 tw, uint32 th, uint32 x, uint32 y, uint32 w, uint32 h) { -d3dvertex vertex[4]; - vertex[0].x = vertex[2].x = (float)(x ) - 0.5; - vertex[1].x = vertex[3].x = (float)(x + w) - 0.5; - vertex[0].y = vertex[1].y = (float)(y ) - 0.5; - vertex[2].y = vertex[3].y = (float)(y + h) - 0.5; - -//unused - vertex[0].z = vertex[1].z = 1.0; - vertex[2].z = vertex[3].z = 1.0; - vertex[0].rhw = vertex[1].rhw = 1.0; - vertex[2].rhw = vertex[3].rhw = 1.0; - -//setup a gradient fade for when pause is enabled - vertex[0].color = 0x80000000; - vertex[1].color = 0xa8000000; - vertex[2].color = 0xa8000000; - vertex[3].color = 0xd0000000; - -float rw = (float)w / (float)pw * (float)tw; -float rh = (float)h / (float)ph * (float)th; - vertex[0].u = vertex[2].u = (float)(px ) / rw; - vertex[1].u = vertex[3].u = (float)(px + w) / rw; - vertex[0].v = vertex[1].v = (float)(py ) / rh; - vertex[2].v = vertex[3].v = (float)(py + h) / rh; - - vertex_buffer->Lock(0, sizeof(d3dvertex) * 4, (void**)&vertex_ptr, 0); - memcpy(vertex_ptr, vertex, sizeof(d3dvertex) * 4); - vertex_buffer->Unlock(); - - device->SetStreamSource(0, vertex_buffer, 0, sizeof(d3dvertex)); -} - -void VideoD3D::clear_video() { - if(!device)return; - if(caps.stretchrect == false && !texture)return; - - if(caps.stretchrect == false) { - texture->GetLevelDesc(0, &d3dsd); - texture->GetSurfaceLevel(0, &surface); - } - - if(surface) { - device->ColorFill(surface, 0, D3DCOLOR_XRGB(0x00, 0x00, 0x00)); - if(caps.stretchrect == false) { - surface->Release(); - } - } - -//clear primary display and all backbuffers - for(int i = 0; i < 3; i++) { - device->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00, 0x00, 0x00), 1.0f, 0); - device->Present(0, 0, 0, 0); - } -} - -bool VideoD3D::lock(uint16 *&data, uint &pitch) { - if(caps.stretchrect == false) { - texture->GetLevelDesc(0, &d3dsd); - texture->GetSurfaceLevel(0, &surface); - } - surface->LockRect(&d3dlr, 0, flags.lock); - pitch = d3dlr.Pitch; - data = (uint16*)d3dlr.pBits; - return data; -} - -void VideoD3D::unlock() { - surface->UnlockRect(); - if(caps.stretchrect == false)surface->Release(); -} - -void VideoD3D::refresh(uint r_width, uint r_height) { - if(!device)return; - - device->BeginScene(); - - if(caps.stretchrect == true) { - RECT rs; - SetRect(&rs, 0, 0, r_width, r_height); - LPDIRECT3DSURFACE9 temp; - device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &temp); - device->StretchRect(surface, &rs, temp, 0, static_cast(flags.filter)); - temp->Release(); - } else { - RECT rd; - GetClientRect(hwnd, &rd); - set_vertex(0, 0, r_width, r_height, 1024, 1024, 0, 0, rd.right, rd.bottom); - device->SetTexture(0, texture); - device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); - } - - device->EndScene(); - - if(settings.synchronize == true) { - D3DRASTER_STATUS status; - for(;;) { - device->GetRasterStatus(0, &status); - if(bool(status.InVBlank) == true)break; - //Sleep(1); - } - } - - device->Present(0, 0, 0, 0); -} - -void VideoD3D::init() { - term(); - update_video_mode(); -} - -void VideoD3D::term() { - safe_release(vertex_buffer); - safe_release(surface); - safe_release(texture); - safe_release(device); - safe_release(lpd3d); -} - -VideoD3D::VideoD3D(HWND handle) { - hwnd = handle; - - vertex_buffer = 0; - surface = 0; - texture = 0; - device = 0; - lpd3d = 0; -} - -VideoD3D::~VideoD3D() { -} - -#undef D3DVERTEX diff --git a/src/ui/video/d3d.h b/src/ui/video/d3d.h deleted file mode 100644 index c10d0a68..00000000 --- a/src/ui/video/d3d.h +++ /dev/null @@ -1,58 +0,0 @@ -#include - -class VideoD3D : public Video { -public: -HWND hwnd; -LPDIRECT3D9 lpd3d; -LPDIRECT3DDEVICE9 device; -LPDIRECT3DVERTEXBUFFER9 vertex_buffer, *vertex_ptr; -D3DPRESENT_PARAMETERS presentation; -D3DSURFACE_DESC d3dsd; -D3DLOCKED_RECT d3dlr; -D3DRASTER_STATUS d3drs; -D3DCAPS9 d3dcaps; -LPDIRECT3DTEXTURE9 texture; -LPDIRECT3DSURFACE9 surface; - -struct d3dvertex { - float x, y, z, rhw; //screen coords - uint32 color; //diffuse color - float u, v; //texture coords -}; - -struct { - uint32 t_usage, v_usage; - uint32 t_pool, v_pool; - uint32 lock; - uint32 filter; -} flags; - -struct { - bool dynamic; //device supports dynamic textures - bool addresswrap; //device supports texture address (u,v) wrapping - bool stretchrect; //device supports StretchRect -} caps; - - void set_vertex(uint32 px, uint32 py, uint32 pw, uint32 ph, - uint32 tw, uint32 th, uint32 x, uint32 y, uint32 w, uint32 h); - - bool lock(uint16 *&data, uint &pitch); - void unlock(); - - uint screen_width() { return GetSystemMetrics(SM_CXSCREEN); } - uint screen_height() { return GetSystemMetrics(SM_CYSCREEN); } - - bool update_video_mode(); - void update_settings(); - - bool capture_screenshot(); - - void init(); - void term(); - - void clear_video(); - void refresh(uint width, uint height); - - VideoD3D(HWND handle); - ~VideoD3D(); -}; diff --git a/src/ui/video/ddraw.cpp b/src/ui/video/ddraw.cpp deleted file mode 100644 index 3bc7ea71..00000000 --- a/src/ui/video/ddraw.cpp +++ /dev/null @@ -1,124 +0,0 @@ -void VideoDD::clear_video() { -DDBLTFX fx; - fx.dwSize = sizeof(DDBLTFX); - fx.dwFillColor = 0x00000000; - screen->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); - raster->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); -} - -bool VideoDD::lock(uint16 *&data, uint &pitch) { - if(raster->Lock(0, &ddsd, DDLOCK_WAIT, 0) != DD_OK) return false; - pitch = ddsd.lPitch; - data = (uint16*)ddsd.lpSurface; - return data; -} - -void VideoDD::unlock() { - raster->Unlock(0); -} - -void VideoDD::refresh(uint r_width, uint r_height) { - if(settings.synchronize) { - for(;;) { - BOOL in_vblank; - lpdd7->GetVerticalBlankStatus(&in_vblank); - if(bool(in_vblank) == true) break; - //Sleep(1); - } - } - -HRESULT hr; -RECT rd, rs; - SetRect(&rs, 0, 0, r_width, r_height); - -POINT p = { 0, 0 }; - ClientToScreen(hwnd, &p); - GetClientRect(hwnd, &rd); - OffsetRect(&rd, p.x, p.y); - - if(screen->Blt(&rd, raster, &rs, DDBLT_WAIT, 0) == DDERR_SURFACELOST) { - screen->Restore(); - raster->Restore(); - } -} - -void VideoDD::init() { - term(); - -// - DirectDrawCreate(0, &lpdd, 0); - lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7); - safe_release(lpdd); - - lpdd7->SetCooperativeLevel(hwnd, DDSCL_NORMAL); - - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - lpdd7->CreateSurface(&ddsd, &screen, 0); - - lpdd7->CreateClipper(0, &clipper, 0); - clipper->SetHWnd(0, hwnd); - screen->SetClipper(clipper); -// - - create_raster(); - clear_video(); -} - -void VideoDD::create_raster() { -int depth; - screen->GetSurfaceDesc(&ddsd); - depth = ddsd.ddpfPixelFormat.dwRGBBitCount; - if(depth == 15 || depth == 16 || config::video.use_vram == false) { - goto try_native_surface; - } - - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | - (config::video.use_vram == true ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY); - ddsd.dwWidth = 1024; - ddsd.dwHeight = 1024; - - ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - ddsd.ddpfPixelFormat.dwRGBBitCount = 16; - ddsd.ddpfPixelFormat.dwRBitMask = 0xf800; - ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0; - ddsd.ddpfPixelFormat.dwBBitMask = 0x001f; - - if(lpdd7->CreateSurface(&ddsd, &raster, 0) == DD_OK) return; - -try_native_surface: - memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | - (config::video.use_vram == true ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY); - ddsd.dwWidth = 1024; - ddsd.dwHeight = 1024; - - lpdd7->CreateSurface(&ddsd, &raster, 0); -} - -void VideoDD::term() { - safe_release(clipper); - safe_release(raster); - safe_release(screen); - safe_release(lpdd7); - safe_release(lpdd); -} - -VideoDD::VideoDD(HWND handle) { - hwnd = handle; - - lpdd = 0; - lpdd7 = 0; - screen = 0; - raster = 0; - clipper = 0; -} diff --git a/src/ui/video/ddraw.h b/src/ui/video/ddraw.h deleted file mode 100644 index afeaafa3..00000000 --- a/src/ui/video/ddraw.h +++ /dev/null @@ -1,24 +0,0 @@ -#include - -class VideoDD : public Video { -private: -HWND hwnd; -LPDIRECTDRAW lpdd; -LPDIRECTDRAW7 lpdd7; -LPDIRECTDRAWSURFACE7 screen, raster; -LPDIRECTDRAWCLIPPER clipper; -DDSURFACEDESC2 ddsd; -DDSCAPS2 ddscaps; - void create_raster(); - void clear_video(); - -public: - bool lock(uint16 *&data, uint &pitch); - void unlock(); - - void refresh(uint width, uint height); - void init(); - void term(); - - VideoDD(HWND handle); -}; diff --git a/src/ui/video/gdi.cpp b/src/ui/video/gdi.cpp deleted file mode 100644 index b79da962..00000000 --- a/src/ui/video/gdi.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "gdi.h" - -bool VideoGDI::lock(uint16 *&data, uint &pitch) { - pitch = 2048; - data = buffer; - return data; -} - -void VideoGDI::unlock() {} - -void VideoGDI::refresh(uint r_width, uint r_height) { -RECT rc; - GetClientRect(hwnd, &rc); - - SetDIBits(bitmapdc, bitmap, 0, r_height, (void*)buffer, &bmi, DIB_RGB_COLORS); -HDC hdc = GetDC(hwnd); - StretchBlt(hdc, rc.left, rc.top, rc.right, rc.bottom, bitmapdc, 0, 1024 - r_height, r_width, r_height, SRCCOPY); - ReleaseDC(hwnd, hdc); -} - -void VideoGDI::init() { -HDC hdc = GetDC(hwnd); - bitmapdc = CreateCompatibleDC(hdc); - assert(bitmapdc); - bitmap = CreateCompatibleBitmap(hdc, 1024, 1024); - assert(bitmap); - SelectObject(bitmapdc, bitmap); - ReleaseDC(hwnd, hdc); - - memset(&bmi, 0, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = 1024; - bmi.bmiHeader.biHeight = -1024; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 16; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = 1024 * 1024 * sizeof(uint16); - -//note: -//biBitCount of 15 is invalid, biBitCount of 16 is really RGB555 - - snes.set_video_pixel_format(SNES::PIXELFORMAT_RGB555); -} - -void VideoGDI::term() { - DeleteObject(bitmap); - DeleteDC(bitmapdc); -} - -VideoGDI::VideoGDI(HWND handle) { - hwnd = handle; - buffer = (uint16*)malloc(1024 * 1024 * sizeof(uint16)); -} - -VideoGDI::~VideoGDI() { - safe_free(buffer); -} diff --git a/src/ui/video/gtk.cpp b/src/ui/video/gtk.cpp deleted file mode 100644 index 8a5452bd..00000000 --- a/src/ui/video/gtk.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "gtk.h" - -bool VideoGTK::lock(uint16 *&data, uint &pitch) { - pitch = 1024 * 2; - data = buffer; - return data; -} - -void VideoGTK::unlock() {} - -void VideoGTK::refresh(uint r_width, uint r_height) { - for(uint y = 0; y < r_height; y++) { - uint8 *dest = gdkbuffer + y * 1024 * 3; - uint16 *src = buffer + y * 1024; - for(uint x = 0; x < r_width; x++) { - uint32 p = *src++; - uint32 pix = ((p & 0xf800) << 8) | ((p & 0x07e0) << 5) | ((p & 0x001f) << 3); - *dest++ = pix >> 16; - *dest++ = pix >> 8; - *dest++ = pix; - } - } - - gdk_draw_rgb_image(GDK_DRAWABLE(widget->window), - widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - 0, 0, r_width, r_height, - GDK_RGB_DITHER_NONE, gdkbuffer, 1024 * 3); -} - -void VideoGTK::init() { - buffer = (uint16*)malloc(1024 * 1024 * 2); - gdkbuffer = (uint8*) malloc(1024 * 1024 * 3); -} - -void VideoGTK::term() { - safe_free(buffer); - safe_free(gdkbuffer); -} - -VideoGTK::VideoGTK(GtkWidget *output_widget) { - widget = output_widget; -} diff --git a/src/ui/video/gtk.h b/src/ui/video/gtk.h deleted file mode 100644 index ddb79e84..00000000 --- a/src/ui/video/gtk.h +++ /dev/null @@ -1,21 +0,0 @@ -#include - -class VideoGTK : public Video { -private: -GtkWidget *widget; -uint16 *buffer; -uint8 *gdkbuffer; - -public: - bool lock(uint16 *&data, uint &pitch); - void unlock(); - - uint screen_width() { return gdk_screen_width(); } - uint screen_height() { return gdk_screen_height(); } - - void refresh(uint width, uint height); - void init(); - void term(); - - VideoGTK(GtkWidget *output_widget); -}; diff --git a/src/ui/video/video.cpp b/src/ui/video/video.cpp deleted file mode 100644 index 09e03b06..00000000 --- a/src/ui/video/video.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "video.h" diff --git a/src/ui/video/video.h b/src/ui/video/video.h deleted file mode 100644 index 6c88f619..00000000 --- a/src/ui/video/video.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef VIDEO_H -#define VIDEO_H - -class Video { public: - -struct Settings { - bool synchronize; - uint filter; - Settings() : synchronize(false), filter(0) {} -} settings; - -enum Filter { - FilterPoint, - FilterLinear, -}; - - virtual bool lock(uint16 *&data, uint &pitch) { return false; } - virtual void unlock() {} - - virtual void clear_video() {} - virtual void refresh(uint width, uint height) {} - virtual void init() {} - virtual void term() {} - - virtual void update_settings() {} - - Video() {} - virtual ~Video() {} -} *uiVideo; - -#endif diff --git a/src/ui/video/xv.cpp b/src/ui/video/xv.cpp deleted file mode 100644 index 95930ad7..00000000 --- a/src/ui/video/xv.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "xv.h" - -bool VideoXv::lock(uint16 *&data, uint &pitch) { - pitch = 1024 * 2; - data = buffer; - return data; -} - -void VideoXv::unlock() { -} - -void VideoXv::clear_video() { - memset(buffer, 0, 1024 * 1024 * sizeof(uint16)); -//clear twice in case video is double buffered ... - refresh(1024, 1024); - refresh(1024, 1024); -} - -void VideoXv::refresh(uint r_width, uint r_height) { -Window dw; -int d0, d1; -unsigned int d2, d3; -unsigned int width, height; - XGetGeometry(display, window, &dw, &d0, &d1, &width, &height, &d2, &d3); - -uint16 *input = (uint16*)buffer; -uint16 *output = (uint16*)xvimage->data; - for(int y = 0; y < r_height; y++) { - for(int x = 0; x < r_width >> 1; x++) { - uint16 p0 = *input++; - uint16 p1 = *input++; - - uint8 u = (utable[p0] + utable[p1]) >> 1; - uint8 v = (vtable[p0] + vtable[p1]) >> 1; - - *output++ = (u << 8) | ytable[p0]; - *output++ = (v << 8) | ytable[p1]; - } - input += 1024 - r_width; - output += 1024 - r_width; - } - - XvShmPutImage(display, xv_port, window, gc, xvimage, - 0, 0, r_width, r_height, - 0, 0, width, height, - true); -} - -void VideoXv::init() { -} - -void VideoXv::term() { -} - -void VideoXv::init_yuv_tables() { - ytable = (uint8*)malloc(65536); - utable = (uint8*)malloc(65536); - vtable = (uint8*)malloc(65536); - - for(uint i = 0; i < 65536; i++) { - //extract RGB565 color data from i - uint8 r = (i >> 11) & 31, g = (i >> 5) & 63, b = (i) & 31; - r = (r << 3) | (r >> 2); //R5->R8 - g = (g << 2) | (g >> 4); //G6->G8 - b = (b << 3) | (b >> 2); //B5->B8 - - //RGB->YUV conversion - int y = int( +(double(r) * 0.257) + (double(g) * 0.504) + (double(b) * 0.098) + 16.0 ); - int u = int( -(double(r) * 0.148) - (double(g) * 0.291) + (double(b) * 0.439) + 128.0 ); - int v = int( +(double(r) * 0.439) - (double(g) * 0.368) - (double(b) * 0.071) + 128.0 ); - - //RGB->YCbCr conversion - //double lr = 0.2126, lb = 0.0722, lg = (1.0 - lr - lb); - //int y = int( double(r) * lr + double(g) * lg + double(b) * lb ); - //int u = int( (double(b) - y) / (2.0 - 2.0 * lb) + 128.0 ); - //int v = int( (double(r) - y) / (2.0 - 2.0 * lr) + 128.0 ); - - ytable[i] = y < 0 ? 0 : y > 255 ? 255 : y; - utable[i] = u < 0 ? 0 : u > 255 ? 255 : u; - vtable[i] = v < 0 ? 0 : v > 255 ? 255 : v; - } -} - -VideoXv::VideoXv(unsigned long handle) { - buffer = (uint16*)malloc(1024 * 1024 * sizeof(uint16)); - window = handle; - display = XOpenDisplay(0); - screen = DefaultScreen(display); - gc = XCreateGC(display, window, 0, 0); - -XVisualInfo visual_info; - if(XMatchVisualInfo(display, screen, 24, TrueColor, &visual_info)) { - } else if(XMatchVisualInfo(display, screen, 16, TrueColor, &visual_info)) { - } else if(XMatchVisualInfo(display, screen, 15, TrueColor, &visual_info)) { - } else if(XMatchVisualInfo(display, screen, 8, PseudoColor, &visual_info)) { - } else if(XMatchVisualInfo(display, screen, 8, GrayScale, &visual_info)) { - } else if(XMatchVisualInfo(display, screen, 8, StaticGray, &visual_info)) { - } else if(XMatchVisualInfo(display, screen, 1, StaticGray, &visual_info)) { - } else { - printf("VideoXv: unable to find suitable video display.\n"); - } - - if(!XShmQueryExtension(display)) { printf("VideoXv: XShm extension not found.\n"); } - - xv_port = -1; -XvAdaptorInfo *adaptor_info; -unsigned int adaptor_count; - XvQueryAdaptors(display, DefaultRootWindow(display), &adaptor_count, &adaptor_info); - for(uint i = 0; i < adaptor_count; i++) { - //find adaptor that supports both input (memory->drawable) and image (drawable->screen) masks - if(adaptor_info[i].type & XvInputMask && adaptor_info[i].type & XvImageMask) { - xv_port = adaptor_info[i].base_id; - break; - } - } - XvFreeAdaptorInfo(adaptor_info); - if(xv_port == -1) { printf("VideoXv: failed to find valid XvPort.\n"); } - -//set colorkey to auto paint, so that Xv video output is always visible -const Atom atom = XInternAtom(display, "XV_AUTOPAINT_COLORKEY", true); - if(atom != None) { XvSetPortAttribute(display, xv_port, atom, 1); } - -//0x00000003 = 32-bit X8R8G8B8 [xRGB] (few drivers support this mode) -//0x32595559 = 16-bit Y8U8,Y8V8 [YUY2] (most drivers support this mode) - xvimage = XvShmCreateImage(display, xv_port, 0x32595559, 0, 1024, 1024, &shminfo); - if(!xvimage) { printf("VideoXv: XShmCreateImage failed.\n"); } - shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777); - shminfo.shmaddr = xvimage->data = (char*)shmat(shminfo.shmid, 0, 0); - shminfo.readOnly = false; - if(!XShmAttach(display, &shminfo)) { printf("VideoXv: XShmAttach failed.\n"); } - - init_yuv_tables(); - clear_video(); -} - -VideoXv::~VideoXv() { - XShmDetach(display, &shminfo); - safe_free(ytable); - safe_free(utable); - safe_free(vtable); -} diff --git a/src/ui/video/xv.h b/src/ui/video/xv.h deleted file mode 100644 index 168dffbc..00000000 --- a/src/ui/video/xv.h +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -extern "C" XvImage* XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*); - -class VideoXv : public Video { -private: -unsigned long window; -uint16 *buffer; -XvImage *xvimage; -GC gc; -Display *display; -int screen, xv_port; -XShmSegmentInfo shminfo; - -uint8 *ytable, *utable, *vtable; - -public: - bool lock(uint16 *&data, uint &pitch); - void unlock(); - - uint screen_width() { return gdk_screen_width(); } - uint screen_height() { return gdk_screen_height(); } - - void clear_video(); - void refresh(uint width, uint height); - void init(); - void term(); - - VideoXv(unsigned long handle); - ~VideoXv(); - -protected: - void init_yuv_tables(); -};