From fa1558319bbce195324fe4123f5a941cad9cafd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sat, 21 Mar 2020 18:35:43 -0400 Subject: [PATCH 001/105] Disable CI on non-master branches --- .github/workflows/build-ubuntu.yml | 8 +++++++- .github/workflows/build-windows.yml | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index fed0f3e2..b57c5b75 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -1,6 +1,12 @@ name: CMake Build (Ubuntu x86-64) -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master env: BUILD_TYPE: Release diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index c7d05d03..ec14e30a 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -1,6 +1,12 @@ name: CMake Build (Windows x86-64) -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master env: BUILD_TYPE: Release From de405ce8922713b78fe30c7612cbfc610578a474 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 14 Apr 2020 23:17:16 +0200 Subject: [PATCH 002/105] so, this is it this was a glorious fight, but I admit defeat --- melonDS.cbp | 2 ++ src/frontend/qt/main.cpp | 45 ++++++++++++++++++++++++++++++++++++++++ src/frontend/qt/main.h | 24 +++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/frontend/qt/main.cpp create mode 100644 src/frontend/qt/main.h diff --git a/melonDS.cbp b/melonDS.cbp index 8d900d1f..7305ee56 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -153,6 +153,8 @@ + + diff --git a/src/frontend/qt/main.cpp b/src/frontend/qt/main.cpp new file mode 100644 index 00000000..3f61ec65 --- /dev/null +++ b/src/frontend/qt/main.cpp @@ -0,0 +1,45 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include +#include + +// Qt includes and shit here, I guess + +#include "main.h" + +#include "../version.h" + + +// + + +int main(int argc, char** argv) +{ + srand(time(NULL)); + + printf("melonDS " MELONDS_VERSION "\n"); + printf(MELONDS_URL "\n"); + + printf("Arisotura hereby admits defeat\n"); + printf("NI DIEU NI MAITRE\n"); + + return 0; +} diff --git a/src/frontend/qt/main.h b/src/frontend/qt/main.h new file mode 100644 index 00000000..65d6518c --- /dev/null +++ b/src/frontend/qt/main.h @@ -0,0 +1,24 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MAIN_H +#define MAIN_H + +// put the class shit here + +#endif // MAIN_H From 07012575460d27ffa9def84b594f728607c4a70c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 14 Apr 2020 23:32:47 +0200 Subject: [PATCH 003/105] add credit for the icon --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cf0afed2..a34b7ea4 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ If everything went well, melonDS and the libraries it needs should now be in the * Martin for GBAtek, a good piece of documentation * Cydrak for the extra 3D GPU research + * limittox for the icon * All of you comrades who have been testing melonDS, reporting issues, suggesting shit, etc ## License From 231f0fc2e5e22b2d4907341cc191cfc9215556fb Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 14 Apr 2020 23:38:48 +0200 Subject: [PATCH 004/105] welp --- melonDS.cbp | 4 ++-- src/frontend/{qt => qt_sdl}/main.cpp | 0 src/frontend/{qt => qt_sdl}/main.h | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/frontend/{qt => qt_sdl}/main.cpp (100%) rename src/frontend/{qt => qt_sdl}/main.h (100%) diff --git a/melonDS.cbp b/melonDS.cbp index 7305ee56..2a33978d 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -153,8 +153,8 @@ - - + + diff --git a/src/frontend/qt/main.cpp b/src/frontend/qt_sdl/main.cpp similarity index 100% rename from src/frontend/qt/main.cpp rename to src/frontend/qt_sdl/main.cpp diff --git a/src/frontend/qt/main.h b/src/frontend/qt_sdl/main.h similarity index 100% rename from src/frontend/qt/main.h rename to src/frontend/qt_sdl/main.h From 053c0f65b4148d3539fa855aa8b64e5c06576ee3 Mon Sep 17 00:00:00 2001 From: Lucian Poston Date: Thu, 23 Apr 2020 17:45:58 -0500 Subject: [PATCH 005/105] Larger unemphasized screen, when possible --- src/libui_sdl/main.cpp | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 8e8bf9ec..ede2576a 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -1398,6 +1398,7 @@ void SetupScreenRects(int width, int height) // side-by-side int heightreq; + int emph_smaller_width; int startX = 0; width -= gap; @@ -1416,23 +1417,26 @@ void SetupScreenRects(int width, int height) else // emph. top/bottom { heightreq = ((width - screenW) * screenH) / screenW; + emph_smaller_width = screenW; if (heightreq > height) { - int newwidth = ((height * (width - screenW)) / heightreq) + screenW; - startX = (width - newwidth) / 2; + int maximal_width = 2 * (height * screenW / screenH); + maximal_width = maximal_width > width ? width : maximal_width; + emph_smaller_width = maximal_width - (height * screenW / screenH); + startX = (width - maximal_width) / 2; heightreq = height; - width = newwidth; + width = maximal_width; } } if (sizemode == 2) { - topscreen->Width = screenW; - topscreen->Height = screenH; + topscreen->Width = emph_smaller_width; + topscreen->Height = emph_smaller_width * screenH / screenW; } else { - topscreen->Width = (sizemode==0) ? (width / 2) : (width - screenW); + topscreen->Width = (sizemode==0) ? (width / 2) : (width - emph_smaller_width); topscreen->Height = heightreq; } topscreen->X = startX; @@ -1442,8 +1446,8 @@ void SetupScreenRects(int width, int height) if (sizemode == 1) { - bottomscreen->Width = screenW; - bottomscreen->Height = screenH; + bottomscreen->Width = emph_smaller_width; + bottomscreen->Height = emph_smaller_width * screenH / screenW; } else { @@ -1457,6 +1461,7 @@ void SetupScreenRects(int width, int height) // top then bottom int widthreq; + int emph_smaller_height; int startY = 0; height -= gap; @@ -1475,24 +1480,27 @@ void SetupScreenRects(int width, int height) else // emph. top/bottom { widthreq = ((height - screenH) * screenW) / screenH; + emph_smaller_height = screenH; if (widthreq > width) { - int newheight = ((width * (height - screenH)) / widthreq) + screenH; - startY = (height - newheight) / 2; + int maximal_height = 2 * (width * screenH / screenW); + maximal_height = maximal_height > height ? height : maximal_height; + emph_smaller_height = maximal_height - (width * screenH / screenW); + startY = (height - maximal_height) / 2; widthreq = width; - height = newheight; + height = maximal_height; } } if (sizemode == 2) { - topscreen->Width = screenW; - topscreen->Height = screenH; + topscreen->Width = emph_smaller_height * screenW / screenH; + topscreen->Height = emph_smaller_height; } else { topscreen->Width = widthreq; - topscreen->Height = (sizemode==0) ? (height / 2) : (height - screenH); + topscreen->Height = (sizemode==0) ? (height / 2) : (height - emph_smaller_height); } topscreen->Y = startY; topscreen->X = (width - topscreen->Width) / 2; @@ -1501,8 +1509,8 @@ void SetupScreenRects(int width, int height) if (sizemode == 1) { - bottomscreen->Width = screenW; - bottomscreen->Height = screenH; + bottomscreen->Width = emph_smaller_height * screenW / screenH; + bottomscreen->Height = emph_smaller_height; } else { From 5ef71181c891aceec9db7297d1642b0e70e98911 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 25 Apr 2020 15:04:46 +0200 Subject: [PATCH 006/105] goodbye old CodeBlocks project --- melonDS.cbp | 292 ---------------------------------------------------- 1 file changed, 292 deletions(-) delete mode 100644 melonDS.cbp diff --git a/melonDS.cbp b/melonDS.cbp deleted file mode 100644 index 8d900d1f..00000000 --- a/melonDS.cbp +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - From a85d41c53eed50f188502925ed34674397b86550 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 25 Apr 2020 18:51:08 +0200 Subject: [PATCH 007/105] berp. --- src/libui_sdl/CMakeLists.txt | 73 - src/libui_sdl/DlgAudioSettings.cpp | 197 -- src/libui_sdl/DlgAudioSettings.h | 30 - src/libui_sdl/DlgEmuSettings.cpp | 117 - src/libui_sdl/DlgEmuSettings.h | 30 - src/libui_sdl/DlgInputConfig.cpp | 663 ---- src/libui_sdl/DlgInputConfig.h | 31 - src/libui_sdl/DlgVideoSettings.cpp | 354 -- src/libui_sdl/DlgVideoSettings.h | 30 - src/libui_sdl/DlgWifiSettings.cpp | 271 -- src/libui_sdl/DlgWifiSettings.h | 31 - src/libui_sdl/LAN_PCap.cpp | 387 --- src/libui_sdl/LAN_PCap.h | 53 - src/libui_sdl/LAN_Socket.cpp | 1145 ------- src/libui_sdl/LAN_Socket.h | 38 - src/libui_sdl/MelonCap.cpp | 347 -- src/libui_sdl/MelonCap.h | 34 - src/libui_sdl/OSD.cpp | 435 --- src/libui_sdl/OSD.h | 35 - src/libui_sdl/Platform.cpp | 557 --- src/libui_sdl/PlatformConfig.cpp | 151 - src/libui_sdl/PlatformConfig.h | 82 - src/libui_sdl/font.h | 135 - src/libui_sdl/libui/.travis.yml | 23 - src/libui_sdl/libui/ANNOUNCE.md | 22 - src/libui_sdl/libui/CMakeLists.txt | 219 -- src/libui_sdl/libui/Changelog.md | 33 - src/libui_sdl/libui/Compatibility.md | 141 - src/libui_sdl/libui/LICENSE | 9 - src/libui_sdl/libui/README.md | 185 - src/libui_sdl/libui/TODO.md | 129 - .../libui/_abort/windowevents/darwin_window.m | 90 - .../libui/_abort/windowevents/page15.c | 65 - src/libui_sdl/libui/_abort/windowevents/ui.h | 6 - .../libui/_abort/windowevents/unix_window.c | 97 - .../_abort/windowevents/windows_window.cpp | 86 - src/libui_sdl/libui/_wip/rules.darwin | 6 - src/libui_sdl/libui/_wip/rules.unix | 3 - src/libui_sdl/libui/_wip/sv/normal | 25 - src/libui_sdl/libui/_wip/sv/normal.nots | 25 - src/libui_sdl/libui/_wip/sv/outlineview | 25 - src/libui_sdl/libui/_wip/sv/outlineview.nots | 25 - src/libui_sdl/libui/_wip/sv/sourcelist | 25 - src/libui_sdl/libui/_wip/sv/sourcelist.nots | 25 - src/libui_sdl/libui/_wip/sv/tableview | 25 - src/libui_sdl/libui/_wip/sv/tableview.nots | 25 - src/libui_sdl/libui/_wip/sv/textview | 25 - src/libui_sdl/libui/_wip/sv/textview.nots | 25 - src/libui_sdl/libui/_wip/table/test_page9.c | 80 - src/libui_sdl/libui/_wip/table/ui.h | 46 - src/libui_sdl/libui/_wip/table/unix_table.c | 87 - .../libui/_wip/table/unix_tablemodel.c | 303 -- src/libui_sdl/libui/common/CMakeLists.txt | 16 - src/libui_sdl/libui/common/areaevents.c | 167 - src/libui_sdl/libui/common/control.c | 117 - src/libui_sdl/libui/common/controlsigs.h | 25 - src/libui_sdl/libui/common/debug.c | 21 - src/libui_sdl/libui/common/matrix.c | 50 - src/libui_sdl/libui/common/shouldquit.c | 22 - src/libui_sdl/libui/common/uipriv.h | 58 - src/libui_sdl/libui/common/userbugs.c | 8 - src/libui_sdl/libui/darwin/CMakeLists.txt | 79 - src/libui_sdl/libui/darwin/alloc.m | 89 - src/libui_sdl/libui/darwin/area.m | 475 --- src/libui_sdl/libui/darwin/areaevents.m | 159 - src/libui_sdl/libui/darwin/autolayout.m | 161 - src/libui_sdl/libui/darwin/box.m | 469 --- src/libui_sdl/libui/darwin/button.m | 113 - src/libui_sdl/libui/darwin/checkbox.m | 129 - src/libui_sdl/libui/darwin/colorbutton.m | 159 - src/libui_sdl/libui/darwin/combobox.m | 145 - src/libui_sdl/libui/darwin/control.m | 84 - src/libui_sdl/libui/darwin/datetimepicker.m | 42 - src/libui_sdl/libui/darwin/debug.m | 19 - src/libui_sdl/libui/darwin/draw.m | 454 --- src/libui_sdl/libui/darwin/drawtext.m | 655 ---- src/libui_sdl/libui/darwin/editablecombo.m | 185 - src/libui_sdl/libui/darwin/entry.m | 251 -- src/libui_sdl/libui/darwin/fontbutton.m | 218 -- src/libui_sdl/libui/darwin/form.m | 561 --- src/libui_sdl/libui/darwin/grid.m | 800 ----- src/libui_sdl/libui/darwin/group.m | 194 -- src/libui_sdl/libui/darwin/image.m | 82 - src/libui_sdl/libui/darwin/label.m | 43 - src/libui_sdl/libui/darwin/main.m | 239 -- src/libui_sdl/libui/darwin/map.m | 59 - src/libui_sdl/libui/darwin/menu.m | 368 -- src/libui_sdl/libui/darwin/multilineentry.m | 233 -- src/libui_sdl/libui/darwin/progressbar.m | 78 - src/libui_sdl/libui/darwin/radiobuttons.m | 207 -- src/libui_sdl/libui/darwin/scrollview.m | 61 - src/libui_sdl/libui/darwin/separator.m | 45 - src/libui_sdl/libui/darwin/slider.m | 147 - src/libui_sdl/libui/darwin/spinbox.m | 214 -- src/libui_sdl/libui/darwin/stddialogs.m | 123 - src/libui_sdl/libui/darwin/tab.m | 292 -- src/libui_sdl/libui/darwin/text.m | 19 - src/libui_sdl/libui/darwin/uipriv_darwin.h | 146 - src/libui_sdl/libui/darwin/util.m | 15 - src/libui_sdl/libui/darwin/window.m | 407 --- src/libui_sdl/libui/darwin/winmoveresize.m | 253 -- src/libui_sdl/libui/doc/area.md | 53 - src/libui_sdl/libui/doc/areahandler | 1 - src/libui_sdl/libui/doc/draw.md | 42 - src/libui_sdl/libui/doc/drawtext | 13 - src/libui_sdl/libui/doc/export/coretext | 5 - src/libui_sdl/libui/doc/form | 1 - src/libui_sdl/libui/doc/main | 1 - src/libui_sdl/libui/doc/mainsteps | 1 - src/libui_sdl/libui/doc/slider | 1 - src/libui_sdl/libui/doc/spinbox | 1 - src/libui_sdl/libui/doc/static | 2 - src/libui_sdl/libui/doc/windowmovesize | 3 - src/libui_sdl/libui/doc/winstatic | 1 - src/libui_sdl/libui/examples/CMakeLists.txt | 38 - .../libui/examples/controlgallery/darwin.png | Bin 97260 -> 0 bytes .../libui/examples/controlgallery/main.c | 540 --- .../libui/examples/controlgallery/unix.png | Bin 41757 -> 0 bytes .../libui/examples/controlgallery/windows.png | Bin 48217 -> 0 bytes .../libui/examples/cpp-multithread/main.cpp | 92 - src/libui_sdl/libui/examples/example.manifest | 20 - .../libui/examples/example.static.manifest | 32 - src/libui_sdl/libui/examples/histogram/main.c | 309 -- src/libui_sdl/libui/examples/resources.rc | 13 - src/libui_sdl/libui/nowintable.diff | 50 - src/libui_sdl/libui/oldhaiku.tgz | Bin 13965 -> 0 bytes src/libui_sdl/libui/test/CMakeLists.txt | 38 - src/libui_sdl/libui/test/drawtests.c | 1978 ----------- .../images/andlabs_16x16test_24june2016.png | Bin 272 -> 0 bytes .../images/andlabs_32x32test_24june2016.png | Bin 432 -> 0 bytes src/libui_sdl/libui/test/images/gen.go | 98 - ...heme-0.8.90_16x16_x-office-spreadsheet.png | Bin 704 -> 0 bytes ...heme-0.8.90_32x32_x-office-spreadsheet.png | Bin 1518 -> 0 bytes src/libui_sdl/libui/test/main.c | 180 - src/libui_sdl/libui/test/menus.c | 112 - src/libui_sdl/libui/test/page1.c | 171 - src/libui_sdl/libui/test/page10.c | 185 - src/libui_sdl/libui/test/page11.c | 54 - src/libui_sdl/libui/test/page12.c | 60 - src/libui_sdl/libui/test/page13.c | 157 - src/libui_sdl/libui/test/page14.c | 350 -- src/libui_sdl/libui/test/page15.c | 260 -- src/libui_sdl/libui/test/page2.c | 215 -- src/libui_sdl/libui/test/page3.c | 69 - src/libui_sdl/libui/test/page4.c | 165 - src/libui_sdl/libui/test/page5.c | 99 - src/libui_sdl/libui/test/page6.c | 126 - src/libui_sdl/libui/test/page7.c | 25 - src/libui_sdl/libui/test/page7a.c | 139 - src/libui_sdl/libui/test/page7b.c | 71 - src/libui_sdl/libui/test/page7c.c | 133 - src/libui_sdl/libui/test/page8.c | 46 - src/libui_sdl/libui/test/page9.c | 289 -- src/libui_sdl/libui/test/resources.rc | 13 - src/libui_sdl/libui/test/spaced.c | 177 - src/libui_sdl/libui/test/test.h | 91 - src/libui_sdl/libui/test/test.manifest | 20 - src/libui_sdl/libui/test/test.static.manifest | 32 - src/libui_sdl/libui/ui.h | 763 ----- src/libui_sdl/libui/ui_darwin.h | 224 -- src/libui_sdl/libui/ui_unix.h | 154 - src/libui_sdl/libui/ui_windows.h | 280 -- src/libui_sdl/libui/unix/CMakeLists.txt | 87 - src/libui_sdl/libui/unix/alloc.c | 84 - src/libui_sdl/libui/unix/area.c | 853 ----- src/libui_sdl/libui/unix/box.c | 159 - src/libui_sdl/libui/unix/button.c | 57 - src/libui_sdl/libui/unix/cellrendererbutton.c | 299 -- src/libui_sdl/libui/unix/checkbox.c | 78 - src/libui_sdl/libui/unix/child.c | 120 - src/libui_sdl/libui/unix/colorbutton.c | 80 - src/libui_sdl/libui/unix/combobox.c | 66 - src/libui_sdl/libui/unix/control.c | 14 - src/libui_sdl/libui/unix/datetimepicker.c | 599 ---- src/libui_sdl/libui/unix/debug.c | 14 - src/libui_sdl/libui/unix/draw.c | 214 -- src/libui_sdl/libui/unix/draw.h | 21 - src/libui_sdl/libui/unix/drawmatrix.c | 115 - src/libui_sdl/libui/unix/drawpath.c | 199 -- src/libui_sdl/libui/unix/drawtext.c | 293 -- src/libui_sdl/libui/unix/editablecombo.c | 79 - src/libui_sdl/libui/unix/entry.c | 97 - src/libui_sdl/libui/unix/fontbutton.c | 70 - src/libui_sdl/libui/unix/form.c | 159 - src/libui_sdl/libui/unix/future.c | 42 - src/libui_sdl/libui/unix/gl.c | 251 -- src/libui_sdl/libui/unix/graphemes.c | 31 - src/libui_sdl/libui/unix/grid.c | 141 - src/libui_sdl/libui/unix/group.c | 89 - src/libui_sdl/libui/unix/image.c | 120 - src/libui_sdl/libui/unix/label.c | 36 - src/libui_sdl/libui/unix/main.c | 147 - src/libui_sdl/libui/unix/menu.c | 432 --- src/libui_sdl/libui/unix/multilineentry.c | 124 - src/libui_sdl/libui/unix/progressbar.c | 71 - src/libui_sdl/libui/unix/radiobuttons.c | 121 - src/libui_sdl/libui/unix/separator.c | 34 - src/libui_sdl/libui/unix/slider.c | 71 - src/libui_sdl/libui/unix/spinbox.c | 72 - src/libui_sdl/libui/unix/stddialogs.c | 116 - src/libui_sdl/libui/unix/tab.c | 97 - src/libui_sdl/libui/unix/text.c | 12 - src/libui_sdl/libui/unix/uipriv_unix.h | 71 - src/libui_sdl/libui/unix/util.c | 10 - src/libui_sdl/libui/unix/window.c | 462 --- src/libui_sdl/libui/windows/CMakeLists.txt | 92 - .../libui/windows/_uipriv_migrate.hpp | 61 - src/libui_sdl/libui/windows/alloc.cpp | 64 - src/libui_sdl/libui/windows/area.cpp | 291 -- src/libui_sdl/libui/windows/area.hpp | 56 - src/libui_sdl/libui/windows/areadraw.cpp | 170 - src/libui_sdl/libui/windows/areaevents.cpp | 435 --- src/libui_sdl/libui/windows/areascroll.cpp | 247 -- src/libui_sdl/libui/windows/areautil.cpp | 53 - src/libui_sdl/libui/windows/box.cpp | 324 -- src/libui_sdl/libui/windows/button.cpp | 126 - src/libui_sdl/libui/windows/checkbox.cpp | 117 - src/libui_sdl/libui/windows/colorbutton.cpp | 192 -- src/libui_sdl/libui/windows/colordialog.cpp | 1255 ------- src/libui_sdl/libui/windows/combobox.cpp | 110 - src/libui_sdl/libui/windows/compilerver.hpp | 13 - src/libui_sdl/libui/windows/container.cpp | 110 - src/libui_sdl/libui/windows/control.cpp | 121 - src/libui_sdl/libui/windows/d2dscratch.cpp | 166 - .../libui/windows/datetimepicker.cpp | 191 -- src/libui_sdl/libui/windows/debug.cpp | 84 - src/libui_sdl/libui/windows/draw.cpp | 578 ---- src/libui_sdl/libui/windows/draw.hpp | 24 - src/libui_sdl/libui/windows/drawmatrix.cpp | 117 - src/libui_sdl/libui/windows/drawpath.cpp | 246 -- src/libui_sdl/libui/windows/drawtext.cpp | 531 --- src/libui_sdl/libui/windows/dwrite.cpp | 88 - src/libui_sdl/libui/windows/editablecombo.cpp | 115 - src/libui_sdl/libui/windows/entry.cpp | 134 - src/libui_sdl/libui/windows/events.cpp | 151 - src/libui_sdl/libui/windows/fontbutton.cpp | 122 - src/libui_sdl/libui/windows/fontdialog.cpp | 686 ---- src/libui_sdl/libui/windows/form.cpp | 326 -- src/libui_sdl/libui/windows/gl.cpp | 196 -- src/libui_sdl/libui/windows/graphemes.cpp | 80 - src/libui_sdl/libui/windows/grid.cpp | 665 ---- src/libui_sdl/libui/windows/group.cpp | 224 -- src/libui_sdl/libui/windows/init.cpp | 167 - src/libui_sdl/libui/windows/label.cpp | 57 - src/libui_sdl/libui/windows/libui.manifest | 31 - src/libui_sdl/libui/windows/main.cpp | 130 - src/libui_sdl/libui/windows/menu.cpp | 420 --- .../libui/windows/multilineentry.cpp | 152 - src/libui_sdl/libui/windows/notes | 3 - src/libui_sdl/libui/windows/parent.cpp | 144 - src/libui_sdl/libui/windows/progressbar.cpp | 83 - src/libui_sdl/libui/windows/radiobuttons.cpp | 196 -- src/libui_sdl/libui/windows/resources.hpp | 37 - src/libui_sdl/libui/windows/resources.rc | 96 - src/libui_sdl/libui/windows/separator.cpp | 69 - src/libui_sdl/libui/windows/sizing.cpp | 62 - src/libui_sdl/libui/windows/slider.cpp | 98 - src/libui_sdl/libui/windows/spinbox.cpp | 215 -- src/libui_sdl/libui/windows/stddialogs.cpp | 167 - src/libui_sdl/libui/windows/tab.cpp | 294 -- src/libui_sdl/libui/windows/tabpage.cpp | 131 - src/libui_sdl/libui/windows/text.cpp | 106 - .../libui/windows/uipriv_windows.hpp | 164 - src/libui_sdl/libui/windows/utf16.cpp | 153 - src/libui_sdl/libui/windows/utilwin.cpp | 76 - src/libui_sdl/libui/windows/winapi.hpp | 55 - src/libui_sdl/libui/windows/window.cpp | 665 ---- src/libui_sdl/libui/windows/winpublic.cpp | 61 - src/libui_sdl/libui/windows/winutil.cpp | 143 - src/libui_sdl/main.cpp | 3029 ----------------- src/libui_sdl/main_shaders.h | 250 -- 271 files changed, 46177 deletions(-) delete mode 100644 src/libui_sdl/CMakeLists.txt delete mode 100644 src/libui_sdl/DlgAudioSettings.cpp delete mode 100644 src/libui_sdl/DlgAudioSettings.h delete mode 100644 src/libui_sdl/DlgEmuSettings.cpp delete mode 100644 src/libui_sdl/DlgEmuSettings.h delete mode 100644 src/libui_sdl/DlgInputConfig.cpp delete mode 100644 src/libui_sdl/DlgInputConfig.h delete mode 100644 src/libui_sdl/DlgVideoSettings.cpp delete mode 100644 src/libui_sdl/DlgVideoSettings.h delete mode 100644 src/libui_sdl/DlgWifiSettings.cpp delete mode 100644 src/libui_sdl/DlgWifiSettings.h delete mode 100644 src/libui_sdl/LAN_PCap.cpp delete mode 100644 src/libui_sdl/LAN_PCap.h delete mode 100644 src/libui_sdl/LAN_Socket.cpp delete mode 100644 src/libui_sdl/LAN_Socket.h delete mode 100644 src/libui_sdl/MelonCap.cpp delete mode 100644 src/libui_sdl/MelonCap.h delete mode 100644 src/libui_sdl/OSD.cpp delete mode 100644 src/libui_sdl/OSD.h delete mode 100644 src/libui_sdl/Platform.cpp delete mode 100644 src/libui_sdl/PlatformConfig.cpp delete mode 100644 src/libui_sdl/PlatformConfig.h delete mode 100644 src/libui_sdl/font.h delete mode 100644 src/libui_sdl/libui/.travis.yml delete mode 100644 src/libui_sdl/libui/ANNOUNCE.md delete mode 100644 src/libui_sdl/libui/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/Changelog.md delete mode 100644 src/libui_sdl/libui/Compatibility.md delete mode 100644 src/libui_sdl/libui/LICENSE delete mode 100644 src/libui_sdl/libui/README.md delete mode 100644 src/libui_sdl/libui/TODO.md delete mode 100644 src/libui_sdl/libui/_abort/windowevents/darwin_window.m delete mode 100644 src/libui_sdl/libui/_abort/windowevents/page15.c delete mode 100644 src/libui_sdl/libui/_abort/windowevents/ui.h delete mode 100644 src/libui_sdl/libui/_abort/windowevents/unix_window.c delete mode 100644 src/libui_sdl/libui/_abort/windowevents/windows_window.cpp delete mode 100644 src/libui_sdl/libui/_wip/rules.darwin delete mode 100644 src/libui_sdl/libui/_wip/rules.unix delete mode 100644 src/libui_sdl/libui/_wip/sv/normal delete mode 100644 src/libui_sdl/libui/_wip/sv/normal.nots delete mode 100644 src/libui_sdl/libui/_wip/sv/outlineview delete mode 100644 src/libui_sdl/libui/_wip/sv/outlineview.nots delete mode 100644 src/libui_sdl/libui/_wip/sv/sourcelist delete mode 100644 src/libui_sdl/libui/_wip/sv/sourcelist.nots delete mode 100644 src/libui_sdl/libui/_wip/sv/tableview delete mode 100644 src/libui_sdl/libui/_wip/sv/tableview.nots delete mode 100644 src/libui_sdl/libui/_wip/sv/textview delete mode 100644 src/libui_sdl/libui/_wip/sv/textview.nots delete mode 100644 src/libui_sdl/libui/_wip/table/test_page9.c delete mode 100644 src/libui_sdl/libui/_wip/table/ui.h delete mode 100644 src/libui_sdl/libui/_wip/table/unix_table.c delete mode 100644 src/libui_sdl/libui/_wip/table/unix_tablemodel.c delete mode 100644 src/libui_sdl/libui/common/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/common/areaevents.c delete mode 100644 src/libui_sdl/libui/common/control.c delete mode 100644 src/libui_sdl/libui/common/controlsigs.h delete mode 100644 src/libui_sdl/libui/common/debug.c delete mode 100644 src/libui_sdl/libui/common/matrix.c delete mode 100644 src/libui_sdl/libui/common/shouldquit.c delete mode 100644 src/libui_sdl/libui/common/uipriv.h delete mode 100644 src/libui_sdl/libui/common/userbugs.c delete mode 100644 src/libui_sdl/libui/darwin/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/darwin/alloc.m delete mode 100644 src/libui_sdl/libui/darwin/area.m delete mode 100644 src/libui_sdl/libui/darwin/areaevents.m delete mode 100644 src/libui_sdl/libui/darwin/autolayout.m delete mode 100644 src/libui_sdl/libui/darwin/box.m delete mode 100644 src/libui_sdl/libui/darwin/button.m delete mode 100644 src/libui_sdl/libui/darwin/checkbox.m delete mode 100644 src/libui_sdl/libui/darwin/colorbutton.m delete mode 100644 src/libui_sdl/libui/darwin/combobox.m delete mode 100644 src/libui_sdl/libui/darwin/control.m delete mode 100644 src/libui_sdl/libui/darwin/datetimepicker.m delete mode 100644 src/libui_sdl/libui/darwin/debug.m delete mode 100644 src/libui_sdl/libui/darwin/draw.m delete mode 100644 src/libui_sdl/libui/darwin/drawtext.m delete mode 100644 src/libui_sdl/libui/darwin/editablecombo.m delete mode 100644 src/libui_sdl/libui/darwin/entry.m delete mode 100644 src/libui_sdl/libui/darwin/fontbutton.m delete mode 100644 src/libui_sdl/libui/darwin/form.m delete mode 100644 src/libui_sdl/libui/darwin/grid.m delete mode 100644 src/libui_sdl/libui/darwin/group.m delete mode 100644 src/libui_sdl/libui/darwin/image.m delete mode 100644 src/libui_sdl/libui/darwin/label.m delete mode 100644 src/libui_sdl/libui/darwin/main.m delete mode 100644 src/libui_sdl/libui/darwin/map.m delete mode 100644 src/libui_sdl/libui/darwin/menu.m delete mode 100644 src/libui_sdl/libui/darwin/multilineentry.m delete mode 100644 src/libui_sdl/libui/darwin/progressbar.m delete mode 100644 src/libui_sdl/libui/darwin/radiobuttons.m delete mode 100644 src/libui_sdl/libui/darwin/scrollview.m delete mode 100644 src/libui_sdl/libui/darwin/separator.m delete mode 100644 src/libui_sdl/libui/darwin/slider.m delete mode 100644 src/libui_sdl/libui/darwin/spinbox.m delete mode 100644 src/libui_sdl/libui/darwin/stddialogs.m delete mode 100644 src/libui_sdl/libui/darwin/tab.m delete mode 100644 src/libui_sdl/libui/darwin/text.m delete mode 100644 src/libui_sdl/libui/darwin/uipriv_darwin.h delete mode 100644 src/libui_sdl/libui/darwin/util.m delete mode 100644 src/libui_sdl/libui/darwin/window.m delete mode 100644 src/libui_sdl/libui/darwin/winmoveresize.m delete mode 100644 src/libui_sdl/libui/doc/area.md delete mode 100644 src/libui_sdl/libui/doc/areahandler delete mode 100644 src/libui_sdl/libui/doc/draw.md delete mode 100644 src/libui_sdl/libui/doc/drawtext delete mode 100644 src/libui_sdl/libui/doc/export/coretext delete mode 100644 src/libui_sdl/libui/doc/form delete mode 100644 src/libui_sdl/libui/doc/main delete mode 100644 src/libui_sdl/libui/doc/mainsteps delete mode 100644 src/libui_sdl/libui/doc/slider delete mode 100644 src/libui_sdl/libui/doc/spinbox delete mode 100644 src/libui_sdl/libui/doc/static delete mode 100644 src/libui_sdl/libui/doc/windowmovesize delete mode 100644 src/libui_sdl/libui/doc/winstatic delete mode 100644 src/libui_sdl/libui/examples/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/examples/controlgallery/darwin.png delete mode 100644 src/libui_sdl/libui/examples/controlgallery/main.c delete mode 100644 src/libui_sdl/libui/examples/controlgallery/unix.png delete mode 100644 src/libui_sdl/libui/examples/controlgallery/windows.png delete mode 100644 src/libui_sdl/libui/examples/cpp-multithread/main.cpp delete mode 100644 src/libui_sdl/libui/examples/example.manifest delete mode 100644 src/libui_sdl/libui/examples/example.static.manifest delete mode 100644 src/libui_sdl/libui/examples/histogram/main.c delete mode 100644 src/libui_sdl/libui/examples/resources.rc delete mode 100644 src/libui_sdl/libui/nowintable.diff delete mode 100644 src/libui_sdl/libui/oldhaiku.tgz delete mode 100644 src/libui_sdl/libui/test/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/test/drawtests.c delete mode 100644 src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.png delete mode 100644 src/libui_sdl/libui/test/images/andlabs_32x32test_24june2016.png delete mode 100644 src/libui_sdl/libui/test/images/gen.go delete mode 100644 src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png delete mode 100644 src/libui_sdl/libui/test/images/tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png delete mode 100644 src/libui_sdl/libui/test/main.c delete mode 100644 src/libui_sdl/libui/test/menus.c delete mode 100644 src/libui_sdl/libui/test/page1.c delete mode 100644 src/libui_sdl/libui/test/page10.c delete mode 100644 src/libui_sdl/libui/test/page11.c delete mode 100644 src/libui_sdl/libui/test/page12.c delete mode 100644 src/libui_sdl/libui/test/page13.c delete mode 100644 src/libui_sdl/libui/test/page14.c delete mode 100644 src/libui_sdl/libui/test/page15.c delete mode 100644 src/libui_sdl/libui/test/page2.c delete mode 100644 src/libui_sdl/libui/test/page3.c delete mode 100644 src/libui_sdl/libui/test/page4.c delete mode 100644 src/libui_sdl/libui/test/page5.c delete mode 100644 src/libui_sdl/libui/test/page6.c delete mode 100644 src/libui_sdl/libui/test/page7.c delete mode 100644 src/libui_sdl/libui/test/page7a.c delete mode 100644 src/libui_sdl/libui/test/page7b.c delete mode 100644 src/libui_sdl/libui/test/page7c.c delete mode 100644 src/libui_sdl/libui/test/page8.c delete mode 100644 src/libui_sdl/libui/test/page9.c delete mode 100644 src/libui_sdl/libui/test/resources.rc delete mode 100644 src/libui_sdl/libui/test/spaced.c delete mode 100644 src/libui_sdl/libui/test/test.h delete mode 100644 src/libui_sdl/libui/test/test.manifest delete mode 100644 src/libui_sdl/libui/test/test.static.manifest delete mode 100644 src/libui_sdl/libui/ui.h delete mode 100644 src/libui_sdl/libui/ui_darwin.h delete mode 100644 src/libui_sdl/libui/ui_unix.h delete mode 100644 src/libui_sdl/libui/ui_windows.h delete mode 100644 src/libui_sdl/libui/unix/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/unix/alloc.c delete mode 100644 src/libui_sdl/libui/unix/area.c delete mode 100644 src/libui_sdl/libui/unix/box.c delete mode 100644 src/libui_sdl/libui/unix/button.c delete mode 100644 src/libui_sdl/libui/unix/cellrendererbutton.c delete mode 100644 src/libui_sdl/libui/unix/checkbox.c delete mode 100644 src/libui_sdl/libui/unix/child.c delete mode 100644 src/libui_sdl/libui/unix/colorbutton.c delete mode 100644 src/libui_sdl/libui/unix/combobox.c delete mode 100644 src/libui_sdl/libui/unix/control.c delete mode 100644 src/libui_sdl/libui/unix/datetimepicker.c delete mode 100644 src/libui_sdl/libui/unix/debug.c delete mode 100644 src/libui_sdl/libui/unix/draw.c delete mode 100644 src/libui_sdl/libui/unix/draw.h delete mode 100644 src/libui_sdl/libui/unix/drawmatrix.c delete mode 100644 src/libui_sdl/libui/unix/drawpath.c delete mode 100644 src/libui_sdl/libui/unix/drawtext.c delete mode 100644 src/libui_sdl/libui/unix/editablecombo.c delete mode 100644 src/libui_sdl/libui/unix/entry.c delete mode 100644 src/libui_sdl/libui/unix/fontbutton.c delete mode 100644 src/libui_sdl/libui/unix/form.c delete mode 100644 src/libui_sdl/libui/unix/future.c delete mode 100644 src/libui_sdl/libui/unix/gl.c delete mode 100644 src/libui_sdl/libui/unix/graphemes.c delete mode 100644 src/libui_sdl/libui/unix/grid.c delete mode 100644 src/libui_sdl/libui/unix/group.c delete mode 100644 src/libui_sdl/libui/unix/image.c delete mode 100644 src/libui_sdl/libui/unix/label.c delete mode 100644 src/libui_sdl/libui/unix/main.c delete mode 100644 src/libui_sdl/libui/unix/menu.c delete mode 100644 src/libui_sdl/libui/unix/multilineentry.c delete mode 100644 src/libui_sdl/libui/unix/progressbar.c delete mode 100644 src/libui_sdl/libui/unix/radiobuttons.c delete mode 100644 src/libui_sdl/libui/unix/separator.c delete mode 100644 src/libui_sdl/libui/unix/slider.c delete mode 100644 src/libui_sdl/libui/unix/spinbox.c delete mode 100644 src/libui_sdl/libui/unix/stddialogs.c delete mode 100644 src/libui_sdl/libui/unix/tab.c delete mode 100644 src/libui_sdl/libui/unix/text.c delete mode 100644 src/libui_sdl/libui/unix/uipriv_unix.h delete mode 100644 src/libui_sdl/libui/unix/util.c delete mode 100644 src/libui_sdl/libui/unix/window.c delete mode 100644 src/libui_sdl/libui/windows/CMakeLists.txt delete mode 100644 src/libui_sdl/libui/windows/_uipriv_migrate.hpp delete mode 100644 src/libui_sdl/libui/windows/alloc.cpp delete mode 100644 src/libui_sdl/libui/windows/area.cpp delete mode 100644 src/libui_sdl/libui/windows/area.hpp delete mode 100644 src/libui_sdl/libui/windows/areadraw.cpp delete mode 100644 src/libui_sdl/libui/windows/areaevents.cpp delete mode 100644 src/libui_sdl/libui/windows/areascroll.cpp delete mode 100644 src/libui_sdl/libui/windows/areautil.cpp delete mode 100644 src/libui_sdl/libui/windows/box.cpp delete mode 100644 src/libui_sdl/libui/windows/button.cpp delete mode 100644 src/libui_sdl/libui/windows/checkbox.cpp delete mode 100644 src/libui_sdl/libui/windows/colorbutton.cpp delete mode 100644 src/libui_sdl/libui/windows/colordialog.cpp delete mode 100644 src/libui_sdl/libui/windows/combobox.cpp delete mode 100644 src/libui_sdl/libui/windows/compilerver.hpp delete mode 100644 src/libui_sdl/libui/windows/container.cpp delete mode 100644 src/libui_sdl/libui/windows/control.cpp delete mode 100644 src/libui_sdl/libui/windows/d2dscratch.cpp delete mode 100644 src/libui_sdl/libui/windows/datetimepicker.cpp delete mode 100644 src/libui_sdl/libui/windows/debug.cpp delete mode 100644 src/libui_sdl/libui/windows/draw.cpp delete mode 100644 src/libui_sdl/libui/windows/draw.hpp delete mode 100644 src/libui_sdl/libui/windows/drawmatrix.cpp delete mode 100644 src/libui_sdl/libui/windows/drawpath.cpp delete mode 100644 src/libui_sdl/libui/windows/drawtext.cpp delete mode 100644 src/libui_sdl/libui/windows/dwrite.cpp delete mode 100644 src/libui_sdl/libui/windows/editablecombo.cpp delete mode 100644 src/libui_sdl/libui/windows/entry.cpp delete mode 100644 src/libui_sdl/libui/windows/events.cpp delete mode 100644 src/libui_sdl/libui/windows/fontbutton.cpp delete mode 100644 src/libui_sdl/libui/windows/fontdialog.cpp delete mode 100644 src/libui_sdl/libui/windows/form.cpp delete mode 100644 src/libui_sdl/libui/windows/gl.cpp delete mode 100644 src/libui_sdl/libui/windows/graphemes.cpp delete mode 100644 src/libui_sdl/libui/windows/grid.cpp delete mode 100644 src/libui_sdl/libui/windows/group.cpp delete mode 100644 src/libui_sdl/libui/windows/init.cpp delete mode 100644 src/libui_sdl/libui/windows/label.cpp delete mode 100644 src/libui_sdl/libui/windows/libui.manifest delete mode 100644 src/libui_sdl/libui/windows/main.cpp delete mode 100644 src/libui_sdl/libui/windows/menu.cpp delete mode 100644 src/libui_sdl/libui/windows/multilineentry.cpp delete mode 100644 src/libui_sdl/libui/windows/notes delete mode 100644 src/libui_sdl/libui/windows/parent.cpp delete mode 100644 src/libui_sdl/libui/windows/progressbar.cpp delete mode 100644 src/libui_sdl/libui/windows/radiobuttons.cpp delete mode 100644 src/libui_sdl/libui/windows/resources.hpp delete mode 100644 src/libui_sdl/libui/windows/resources.rc delete mode 100644 src/libui_sdl/libui/windows/separator.cpp delete mode 100644 src/libui_sdl/libui/windows/sizing.cpp delete mode 100644 src/libui_sdl/libui/windows/slider.cpp delete mode 100644 src/libui_sdl/libui/windows/spinbox.cpp delete mode 100644 src/libui_sdl/libui/windows/stddialogs.cpp delete mode 100644 src/libui_sdl/libui/windows/tab.cpp delete mode 100644 src/libui_sdl/libui/windows/tabpage.cpp delete mode 100644 src/libui_sdl/libui/windows/text.cpp delete mode 100644 src/libui_sdl/libui/windows/uipriv_windows.hpp delete mode 100644 src/libui_sdl/libui/windows/utf16.cpp delete mode 100644 src/libui_sdl/libui/windows/utilwin.cpp delete mode 100644 src/libui_sdl/libui/windows/winapi.hpp delete mode 100644 src/libui_sdl/libui/windows/window.cpp delete mode 100644 src/libui_sdl/libui/windows/winpublic.cpp delete mode 100644 src/libui_sdl/libui/windows/winutil.cpp delete mode 100644 src/libui_sdl/main.cpp delete mode 100644 src/libui_sdl/main_shaders.h diff --git a/src/libui_sdl/CMakeLists.txt b/src/libui_sdl/CMakeLists.txt deleted file mode 100644 index a3a7f8a9..00000000 --- a/src/libui_sdl/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -project(libui_sdl) - -SET(SOURCES_LIBUI - main.cpp - Platform.cpp - PlatformConfig.cpp - LAN_Socket.cpp - LAN_PCap.cpp - DlgAudioSettings.cpp - DlgEmuSettings.cpp - DlgInputConfig.cpp - DlgVideoSettings.cpp - DlgWifiSettings.cpp - OSD.cpp -) - -if (WIN32) - set(CMAKE_RC_COMPILE_OBJECT " -i -o ") -endif() - -option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON) -set(BUILD_SHARED_LIBS OFF) -add_subdirectory(libui) - -find_package(PkgConfig REQUIRED) -pkg_check_modules(SDL2 REQUIRED sdl2) - -add_executable(melonDS ${SOURCES_LIBUI}) -target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) -target_link_libraries(melonDS core libui ${SDL2_LIBRARIES}) - -if (UNIX) - option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) - if (UNIX_PORTABLE) - add_definitions(-DUNIX_PORTABLE) - endif() - - find_package(PkgConfig REQUIRED) - pkg_check_modules(GTK3 REQUIRED gtk+-3.0) - - target_include_directories(melonDS PRIVATE ${GTK3_INCLUDE_DIRS}) - target_link_libraries(melonDS ${GTK3_LIBRARIES}) - - ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) - - add_custom_command(OUTPUT melon_grc.c - COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} - --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c - --generate-source "${CMAKE_SOURCE_DIR}/melon_grc.xml" - COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} - --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h - --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") - - if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(melonDS dl) - endif () - - target_sources(melonDS PUBLIC melon_grc.c) -elseif (WIN32) - target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) -endif () - -install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) -install(FILES ../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_32x32.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/32x32/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) -install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/src/libui_sdl/DlgAudioSettings.cpp b/src/libui_sdl/DlgAudioSettings.cpp deleted file mode 100644 index 43836ae9..00000000 --- a/src/libui_sdl/DlgAudioSettings.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include - -#include "libui/ui.h" - -#include "../types.h" -#include "PlatformConfig.h" - -#include "DlgAudioSettings.h" - - -void MicLoadWav(char* path); - - -namespace DlgAudioSettings -{ - -bool opened; -uiWindow* win; - -uiSlider* slVolume; -uiRadioButtons* rbMicInputType; -uiEntry* txMicWavPath; - -int oldvolume; - - -void RevertSettings() -{ - Config::AudioVolume = oldvolume; -} - - -int OnCloseWindow(uiWindow* window, void* blarg) -{ - RevertSettings(); - opened = false; - return 1; -} - -void OnVolumeChanged(uiSlider* slider, void* blarg) -{ - Config::AudioVolume = uiSliderValue(slVolume); -} - -void OnMicWavBrowse(uiButton* btn, void* blarg) -{ - char* file = uiOpenFile(win, "WAV file (*.wav)|*.wav|Any file|*.*", NULL); - if (!file) - { - return; - } - - uiEntrySetText(txMicWavPath, file); - uiFreeText(file); -} - -void OnCancel(uiButton* btn, void* blarg) -{ - RevertSettings(); - - uiControlDestroy(uiControl(win)); - opened = false; -} - -void OnOk(uiButton* btn, void* blarg) -{ - Config::AudioVolume = uiSliderValue(slVolume); - Config::MicInputType = uiRadioButtonsSelected(rbMicInputType); - - char* wavpath = uiEntryText(txMicWavPath); - strncpy(Config::MicWavPath, wavpath, 511); - uiFreeText(wavpath); - - Config::Save(); - - if (Config::MicInputType == 3) MicLoadWav(Config::MicWavPath); - - uiControlDestroy(uiControl(win)); - opened = false; -} - -void Open() -{ - if (opened) - { - uiControlSetFocus(uiControl(win)); - return; - } - - opened = true; - win = uiNewWindow("Audio settings - melonDS", 400, 100, 0, 0, 0); - uiWindowSetMargined(win, 1); - uiWindowOnClosing(win, OnCloseWindow, NULL); - - uiBox* top = uiNewVerticalBox(); - uiWindowSetChild(win, uiControl(top)); - uiBoxSetPadded(top, 1); - - { - uiGroup* grp = uiNewGroup("Audio output"); - uiBoxAppend(top, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - uiLabel* label_vol = uiNewLabel("Volume:"); - uiBoxAppend(in_ctrl, uiControl(label_vol), 0); - - slVolume = uiNewSlider(0, 256); - uiSliderOnChanged(slVolume, OnVolumeChanged, NULL); - uiBoxAppend(in_ctrl, uiControl(slVolume), 0); - } - - { - uiGroup* grp = uiNewGroup("Microphone input"); - uiBoxAppend(top, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - rbMicInputType = uiNewRadioButtons(); - uiRadioButtonsAppend(rbMicInputType, "None"); - uiRadioButtonsAppend(rbMicInputType, "Microphone"); - uiRadioButtonsAppend(rbMicInputType, "White noise"); - uiRadioButtonsAppend(rbMicInputType, "WAV file:"); - uiBoxAppend(in_ctrl, uiControl(rbMicInputType), 0); - - uiBox* path_box = uiNewHorizontalBox(); - uiBoxAppend(in_ctrl, uiControl(path_box), 0); - - txMicWavPath = uiNewEntry(); - uiBoxAppend(path_box, uiControl(txMicWavPath), 1); - - uiButton* path_browse = uiNewButton("..."); - uiButtonOnClicked(path_browse, OnMicWavBrowse, NULL); - uiBoxAppend(path_box, uiControl(path_browse), 0); - } - - { - uiBox* in_ctrl = uiNewHorizontalBox(); - uiBoxSetPadded(in_ctrl, 1); - uiBoxAppend(top, uiControl(in_ctrl), 0); - - uiLabel* dummy = uiNewLabel(""); - uiBoxAppend(in_ctrl, uiControl(dummy), 1); - - uiButton* btncancel = uiNewButton("Cancel"); - uiButtonOnClicked(btncancel, OnCancel, NULL); - uiBoxAppend(in_ctrl, uiControl(btncancel), 0); - - uiButton* btnok = uiNewButton("Ok"); - uiButtonOnClicked(btnok, OnOk, NULL); - uiBoxAppend(in_ctrl, uiControl(btnok), 0); - } - - if (Config::AudioVolume < 0) Config::AudioVolume = 0; - else if (Config::AudioVolume > 256) Config::AudioVolume = 256; - - oldvolume = Config::AudioVolume; - - uiSliderSetValue(slVolume, Config::AudioVolume); - uiRadioButtonsSetSelected(rbMicInputType, Config::MicInputType); - uiEntrySetText(txMicWavPath, Config::MicWavPath); - - uiControlShow(uiControl(win)); -} - -void Close() -{ - if (!opened) return; - uiControlDestroy(uiControl(win)); - opened = false; -} - -} diff --git a/src/libui_sdl/DlgAudioSettings.h b/src/libui_sdl/DlgAudioSettings.h deleted file mode 100644 index 7a5afccd..00000000 --- a/src/libui_sdl/DlgAudioSettings.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef DLGAUDIOSETTINGS_H -#define DLGAUDIOSETTINGS_H - -namespace DlgAudioSettings -{ - -void Open(); -void Close(); - -} - -#endif // DLGAUDIOSETTINGS_H diff --git a/src/libui_sdl/DlgEmuSettings.cpp b/src/libui_sdl/DlgEmuSettings.cpp deleted file mode 100644 index c50f2169..00000000 --- a/src/libui_sdl/DlgEmuSettings.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include - -#include "libui/ui.h" - -#include "../types.h" -#include "PlatformConfig.h" - -#include "DlgEmuSettings.h" - - -void ApplyNewSettings(int type); - - -namespace DlgEmuSettings -{ - -bool opened; -uiWindow* win; - -uiCheckbox* cbDirectBoot; - - -int OnCloseWindow(uiWindow* window, void* blarg) -{ - opened = false; - return 1; -} - -void OnCancel(uiButton* btn, void* blarg) -{ - uiControlDestroy(uiControl(win)); - opened = false; -} - -void OnOk(uiButton* btn, void* blarg) -{ - Config::DirectBoot = uiCheckboxChecked(cbDirectBoot); - - Config::Save(); - - uiControlDestroy(uiControl(win)); - opened = false; -} - -void Open() -{ - if (opened) - { - uiControlSetFocus(uiControl(win)); - return; - } - - opened = true; - win = uiNewWindow("Emu settings - melonDS", 300, 200, 0, 0, 0); - uiWindowSetMargined(win, 1); - uiWindowOnClosing(win, OnCloseWindow, NULL); - - uiBox* top = uiNewVerticalBox(); - uiWindowSetChild(win, uiControl(top)); - - { - uiBox* in_ctrl = uiNewVerticalBox(); - uiBoxAppend(top, uiControl(in_ctrl), 1); - - cbDirectBoot = uiNewCheckbox("Boot game directly"); - uiBoxAppend(in_ctrl, uiControl(cbDirectBoot), 0); - } - - { - uiBox* in_ctrl = uiNewHorizontalBox(); - uiBoxSetPadded(in_ctrl, 1); - uiBoxAppend(top, uiControl(in_ctrl), 0); - - uiLabel* dummy = uiNewLabel(""); - uiBoxAppend(in_ctrl, uiControl(dummy), 1); - - uiButton* btncancel = uiNewButton("Cancel"); - uiButtonOnClicked(btncancel, OnCancel, NULL); - uiBoxAppend(in_ctrl, uiControl(btncancel), 0); - - uiButton* btnok = uiNewButton("Ok"); - uiButtonOnClicked(btnok, OnOk, NULL); - uiBoxAppend(in_ctrl, uiControl(btnok), 0); - } - - uiCheckboxSetChecked(cbDirectBoot, Config::DirectBoot); - - uiControlShow(uiControl(win)); -} - -void Close() -{ - if (!opened) return; - uiControlDestroy(uiControl(win)); - opened = false; -} - -} diff --git a/src/libui_sdl/DlgEmuSettings.h b/src/libui_sdl/DlgEmuSettings.h deleted file mode 100644 index d937448b..00000000 --- a/src/libui_sdl/DlgEmuSettings.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef DLGEMUSETTINGS_H -#define DLGEMUSETTINGS_H - -namespace DlgEmuSettings -{ - -void Open(); -void Close(); - -} - -#endif // DLGEMUSETTINGS_H diff --git a/src/libui_sdl/DlgInputConfig.cpp b/src/libui_sdl/DlgInputConfig.cpp deleted file mode 100644 index f4245b4f..00000000 --- a/src/libui_sdl/DlgInputConfig.cpp +++ /dev/null @@ -1,663 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include - -#include -#include "libui/ui.h" - -#include "../types.h" -#include "PlatformConfig.h" - -#include "DlgInputConfig.h" - - -extern int JoystickID; -extern SDL_Joystick* Joystick; - -extern void OpenJoystick(); - - -namespace DlgInputConfig -{ - -typedef struct -{ - int type; - uiWindow* win; - - uiAreaHandler areahandler; - uiArea* keypresscatcher; - - int numkeys; - int keymap[32]; - int joymap[32]; - - int pollid; - uiButton* pollbtn; - SDL_TimerID timer; - - int axes_rest[16]; - -} InputDlgData; - - -int dskeyorder[12] = {0, 1, 10, 11, 5, 4, 6, 7, 9, 8, 3, 2}; -char dskeylabels[12][8] = {"A:", "B:", "Select:", "Start:", "Right:", "Left:", "Up:", "Down:", "R:", "L:", "X:", "Y:"}; - -int identity[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; - -char hotkeylabels[HK_MAX][32] = -{ - "Close/open lid:", - "Microphone:", - "Pause/resume:", - "Reset:", - "Fast forward:", - "Fast forward (toggle):", - "Decrease sunlight (Boktai):", - "Increase sunlight (Boktai):" -}; - -int openedmask; -InputDlgData inputdlg[2]; - - -void KeyMappingName(int id, char* str) -{ - if (id < 0) - { - strcpy(str, "None"); - return; - } - - int key = id & 0xFFFF; - char* keyname = uiKeyName(key); - strncpy(str, keyname, 63); str[63] = '\0'; - uiFreeText(keyname); - - int mod = id >> 16; - - if (key == 0x11D) mod = 0; - else if (key == 0x138) mod = 0; - else if (key == 0x036) mod = 0; - - if (mod != 0) - { - // CTRL / ALT / SHIFT - const int modscan[] = {0x1D, 0x38, 0x2A}; - char tmp[64]; - - for (int m = 2; m >= 0; m--) - { - if (!(mod & (1<> 4) & 0xF) + 1; - - switch (id & 0xF) - { - case 0x1: sprintf(str, "Hat %d up", hatnum); break; - case 0x2: sprintf(str, "Hat %d right", hatnum); break; - case 0x4: sprintf(str, "Hat %d down", hatnum); break; - case 0x8: sprintf(str, "Hat %d left", hatnum); break; - } - } - else - { - sprintf(str, "Button %d", (id & 0xFFFF) + 1); - } - } - else - { - strcpy(str, ""); - } - - if (id & 0x10000) - { - int axisnum = ((id >> 24) & 0xF) + 1; - - char tmp[64]; - memcpy(tmp, str, 64); - - switch ((id >> 20) & 0xF) - { - case 0: sprintf(str, "%s%sAxis %d +", tmp, hasbtn?" / ":"", axisnum); break; - case 1: sprintf(str, "%s%sAxis %d -", tmp, hasbtn?" / ":"", axisnum); break; - case 2: sprintf(str, "%s%sTrigger %d", tmp, hasbtn?" / ":"", axisnum); break; - } - } -} - - -void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) -{ -} - -void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt) -{ -} - -void OnAreaMouseCrossed(uiAreaHandler* handler, uiArea* area, int left) -{ -} - -void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) -{ -} - -void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height) -{ -} - -int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) -{ - InputDlgData* dlg = (InputDlgData*)uiControl(area)->UserData; - - if (dlg->pollid < 0) - return 0; - - if (evt->Scancode == 0x1D) // CTRL - return 1; - if (evt->Scancode == 0x38) // ALT - return 1; - if (evt->Scancode == 0x2A) // SHIFT - return 1; - - if (dlg->pollid > 12) - { - if (dlg->pollid < 0x100) return 0; - int id = dlg->pollid & 0xFF; - if (id > 12) return 0; - if (evt->Scancode != 0x1 || evt->Modifiers != 0) // ESC - { - if (evt->Scancode == 0xE && evt->Modifiers == 0) // backspace - dlg->joymap[id] = -1; - else - return 1; - } - - char keyname[64]; - JoyMappingName(dlg->joymap[id], keyname); - uiButtonSetText(dlg->pollbtn, keyname); - uiControlEnable(uiControl(dlg->pollbtn)); - - dlg->pollid = -1; - - uiControlSetFocus(uiControl(dlg->pollbtn)); - - return 1; - } - - if (!evt->Up) - { - // set key. - if (evt->Scancode != 0x1 || evt->Modifiers != 0) // ESC - { - int mod = (dlg->type == 0) ? 0 : evt->Modifiers; - - if (evt->Scancode == 0xE && evt->Modifiers == 0) // backspace - dlg->keymap[dlg->pollid] = -1; - else - dlg->keymap[dlg->pollid] = evt->Scancode | (mod << 16); - } - - char keyname[64]; - KeyMappingName(dlg->keymap[dlg->pollid], keyname); - uiButtonSetText(dlg->pollbtn, keyname); - uiControlEnable(uiControl(dlg->pollbtn)); - - dlg->pollid = -1; - - uiControlSetFocus(uiControl(dlg->pollbtn)); - } - - return 1; -} - -void FinishJoyMapping(void* param) -{ - InputDlgData* dlg = (InputDlgData*)param; - int id = dlg->pollid & 0xFF; - - char keyname[64]; - JoyMappingName(dlg->joymap[id], keyname); - uiButtonSetText(dlg->pollbtn, keyname); - uiControlEnable(uiControl(dlg->pollbtn)); - - dlg->pollid = -1; - - uiControlSetFocus(uiControl(dlg->pollbtn)); -} - -Uint32 JoyPoll(Uint32 interval, void* param) -{ - InputDlgData* dlg = (InputDlgData*)param; - - if (dlg->pollid < 0x100) - { - dlg->timer = 0; - return 0; - } - - int id = dlg->pollid & 0xFF; - if (id > 12) - { - dlg->timer = 0; - return 0; - } - - SDL_Joystick* joy = Joystick; - if (!joy) - { - dlg->timer = 0; - return 0; - } - if (!SDL_JoystickGetAttached(joy)) - { - dlg->timer = 0; - return 0; - } - - int oldmap; - if (dlg->joymap[id] == -1) oldmap = 0xFFFF; - else oldmap = dlg->joymap[id]; - - int nbuttons = SDL_JoystickNumButtons(joy); - for (int i = 0; i < nbuttons; i++) - { - if (SDL_JoystickGetButton(joy, i)) - { - dlg->joymap[id] = (oldmap & 0xFFFF0000) | i; - uiQueueMain(FinishJoyMapping, dlg); - dlg->timer = 0; - return 0; - } - } - - int nhats = SDL_JoystickNumHats(joy); - if (nhats > 16) nhats = 16; - for (int i = 0; i < nhats; i++) - { - Uint8 blackhat = SDL_JoystickGetHat(joy, i); - if (blackhat) - { - if (blackhat & 0x1) blackhat = 0x1; - else if (blackhat & 0x2) blackhat = 0x2; - else if (blackhat & 0x4) blackhat = 0x4; - else blackhat = 0x8; - - dlg->joymap[id] = (oldmap & 0xFFFF0000) | 0x100 | blackhat | (i << 4); - uiQueueMain(FinishJoyMapping, dlg); - dlg->timer = 0; - return 0; - } - } - - int naxes = SDL_JoystickNumAxes(joy); - if (naxes > 16) naxes = 16; - for (int i = 0; i < naxes; i++) - { - Sint16 axisval = SDL_JoystickGetAxis(joy, i); - int diff = abs(axisval - dlg->axes_rest[i]); - - if (dlg->axes_rest[i] < -16384 && axisval >= 0) - { - dlg->joymap[id] = (oldmap & 0xFFFF) | 0x10000 | (2 << 20) | (i << 24); - uiQueueMain(FinishJoyMapping, dlg); - dlg->timer = 0; - return 0; - } - else if (diff > 16384) - { - int axistype; - if (axisval > 0) axistype = 0; - else axistype = 1; - - dlg->joymap[id] = (oldmap & 0xFFFF) | 0x10000 | (axistype << 20) | (i << 24); - uiQueueMain(FinishJoyMapping, dlg); - dlg->timer = 0; - return 0; - } - } - - return interval; -} - - -void OnKeyStartConfig(uiButton* btn, void* data) -{ - InputDlgData* dlg = (InputDlgData*)uiControl(btn)->UserData; - - if (dlg->pollid != -1) - { - // TODO: handle this better? - if (dlg->pollid <= 12) - uiControlSetFocus(uiControl(dlg->keypresscatcher)); - return; - } - - int id = *(int*)data; - dlg->pollid = id; - dlg->pollbtn = btn; - - uiButtonSetText(btn, "[press key]"); - uiControlDisable(uiControl(btn)); - - uiControlSetFocus(uiControl(dlg->keypresscatcher)); -} - -void OnJoyStartConfig(uiButton* btn, void* data) -{ - InputDlgData* dlg = (InputDlgData*)uiControl(btn)->UserData; - - if (dlg->pollid != -1) - { - // TODO: handle this better? - if (dlg->pollid <= 12) - uiControlSetFocus(uiControl(dlg->keypresscatcher)); - return; - } - - int naxes = SDL_JoystickNumAxes(Joystick); - if (naxes > 16) naxes = 16; - for (int a = 0; a < naxes; a++) - { - dlg->axes_rest[a] = SDL_JoystickGetAxis(Joystick, a); - } - - int id = *(int*)data; - dlg->pollid = id | 0x100; - dlg->pollbtn = btn; - - uiButtonSetText(btn, "[press button / axis]"); - uiControlDisable(uiControl(btn)); - - dlg->timer = SDL_AddTimer(100, JoyPoll, dlg); - uiControlSetFocus(uiControl(dlg->keypresscatcher)); -} - - -void OnJoystickChanged(uiCombobox* cb, void* data) -{ - JoystickID = uiComboboxSelected(cb); - OpenJoystick(); -} - - -int OnCloseWindow(uiWindow* window, void* blarg) -{ - InputDlgData* dlg = (InputDlgData*)(uiControl(window)->UserData); - openedmask &= ~(1 << dlg->type); - if (dlg->timer) SDL_RemoveTimer(dlg->timer); - - JoystickID = Config::JoystickID; - OpenJoystick(); - - return 1; -} - -void OnGetFocus(uiWindow* window, void* blarg) -{ - InputDlgData* dlg = (InputDlgData*)(uiControl(window)->UserData); - - if (dlg->pollid >= 0) - uiControlSetFocus(uiControl(dlg->keypresscatcher)); -} - -void OnLoseFocus(uiWindow* window, void* blarg) -{ -} - -void OnCancel(uiButton* btn, void* data) -{ - InputDlgData* dlg = (InputDlgData*)data; - - uiControlDestroy(uiControl(dlg->win)); - openedmask &= ~(1 << dlg->type); - if (dlg->timer) SDL_RemoveTimer(dlg->timer); - - JoystickID = Config::JoystickID; - OpenJoystick(); -} - -void OnOk(uiButton* btn, void* data) -{ - InputDlgData* dlg = (InputDlgData*)data; - - if (dlg->type == 0) - { - memcpy(Config::KeyMapping, dlg->keymap, sizeof(int)*12); - memcpy(Config::JoyMapping, dlg->joymap, sizeof(int)*12); - } - else if (dlg->type == 1) - { - memcpy(Config::HKKeyMapping, dlg->keymap, sizeof(int)*HK_MAX); - memcpy(Config::HKJoyMapping, dlg->joymap, sizeof(int)*HK_MAX); - } - - Config::JoystickID = JoystickID; - - Config::Save(); - - uiControlDestroy(uiControl(dlg->win)); - openedmask &= ~(1 << dlg->type); - if (dlg->timer) SDL_RemoveTimer(dlg->timer); -} - -void Open(int type) -{ - InputDlgData* dlg = &inputdlg[type]; - - int mask = 1 << type; - if (openedmask & mask) - { - uiControlSetFocus(uiControl(dlg->win)); - return; - } - - openedmask |= mask; - - dlg->type = type; - dlg->pollid = -1; - dlg->timer = 0; - - if (type == 0) - { - dlg->numkeys = 12; - memcpy(dlg->keymap, Config::KeyMapping, sizeof(int)*12); - memcpy(dlg->joymap, Config::JoyMapping, sizeof(int)*12); - - dlg->win = uiNewWindow("Input config - melonDS", 600, 100, 0, 0, 0); - } - else if (type == 1) - { - dlg->numkeys = HK_MAX; - memcpy(dlg->keymap, Config::HKKeyMapping, sizeof(int)*HK_MAX); - memcpy(dlg->joymap, Config::HKJoyMapping, sizeof(int)*HK_MAX); - - dlg->win = uiNewWindow("Hotkey config - melonDS", 700, 100, 0, 0, 0); - } - - uiControl(dlg->win)->UserData = dlg; - - uiWindowSetMargined(dlg->win, 1); - uiWindowOnClosing(dlg->win, OnCloseWindow, NULL); - uiWindowOnGetFocus(dlg->win, OnGetFocus, NULL); - uiWindowOnLoseFocus(dlg->win, OnLoseFocus, NULL); - - dlg->areahandler.Draw = OnAreaDraw; - dlg->areahandler.MouseEvent = OnAreaMouseEvent; - dlg->areahandler.MouseCrossed = OnAreaMouseCrossed; - dlg->areahandler.DragBroken = OnAreaDragBroken; - dlg->areahandler.KeyEvent = OnAreaKeyEvent; - dlg->areahandler.Resize = OnAreaResize; - - uiBox* top = uiNewVerticalBox(); - uiWindowSetChild(dlg->win, uiControl(top)); - uiControlHide(uiControl(top)); - - { - uiBox* in_ctrl = uiNewHorizontalBox(); - uiBoxAppend(top, uiControl(in_ctrl), 0); - uiBoxSetPadded(in_ctrl, 1); - - uiGroup* g_key = uiNewGroup("Keyboard"); - uiBoxAppend(in_ctrl, uiControl(g_key), 1); - uiGrid* b_key = uiNewGrid(); - uiGroupSetChild(g_key, uiControl(b_key)); - - const int width = 240; - - for (int i = 0; i < dlg->numkeys; i++) - { - int j = (type==0) ? dskeyorder[i] : i; - - uiLabel* label = uiNewLabel((type==0) ? dskeylabels[j] : hotkeylabels[j]); - uiGridAppend(b_key, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter); - uiControlSetMinSize(uiControl(label), width, 1); - - char keyname[64]; - KeyMappingName(dlg->keymap[j], keyname); - - uiButton* btn = uiNewButton(keyname); - uiControl(btn)->UserData = dlg; - uiGridAppend(b_key, uiControl(btn), 1, i, 1, 1, 1, uiAlignFill, 1, uiAlignCenter); - uiButtonOnClicked(btn, OnKeyStartConfig, (type==0) ? &dskeyorder[i] : &identity[i]); - uiControlSetMinSize(uiControl(btn), width, 1); - } - - uiGroup* g_joy = uiNewGroup("Joystick"); - uiBoxAppend(in_ctrl, uiControl(g_joy), 1); - uiGrid* b_joy = uiNewGrid(); - uiGroupSetChild(g_joy, uiControl(b_joy)); - - for (int i = 0; i < dlg->numkeys; i++) - { - int j = (type==0) ? dskeyorder[i] : i; - - uiLabel* label = uiNewLabel((type==0) ? dskeylabels[j] : hotkeylabels[j]); - uiGridAppend(b_joy, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter); - uiControlSetMinSize(uiControl(label), width, 1); - - char keyname[64]; - JoyMappingName(dlg->joymap[j], keyname); - - uiButton* btn = uiNewButton(keyname); - uiControl(btn)->UserData = dlg; - uiGridAppend(b_joy, uiControl(btn), 1, i, 1, 1, 1, uiAlignFill, 1, uiAlignCenter); - uiButtonOnClicked(btn, OnJoyStartConfig, (type==0) ? &dskeyorder[i] : &identity[i]); - uiControlSetMinSize(uiControl(btn), width, 1); - } - - if (type == 0) - { - uiLabel* dummy = uiNewLabel(" "); - uiGridAppend(b_key, uiControl(dummy), 0, dlg->numkeys, 2, 1, 1, uiAlignFill, 1, uiAlignCenter); - - uiCombobox* joycombo = uiNewCombobox(); - uiGridAppend(b_joy, uiControl(joycombo), 0, dlg->numkeys, 2, 1, 1, uiAlignFill, 1, uiAlignCenter); - - int numjoys = SDL_NumJoysticks(); - if (numjoys < 1) - { - uiComboboxAppend(joycombo, "(no joysticks available)"); - uiControlDisable(uiControl(joycombo)); - } - else - { - for (int i = 0; i < numjoys; i++) - { - const char* joyname = SDL_JoystickNameForIndex(i); - char fullname[256]; - snprintf(fullname, 256, "%d. %s", i+1, joyname); - - uiComboboxAppend(joycombo, fullname); - } - - uiComboboxSetSelected(joycombo, JoystickID); - uiComboboxOnSelected(joycombo, OnJoystickChanged, NULL); - } - } - } - - uiLabel* filler = uiNewLabel(""); - uiBoxAppend(top, uiControl(filler), 1); - - { - uiBox* in_ctrl = uiNewHorizontalBox(); - uiBoxSetPadded(in_ctrl, 1); - uiBoxAppend(top, uiControl(in_ctrl), 0); - - uiLabel* dummy = uiNewLabel(""); - uiBoxAppend(in_ctrl, uiControl(dummy), 1); - - dlg->keypresscatcher = uiNewArea(&dlg->areahandler); - uiControl(dlg->keypresscatcher)->UserData = dlg; - uiBoxAppend(in_ctrl, uiControl(dlg->keypresscatcher), 0); - - uiButton* btncancel = uiNewButton("Cancel"); - uiButtonOnClicked(btncancel, OnCancel, dlg); - uiBoxAppend(in_ctrl, uiControl(btncancel), 0); - - uiButton* btnok = uiNewButton("Ok"); - uiButtonOnClicked(btnok, OnOk, dlg); - uiBoxAppend(in_ctrl, uiControl(btnok), 0); - } - - uiControlShow(uiControl(top)); - - uiControlShow(uiControl(dlg->win)); -} - -void Close(int type) -{ - if (openedmask & (1< -#include -#include - -#include "libui/ui.h" - -#include "../types.h" -#include "PlatformConfig.h" - -#include "DlgVideoSettings.h" - - -void ApplyNewSettings(int type); - - -namespace DlgVideoSettings -{ - -bool opened; -uiWindow* win; - -uiRadioButtons* rbRenderer; -uiCheckbox* cbGLDisplay; -uiCheckbox* cbVSync; -uiCheckbox* cbThreaded3D; -uiCombobox* cbResolution; -uiCheckbox* cbAntialias; - -int old_renderer; -int old_gldisplay; -int old_vsync; -int old_threaded3D; -int old_resolution; -int old_antialias; - - -void UpdateControls() -{ - int renderer = uiRadioButtonsSelected(rbRenderer); - - if (renderer == 0) - { - uiControlEnable(uiControl(cbGLDisplay)); - uiControlEnable(uiControl(cbThreaded3D)); - uiControlDisable(uiControl(cbResolution)); - //uiControlDisable(uiControl(cbAntialias)); - } - else - { - uiControlDisable(uiControl(cbGLDisplay)); - uiControlDisable(uiControl(cbThreaded3D)); - uiControlEnable(uiControl(cbResolution)); - //uiControlEnable(uiControl(cbAntialias)); - } -} - -void RevertSettings() -{ - bool apply0 = false; - bool apply2 = false; - bool apply3 = false; - - bool old_usegl = (old_gldisplay != 0) || (old_renderer != 0); - bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); - - if (old_renderer != Config::_3DRenderer) - { - Config::_3DRenderer = old_renderer; - apply3 = true; - } - - if (old_gldisplay != Config::ScreenUseGL) - { - Config::ScreenUseGL = old_gldisplay; - } - if (old_vsync != Config::ScreenVSync) - { - Config::ScreenVSync = old_vsync; - //ApplyNewSettings(4); - } - if (old_usegl != new_usegl) - { - apply2 = true; - } - - if (old_threaded3D != Config::Threaded3D) - { - Config::Threaded3D = old_threaded3D; - apply0 = true; - } - - if (old_resolution != Config::GL_ScaleFactor || - old_antialias != Config::GL_Antialias) - { - Config::GL_ScaleFactor = old_resolution; - Config::GL_Antialias = old_antialias; - apply0 = true; - } - - if (apply2) ApplyNewSettings(2); - else if (apply3) ApplyNewSettings(3); - if (apply0) ApplyNewSettings(0); -} - - -int OnCloseWindow(uiWindow* window, void* blarg) -{ - RevertSettings(); - opened = false; - return 1; -} - -void OnRendererChanged(uiRadioButtons* rb, void* blarg) -{ - int id = uiRadioButtonsSelected(rb); - bool old_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); - - Config::_3DRenderer = id; - UpdateControls(); - - bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); - - if (new_usegl) uiControlEnable(uiControl(cbVSync)); - else uiControlDisable(uiControl(cbVSync)); - - if (new_usegl != old_usegl) - ApplyNewSettings(2); - else - ApplyNewSettings(3); - - uiControlSetFocus(uiControl(win)); -} - -void OnGLDisplayChanged(uiCheckbox* cb, void* blarg) -{ - Config::ScreenUseGL = uiCheckboxChecked(cb); - if (Config::ScreenUseGL) uiControlEnable(uiControl(cbVSync)); - else uiControlDisable(uiControl(cbVSync)); - ApplyNewSettings(2); - uiControlSetFocus(uiControl(win)); -} - -void OnVSyncChanged(uiCheckbox* cb, void* blarg) -{ - Config::ScreenVSync = uiCheckboxChecked(cb); - //ApplyNewSettings(4); -} - -void OnThreaded3DChanged(uiCheckbox* cb, void* blarg) -{ - Config::Threaded3D = uiCheckboxChecked(cb); - ApplyNewSettings(0); -} - -void OnResolutionChanged(uiCombobox* cb, void* blarg) -{ - int id = uiComboboxSelected(cb); - - Config::GL_ScaleFactor = id+1; - ApplyNewSettings(0); -} - -void OnAntialiasChanged(uiCheckbox* cb, void* blarg) -{ - Config::GL_Antialias = uiCheckboxChecked(cb); - ApplyNewSettings(0); -} - -void OnCancel(uiButton* btn, void* blarg) -{ - RevertSettings(); - - uiControlDestroy(uiControl(win)); - opened = false; -} - -void OnOk(uiButton* btn, void* blarg) -{ - Config::Save(); - - uiControlDestroy(uiControl(win)); - opened = false; -} - -void Open() -{ - if (opened) - { - uiControlSetFocus(uiControl(win)); - return; - } - - opened = true; - win = uiNewWindow("Video settings - melonDS", 400, 100, 0, 0, 0); - uiWindowSetMargined(win, 1); - uiWindowOnClosing(win, OnCloseWindow, NULL); - - uiBox* top = uiNewVerticalBox(); - uiWindowSetChild(win, uiControl(top)); - uiBoxSetPadded(top, 1); - - uiBox* splitter = uiNewHorizontalBox(); - uiBoxAppend(top, uiControl(splitter), 0); - uiBoxSetPadded(splitter, 1); - - uiBox* left = uiNewVerticalBox(); - uiBoxAppend(splitter, uiControl(left), 1); - uiBoxSetPadded(left, 1); - uiBox* right = uiNewVerticalBox(); - uiBoxAppend(splitter, uiControl(right), 1); - uiBoxSetPadded(right, 1); - - { - uiGroup* grp = uiNewGroup("Display settings"); - uiBoxAppend(left, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - uiLabel* lbl = uiNewLabel("3D renderer:"); - uiBoxAppend(in_ctrl, uiControl(lbl), 0); - - rbRenderer = uiNewRadioButtons(); - uiRadioButtonsAppend(rbRenderer, "Software"); - uiRadioButtonsAppend(rbRenderer, "OpenGL"); - uiRadioButtonsOnSelected(rbRenderer, OnRendererChanged, NULL); - uiBoxAppend(in_ctrl, uiControl(rbRenderer), 0); - - lbl = uiNewLabel(""); - uiBoxAppend(in_ctrl, uiControl(lbl), 0); - - cbGLDisplay = uiNewCheckbox("OpenGL display"); - uiCheckboxOnToggled(cbGLDisplay, OnGLDisplayChanged, NULL); - uiBoxAppend(in_ctrl, uiControl(cbGLDisplay), 0); - - cbVSync = uiNewCheckbox("VSync"); - uiCheckboxOnToggled(cbVSync, OnVSyncChanged, NULL); - uiBoxAppend(in_ctrl, uiControl(cbVSync), 0); - } - - { - uiGroup* grp = uiNewGroup("Software renderer"); - uiBoxAppend(right, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - cbThreaded3D = uiNewCheckbox("Threaded"); - uiCheckboxOnToggled(cbThreaded3D, OnThreaded3DChanged, NULL); - uiBoxAppend(in_ctrl, uiControl(cbThreaded3D), 0); - } - - { - uiGroup* grp = uiNewGroup("OpenGL renderer"); - uiBoxAppend(right, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - uiLabel* lbl = uiNewLabel("Internal resolution:"); - uiBoxAppend(in_ctrl, uiControl(lbl), 0); - - cbResolution = uiNewCombobox(); - uiComboboxOnSelected(cbResolution, OnResolutionChanged, NULL); - for (int i = 1; i <= 8; i++) - { - char txt[64]; - sprintf(txt, "%dx native (%dx%d)", i, 256*i, 192*i); - uiComboboxAppend(cbResolution, txt); - } - uiBoxAppend(in_ctrl, uiControl(cbResolution), 0); - - //lbl = uiNewLabel(""); - //uiBoxAppend(in_ctrl, uiControl(lbl), 0); - - //cbAntialias = uiNewCheckbox("Antialiasing"); - //uiCheckboxOnToggled(cbAntialias, OnAntialiasChanged, NULL); - //uiBoxAppend(in_ctrl, uiControl(cbAntialias), 0); - } - - { - uiBox* in_ctrl = uiNewHorizontalBox(); - uiBoxSetPadded(in_ctrl, 1); - uiBoxAppend(top, uiControl(in_ctrl), 0); - - uiLabel* dummy = uiNewLabel(""); - uiBoxAppend(in_ctrl, uiControl(dummy), 1); - - uiButton* btncancel = uiNewButton("Cancel"); - uiButtonOnClicked(btncancel, OnCancel, NULL); - uiBoxAppend(in_ctrl, uiControl(btncancel), 0); - - uiButton* btnok = uiNewButton("Ok"); - uiButtonOnClicked(btnok, OnOk, NULL); - uiBoxAppend(in_ctrl, uiControl(btnok), 0); - } - - Config::_3DRenderer = Config::_3DRenderer ? 1 : 0; - - if (Config::GL_ScaleFactor < 1) Config::GL_ScaleFactor = 1; - else if (Config::GL_ScaleFactor > 8) Config::GL_ScaleFactor = 8; - - old_renderer = Config::_3DRenderer; - old_gldisplay = Config::ScreenUseGL; - old_vsync = Config::ScreenVSync; - old_threaded3D = Config::Threaded3D; - old_resolution = Config::GL_ScaleFactor; - old_antialias = Config::GL_Antialias; - - uiCheckboxSetChecked(cbGLDisplay, Config::ScreenUseGL); - uiCheckboxSetChecked(cbVSync, Config::ScreenVSync); - uiCheckboxSetChecked(cbThreaded3D, Config::Threaded3D); - uiComboboxSetSelected(cbResolution, Config::GL_ScaleFactor-1); - //uiCheckboxSetChecked(cbAntialias, Config::GL_Antialias); - uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer); - UpdateControls(); - - if (Config::ScreenUseGL || Config::_3DRenderer != 0) - uiControlEnable(uiControl(cbVSync)); - else - uiControlDisable(uiControl(cbVSync)); - - uiControlShow(uiControl(win)); -} - -void Close() -{ - if (!opened) return; - uiControlDestroy(uiControl(win)); - opened = false; -} - -} diff --git a/src/libui_sdl/DlgVideoSettings.h b/src/libui_sdl/DlgVideoSettings.h deleted file mode 100644 index 17072e0d..00000000 --- a/src/libui_sdl/DlgVideoSettings.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef DLGVIDEOSETTINGS_H -#define DLGVIDEOSETTINGS_H - -namespace DlgVideoSettings -{ - -void Open(); -void Close(); - -} - -#endif // DLGVIDEOSETTINGS_H diff --git a/src/libui_sdl/DlgWifiSettings.cpp b/src/libui_sdl/DlgWifiSettings.cpp deleted file mode 100644 index d1ce8bd7..00000000 --- a/src/libui_sdl/DlgWifiSettings.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include - -#include "libui/ui.h" - -#include "../types.h" -#include "PlatformConfig.h" - -#include "LAN_Socket.h" -#include "LAN_PCap.h" -#include "DlgWifiSettings.h" - - -#ifdef __WIN32__ -#define PCAP_NAME "winpcap/npcap" -#else -#define PCAP_NAME "libpcap" -#endif // __WIN32__ - - -void ApplyNewSettings(int type); - - -namespace DlgWifiSettings -{ - -bool opened; -uiWindow* win; - -bool haspcap; - -uiCheckbox* cbBindAnyAddr; - -uiLabel* lbAdapterList; -uiCombobox* cmAdapterList; -uiCheckbox* cbDirectLAN; - -uiLabel* lbAdapterMAC; -uiLabel* lbAdapterIP; -uiLabel* lbAdapterDNS0; -uiLabel* lbAdapterDNS1; - - -void UpdateAdapterControls() -{ - bool enable = haspcap && uiCheckboxChecked(cbDirectLAN); - - if (enable) - { - uiControlEnable(uiControl(lbAdapterList)); - uiControlEnable(uiControl(cmAdapterList)); - uiControlEnable(uiControl(lbAdapterMAC)); - uiControlEnable(uiControl(lbAdapterIP)); - } - else - { - uiControlDisable(uiControl(lbAdapterList)); - uiControlDisable(uiControl(cmAdapterList)); - uiControlDisable(uiControl(lbAdapterMAC)); - uiControlDisable(uiControl(lbAdapterIP)); - } -} - -void UpdateAdapterInfo() -{ - if (!haspcap) return; - - int sel = uiComboboxSelected(cmAdapterList); - if (sel < 0 || sel >= LAN_PCap::NumAdapters) return; - if (LAN_PCap::NumAdapters < 1) return; - - LAN_PCap::AdapterData* adapter = &LAN_PCap::Adapters[sel]; - char tmp[64]; - - sprintf(tmp, "MAC: %02X:%02X:%02X:%02X:%02X:%02X", - adapter->MAC[0], adapter->MAC[1], adapter->MAC[2], - adapter->MAC[3], adapter->MAC[4], adapter->MAC[5]); - uiLabelSetText(lbAdapterMAC, tmp); - - sprintf(tmp, "IP: %d.%d.%d.%d", - adapter->IP_v4[0], adapter->IP_v4[1], - adapter->IP_v4[2], adapter->IP_v4[3]); - uiLabelSetText(lbAdapterIP, tmp); - - /*sprintf(tmp, "Primary DNS: %d.%d.%d.%d", - adapter->DNS[0][0], adapter->DNS[0][1], - adapter->DNS[0][2], adapter->DNS[0][3]); - uiLabelSetText(lbAdapterDNS0, tmp); - - sprintf(tmp, "Secondary DNS: %d.%d.%d.%d", - adapter->DNS[1][0], adapter->DNS[1][1], - adapter->DNS[1][2], adapter->DNS[1][3]); - uiLabelSetText(lbAdapterDNS1, tmp);*/ -} - -int OnCloseWindow(uiWindow* window, void* blarg) -{ - opened = false; - return 1; -} - -void OnDirectModeToggle(uiCheckbox* c, void* blarg) -{ - UpdateAdapterControls(); -} - -void OnAdapterSelect(uiCombobox* c, void* blarg) -{ - UpdateAdapterInfo(); -} - -void OnCancel(uiButton* btn, void* blarg) -{ - uiControlDestroy(uiControl(win)); - opened = false; -} - -void OnOk(uiButton* btn, void* blarg) -{ - Config::SocketBindAnyAddr = uiCheckboxChecked(cbBindAnyAddr); - Config::DirectLAN = uiCheckboxChecked(cbDirectLAN); - - int sel = uiComboboxSelected(cmAdapterList); - if (sel < 0 || sel >= LAN_PCap::NumAdapters) sel = 0; - if (LAN_PCap::NumAdapters < 1) - { - Config::LANDevice[0] = '\0'; - } - else - { - strncpy(Config::LANDevice, LAN_PCap::Adapters[sel].DeviceName, 127); - Config::LANDevice[127] = '\0'; - } - - Config::Save(); - - uiControlDestroy(uiControl(win)); - opened = false; - - ApplyNewSettings(1); -} - -void Open() -{ - if (opened) - { - uiControlSetFocus(uiControl(win)); - return; - } - - LAN_Socket::Init(); - haspcap = LAN_PCap::Init(false); - - opened = true; - win = uiNewWindow("Wifi settings - melonDS", 400, 100, 0, 0, 0); - uiWindowSetMargined(win, 1); - uiWindowOnClosing(win, OnCloseWindow, NULL); - - uiBox* top = uiNewVerticalBox(); - uiWindowSetChild(win, uiControl(top)); - uiBoxSetPadded(top, 1); - - { - uiGroup* grp = uiNewGroup("Local"); - uiBoxAppend(top, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - cbBindAnyAddr = uiNewCheckbox("Bind socket to any address"); - uiBoxAppend(in_ctrl, uiControl(cbBindAnyAddr), 0); - } - - { - uiLabel* lbl; - - uiGroup* grp = uiNewGroup("Online"); - uiBoxAppend(top, uiControl(grp), 0); - uiGroupSetMargined(grp, 1); - - uiBox* in_ctrl = uiNewVerticalBox(); - uiGroupSetChild(grp, uiControl(in_ctrl)); - - cbDirectLAN = uiNewCheckbox("Direct mode (requires " PCAP_NAME " and ethernet connection)"); - uiCheckboxOnToggled(cbDirectLAN, OnDirectModeToggle, NULL); - uiBoxAppend(in_ctrl, uiControl(cbDirectLAN), 0); - - lbAdapterList = uiNewLabel("Network adapter:"); - uiBoxAppend(in_ctrl, uiControl(lbAdapterList), 0); - - cmAdapterList = uiNewCombobox(); - uiComboboxOnSelected(cmAdapterList, OnAdapterSelect, NULL); - uiBoxAppend(in_ctrl, uiControl(cmAdapterList), 0); - - lbAdapterMAC = uiNewLabel("MAC: ??"); - uiBoxAppend(in_ctrl, uiControl(lbAdapterMAC), 0); - lbAdapterIP = uiNewLabel("IP: ??"); - uiBoxAppend(in_ctrl, uiControl(lbAdapterIP), 0); - /*lbAdapterDNS0 = uiNewLabel("DNS0"); - uiBoxAppend(in_ctrl, uiControl(lbAdapterDNS0), 0); - lbAdapterDNS1 = uiNewLabel("DNS1"); - uiBoxAppend(in_ctrl, uiControl(lbAdapterDNS1), 0);*/ - } - - { - uiBox* in_ctrl = uiNewHorizontalBox(); - uiBoxSetPadded(in_ctrl, 1); - uiBoxAppend(top, uiControl(in_ctrl), 0); - - uiLabel* dummy = uiNewLabel(""); - uiBoxAppend(in_ctrl, uiControl(dummy), 1); - - uiButton* btncancel = uiNewButton("Cancel"); - uiButtonOnClicked(btncancel, OnCancel, NULL); - uiBoxAppend(in_ctrl, uiControl(btncancel), 0); - - uiButton* btnok = uiNewButton("Ok"); - uiButtonOnClicked(btnok, OnOk, NULL); - uiBoxAppend(in_ctrl, uiControl(btnok), 0); - } - - uiCheckboxSetChecked(cbBindAnyAddr, Config::SocketBindAnyAddr); - - int sel = 0; - for (int i = 0; i < LAN_PCap::NumAdapters; i++) - { - LAN_PCap::AdapterData* adapter = &LAN_PCap::Adapters[i]; - - uiComboboxAppend(cmAdapterList, adapter->FriendlyName); - - if (!strncmp(adapter->DeviceName, Config::LANDevice, 128)) - sel = i; - } - uiComboboxSetSelected(cmAdapterList, sel); - UpdateAdapterInfo(); - - uiCheckboxSetChecked(cbDirectLAN, Config::DirectLAN); - if (!haspcap) uiControlDisable(uiControl(cbDirectLAN)); - UpdateAdapterControls(); - - uiControlShow(uiControl(win)); -} - -void Close() -{ - if (!opened) return; - uiControlDestroy(uiControl(win)); - opened = false; -} - -} diff --git a/src/libui_sdl/DlgWifiSettings.h b/src/libui_sdl/DlgWifiSettings.h deleted file mode 100644 index a12cbfd0..00000000 --- a/src/libui_sdl/DlgWifiSettings.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef DLGWIFISETTINGS_H -#define DLGWIFISETTINGS_H - -namespace DlgWifiSettings -{ - -void Open(); -void Close(); - -} - -#endif // DLGWIFISETTINGS_H - diff --git a/src/libui_sdl/LAN_PCap.cpp b/src/libui_sdl/LAN_PCap.cpp deleted file mode 100644 index ce278bcb..00000000 --- a/src/libui_sdl/LAN_PCap.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -// direct LAN interface. Currently powered by libpcap, may change. - -#include -#include -#include -#include -#include -#include "../Wifi.h" -#include "LAN_PCap.h" -#include "PlatformConfig.h" - -#ifdef __WIN32__ - #include -#else - #include - #include - #include - #include -#endif - - -// welp -#ifndef PCAP_OPENFLAG_PROMISCUOUS -#define PCAP_OPENFLAG_PROMISCUOUS 1 -#endif - - -#define DECL_PCAP_FUNC(ret, name, args, args2) \ - typedef ret (*type_##name) args; \ - type_##name ptr_##name = NULL; \ - ret name args { return ptr_##name args2; } - -DECL_PCAP_FUNC(int, pcap_findalldevs, (pcap_if_t** alldevs, char* errbuf), (alldevs,errbuf)) -DECL_PCAP_FUNC(void, pcap_freealldevs, (pcap_if_t* alldevs), (alldevs)) -DECL_PCAP_FUNC(pcap_t*, pcap_open_live, (const char* src, int snaplen, int flags, int readtimeout, char* errbuf), (src,snaplen,flags,readtimeout,errbuf)) -DECL_PCAP_FUNC(void, pcap_close, (pcap_t* dev), (dev)) -DECL_PCAP_FUNC(int, pcap_setnonblock, (pcap_t* dev, int nonblock, char* errbuf), (dev,nonblock,errbuf)) -DECL_PCAP_FUNC(int, pcap_sendpacket, (pcap_t* dev, const u_char* data, int len), (dev,data,len)) -DECL_PCAP_FUNC(int, pcap_dispatch, (pcap_t* dev, int num, pcap_handler callback, u_char* data), (dev,num,callback,data)) -DECL_PCAP_FUNC(const u_char*, pcap_next, (pcap_t* dev, struct pcap_pkthdr* hdr), (dev,hdr)) - - -namespace LAN_PCap -{ - -const char* PCapLibNames[] = -{ -#ifdef __WIN32__ - // TODO: name for npcap in non-WinPCap mode - "wpcap.dll", -#else - // Linux lib names - "libpcap.so.1", - "libpcap.so", -#endif - NULL -}; - -AdapterData* Adapters = NULL; -int NumAdapters = 0; - -void* PCapLib = NULL; -pcap_t* PCapAdapter = NULL; -AdapterData* PCapAdapterData; - -u8 PacketBuffer[2048]; -int PacketLen; -volatile int RXNum; - - -#define LOAD_PCAP_FUNC(sym) \ - ptr_##sym = (type_##sym)SDL_LoadFunction(lib, #sym); \ - if (!ptr_##sym) return false; - -bool TryLoadPCap(void* lib) -{ - LOAD_PCAP_FUNC(pcap_findalldevs) - LOAD_PCAP_FUNC(pcap_freealldevs) - LOAD_PCAP_FUNC(pcap_open_live) - LOAD_PCAP_FUNC(pcap_close) - LOAD_PCAP_FUNC(pcap_setnonblock) - LOAD_PCAP_FUNC(pcap_sendpacket) - LOAD_PCAP_FUNC(pcap_dispatch) - LOAD_PCAP_FUNC(pcap_next) - - return true; -} - -bool Init(bool open_adapter) -{ - // TODO: how to deal with cases where an adapter is unplugged or changes config?? - if (!PCapLib) - { - PCapLib = NULL; - - for (int i = 0; PCapLibNames[i]; i++) - { - void* lib = SDL_LoadObject(PCapLibNames[i]); - if (!lib) continue; - - if (!TryLoadPCap(lib)) - { - SDL_UnloadObject(lib); - continue; - } - - printf("PCap: lib %s, init successful\n", PCapLibNames[i]); - PCapLib = lib; - break; - } - - if (PCapLib == NULL) - { - printf("PCap: init failed\n"); - return false; - } - } - - PCapAdapter = NULL; - PacketLen = 0; - RXNum = 0; - - NumAdapters = 0; - - char errbuf[PCAP_ERRBUF_SIZE]; - int ret; - - pcap_if_t* alldevs; - ret = pcap_findalldevs(&alldevs, errbuf); - if (ret < 0 || alldevs == NULL) - { - printf("PCap: no devices available\n"); - return false; - } - - pcap_if_t* dev = alldevs; - while (dev) { NumAdapters++; dev = dev->next; } - - Adapters = new AdapterData[NumAdapters]; - memset(Adapters, 0, sizeof(AdapterData)*NumAdapters); - - AdapterData* adata = &Adapters[0]; - dev = alldevs; - while (dev) - { - adata->Internal = dev; - -#ifdef __WIN32__ - // hax - int len = strlen(dev->name); - len -= 12; if (len > 127) len = 127; - strncpy(adata->DeviceName, &dev->name[12], len); - adata->DeviceName[len] = '\0'; -#else - strncpy(adata->DeviceName, dev->name, 127); - adata->DeviceName[127] = '\0'; - - strncpy(adata->FriendlyName, adata->DeviceName, 127); - adata->FriendlyName[127] = '\0'; -#endif // __WIN32__ - - dev = dev->next; - adata++; - } - -#ifdef __WIN32__ - - ULONG bufsize = 16384; - IP_ADAPTER_ADDRESSES* buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize); - ULONG uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize); - if (uret == ERROR_BUFFER_OVERFLOW) - { - HeapFree(GetProcessHeap(), 0, buf); - buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize); - uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize); - } - if (uret != ERROR_SUCCESS) - { - printf("GetAdaptersAddresses() shat itself: %08X\n", uret); - return false; - } - - for (int i = 0; i < NumAdapters; i++) - { - adata = &Adapters[i]; - IP_ADAPTER_ADDRESSES* addr = buf; - while (addr) - { - if (strcmp(addr->AdapterName, adata->DeviceName)) - { - addr = addr->Next; - continue; - } - - WideCharToMultiByte(CP_UTF8, 0, addr->FriendlyName, 127, adata->FriendlyName, 127, NULL, NULL); - adata->FriendlyName[127] = '\0'; - - WideCharToMultiByte(CP_UTF8, 0, addr->Description, 127, adata->Description, 127, NULL, NULL); - adata->Description[127] = '\0'; - - if (addr->PhysicalAddressLength != 6) - { - printf("weird MAC addr length %d for %s\n", addr->PhysicalAddressLength, addr->AdapterName); - } - else - memcpy(adata->MAC, addr->PhysicalAddress, 6); - - IP_ADAPTER_UNICAST_ADDRESS* ipaddr = addr->FirstUnicastAddress; - while (ipaddr) - { - SOCKADDR* sa = ipaddr->Address.lpSockaddr; - if (sa->sa_family == AF_INET) - { - struct in_addr sa4 = ((sockaddr_in*)sa)->sin_addr; - memcpy(adata->IP_v4, &sa4, 4); - } - - ipaddr = ipaddr->Next; - } - - break; - } - } - - HeapFree(GetProcessHeap(), 0, buf); - -#else - - struct ifaddrs* addrs; - if (getifaddrs(&addrs) != 0) - { - printf("getifaddrs() shat itself :(\n"); - return false; - } - - for (int i = 0; i < NumAdapters; i++) - { - adata = &Adapters[i]; - struct ifaddrs* curaddr = addrs; - while (curaddr) - { - if (strcmp(curaddr->ifa_name, adata->DeviceName)) - { - curaddr = curaddr->ifa_next; - continue; - } - - if (!curaddr->ifa_addr) - { - printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); - curaddr = curaddr->ifa_next; - continue; - } - - u16 af = curaddr->ifa_addr->sa_family; - if (af == AF_INET) - { - struct sockaddr_in* sa = (sockaddr_in*)curaddr->ifa_addr; - memcpy(adata->IP_v4, &sa->sin_addr, 4); - } - else if (af == AF_PACKET) - { - struct sockaddr_ll* sa = (sockaddr_ll*)curaddr->ifa_addr; - if (sa->sll_halen != 6) - printf("weird MAC length %d for %s\n", sa->sll_halen, curaddr->ifa_name); - else - memcpy(adata->MAC, sa->sll_addr, 6); - } - - curaddr = curaddr->ifa_next; - } - } - - freeifaddrs(addrs); - -#endif // __WIN32__ - - if (!open_adapter) return true; - if (PCapAdapter) pcap_close(PCapAdapter); - - // open pcap device - PCapAdapterData = &Adapters[0]; - for (int i = 0; i < NumAdapters; i++) - { - if (!strncmp(Adapters[i].DeviceName, Config::LANDevice, 128)) - PCapAdapterData = &Adapters[i]; - } - - dev = (pcap_if_t*)PCapAdapterData->Internal; - PCapAdapter = pcap_open_live(dev->name, 2048, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf); - if (!PCapAdapter) - { - printf("PCap: failed to open adapter %s\n", errbuf); - return false; - } - - pcap_freealldevs(alldevs); - - if (pcap_setnonblock(PCapAdapter, 1, errbuf) < 0) - { - printf("PCap: failed to set nonblocking mode\n"); - pcap_close(PCapAdapter); PCapAdapter = NULL; - return false; - } - - return true; -} - -void DeInit() -{ - if (PCapLib) - { - if (PCapAdapter) - { - pcap_close(PCapAdapter); - PCapAdapter = NULL; - } - - SDL_UnloadObject(PCapLib); - PCapLib = NULL; - } -} - - -void RXCallback(u_char* blarg, const struct pcap_pkthdr* header, const u_char* data) -{ - while (RXNum > 0); - - if (header->len > 2048-64) return; - - PacketLen = header->len; - memcpy(PacketBuffer, data, PacketLen); - RXNum = 1; -} - -int SendPacket(u8* data, int len) -{ - if (PCapAdapter == NULL) - return 0; - - if (len > 2048) - { - printf("LAN_SendPacket: error: packet too long (%d)\n", len); - return 0; - } - - pcap_sendpacket(PCapAdapter, data, len); - // TODO: check success - return len; -} - -int RecvPacket(u8* data) -{ - if (PCapAdapter == NULL) - return 0; - - int ret = 0; - if (RXNum > 0) - { - memcpy(data, PacketBuffer, PacketLen); - ret = PacketLen; - RXNum = 0; - } - - pcap_dispatch(PCapAdapter, 1, RXCallback, NULL); - return ret; -} - -} diff --git a/src/libui_sdl/LAN_PCap.h b/src/libui_sdl/LAN_PCap.h deleted file mode 100644 index 250b8e90..00000000 --- a/src/libui_sdl/LAN_PCap.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef LAN_PCAP_H -#define LAN_PCAP_H - -#include "../types.h" - -namespace LAN_PCap -{ - -typedef struct -{ - char DeviceName[128]; - char FriendlyName[128]; - char Description[128]; - - u8 MAC[6]; - u8 IP_v4[4]; - - void* Internal; - -} AdapterData; - - -extern AdapterData* Adapters; -extern int NumAdapters; - - -bool Init(bool open_adapter); -void DeInit(); - -int SendPacket(u8* data, int len); -int RecvPacket(u8* data); - -} - -#endif // LAN_PCAP_H diff --git a/src/libui_sdl/LAN_Socket.cpp b/src/libui_sdl/LAN_Socket.cpp deleted file mode 100644 index c6fbd4b6..00000000 --- a/src/libui_sdl/LAN_Socket.cpp +++ /dev/null @@ -1,1145 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -// indirect LAN interface, powered by BSD sockets. - -#include -#include -#include -#include "../Wifi.h" -#include "LAN_Socket.h" -#include "../Config.h" - -#ifdef __WIN32__ - #include - #include - #define socket_t SOCKET - #define sockaddr_t SOCKADDR -#else - #include - #include - #include - #include - #include - #include - #include - #define socket_t int - #define sockaddr_t struct sockaddr - #define closesocket close -#endif - -#ifndef INVALID_SOCKET -#define INVALID_SOCKET (socket_t)-1 -#endif - - -namespace LAN_Socket -{ - -const u32 kSubnet = 0x0A400000; -const u32 kServerIP = kSubnet | 0x01; -const u32 kDNSIP = kSubnet | 0x02; -const u32 kClientIP = kSubnet | 0x10; - -const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44}; -const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55}; - -u8 PacketBuffer[2048]; -int PacketLen; -volatile int RXNum; - -u16 IPv4ID; - - -// TODO: UDP sockets -// * use FIFO list -// * assign new socket when seeing new IP/port - - -typedef struct -{ - u8 DestIP[4]; - u16 SourcePort; - u16 DestPort; - - u32 SeqNum; // sequence number for incoming frames - u32 AckNum; - - // 0: unused - // 1: connected - u8 Status; - - socket_t Backend; - -} TCPSocket; - -typedef struct -{ - u8 DestIP[4]; - u16 SourcePort; - u16 DestPort; - - socket_t Backend; - struct sockaddr_in BackendAddr; - -} UDPSocket; - -TCPSocket TCPSocketList[16]; -UDPSocket UDPSocketList[4]; - -int UDPSocketID = 0; - - -bool Init() -{ - // TODO: how to deal with cases where an adapter is unplugged or changes config?? - //if (PCapLib) return true; - - //Lib = NULL; - PacketLen = 0; - RXNum = 0; - - IPv4ID = 1; - - memset(TCPSocketList, 0, sizeof(TCPSocketList)); - memset(UDPSocketList, 0, sizeof(UDPSocketList)); - - UDPSocketID = 0; - - return true; -} - -void DeInit() -{ - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - TCPSocket* sock = &TCPSocketList[i]; - if (sock->Backend) closesocket(sock->Backend); - } - - for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) - { - UDPSocket* sock = &UDPSocketList[i]; - if (sock->Backend) closesocket(sock->Backend); - } -} - - -void FinishUDPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* udpheader = &data[0x22]; - - // lengths - *(u16*)&ipheader[2] = htons(len - 0xE); - *(u16*)&udpheader[4] = htons(len - (0xE + 0x14)); - - // IP checksum - u32 tmp = 0; - - for (int i = 0; i < 20; i += 2) - tmp += ntohs(*(u16*)&ipheader[i]); - while (tmp >> 16) - tmp = (tmp & 0xFFFF) + (tmp >> 16); - tmp ^= 0xFFFF; - *(u16*)&ipheader[10] = htons(tmp); - - // UDP checksum - // (note: normally not mandatory, but some older sgIP versions require it) - tmp = 0; - tmp += ntohs(*(u16*)&ipheader[12]); - tmp += ntohs(*(u16*)&ipheader[14]); - tmp += ntohs(*(u16*)&ipheader[16]); - tmp += ntohs(*(u16*)&ipheader[18]); - tmp += ntohs(0x1100); - tmp += (len-0x22); - for (u8* i = udpheader; i < &udpheader[len-0x23]; i += 2) - tmp += ntohs(*(u16*)i); - if (len & 1) - tmp += ntohs((u_short)udpheader[len-0x23]); - while (tmp >> 16) - tmp = (tmp & 0xFFFF) + (tmp >> 16); - tmp ^= 0xFFFF; - if (tmp == 0) tmp = 0xFFFF; - *(u16*)&udpheader[6] = htons(tmp); -} - -void FinishTCPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* tcpheader = &data[0x22]; - - // lengths - *(u16*)&ipheader[2] = htons(len - 0xE); - - // IP checksum - u32 tmp = 0; - - for (int i = 0; i < 20; i += 2) - tmp += ntohs(*(u16*)&ipheader[i]); - while (tmp >> 16) - tmp = (tmp & 0xFFFF) + (tmp >> 16); - tmp ^= 0xFFFF; - *(u16*)&ipheader[10] = htons(tmp); - - u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14; - - // TCP checksum - tmp = 0; - tmp += ntohs(*(u16*)&ipheader[12]); - tmp += ntohs(*(u16*)&ipheader[14]); - tmp += ntohs(*(u16*)&ipheader[16]); - tmp += ntohs(*(u16*)&ipheader[18]); - tmp += ntohs(0x0600); - tmp += tcplen; - for (u8* i = tcpheader; i < &tcpheader[tcplen-1]; i += 2) - tmp += ntohs(*(u16*)i); - if (tcplen & 1) - tmp += ntohs((u_short)tcpheader[tcplen-1]); - while (tmp >> 16) - tmp = (tmp & 0xFFFF) + (tmp >> 16); - tmp ^= 0xFFFF; - *(u16*)&tcpheader[16] = htons(tmp); -} - - -void HandleDHCPFrame(u8* data, int len) -{ - u8 type = 0xFF; - - u32 transid = *(u32*)&data[0x2E]; - - u8* options = &data[0x11A]; - for (;;) - { - if (options >= &data[len]) break; - u8 opt = *options++; - if (opt == 255) break; - - u8 len = *options++; - switch (opt) - { - case 53: // frame type - type = options[0]; - break; - } - - options += len; - } - - if (type == 0xFF) - { - printf("DHCP: bad frame\n"); - return; - } - - printf("DHCP: frame type %d, transid %08X\n", type, transid); - - if (type == 1 || // discover - type == 3) // request - { - u8 resp[512]; - u8* out = &resp[0]; - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x11; // protocol (UDP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = htonl(kServerIP); out += 4; // source IP - if (type == 1) - { - *(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP - } - else if (type == 3) - { - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - } - - // UDP - u8* udpheader = out; - *(u16*)out = htons(67); out += 2; // source port - *(u16*)out = htons(68); out += 2; // destination port - *(u16*)out = 0; out += 2; // length - *(u16*)out = 0; out += 2; // checksum - - // DHCP - u8* body = out; - *out++ = 0x02; - *out++ = 0x01; - *out++ = 0x06; - *out++ = 0x00; - *(u32*)out = transid; out += 4; - *(u16*)out = 0; out += 2; // seconds elapsed - *(u16*)out = 0; out += 2; - *(u32*)out = htonl(0x00000000); out += 4; // client IP - *(u32*)out = htonl(kClientIP); out += 4; // your IP - *(u32*)out = htonl(kServerIP); out += 4; // server IP - *(u32*)out = htonl(0x00000000); out += 4; // gateway IP - memcpy(out, &data[6], 6); out += 6; - memset(out, 0, 10); out += 10; - memset(out, 0, 192); out += 192; - *(u32*)out = 0x63538263; out += 4; // DHCP magic - - // DHCP options - *out++ = 53; *out++ = 1; - *out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack - *out++ = 1; *out++ = 4; - *(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask - *out++ = 3; *out++ = 4; - *(u32*)out = htonl(kServerIP); out += 4; // router - *out++ = 51; *out++ = 4; - *(u32*)out = htonl(442030); out += 4; // lease time - *out++ = 54; *out++ = 4; - *(u32*)out = htonl(kServerIP); out += 4; // DHCP server - *out++ = 6; *out++ = 4; - *(u32*)out = htonl(kDNSIP); out += 4; // DNS (hax) - - *out++ = 0xFF; - memset(out, 0, 20); out += 20; - - u32 framelen = (u32)(out - &resp[0]); - if (framelen & 1) { *out++ = 0; framelen++; } - FinishUDPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; - } -} - -void HandleDNSFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* udpheader = &data[0x22]; - u8* dnsbody = &data[0x2A]; - - u32 srcip = ntohl(*(u32*)&ipheader[12]); - u16 srcport = ntohs(*(u16*)&udpheader[0]); - - u16 id = ntohs(*(u16*)&dnsbody[0]); - u16 flags = ntohs(*(u16*)&dnsbody[2]); - u16 numquestions = ntohs(*(u16*)&dnsbody[4]); - u16 numanswers = ntohs(*(u16*)&dnsbody[6]); - u16 numauth = ntohs(*(u16*)&dnsbody[8]); - u16 numadd = ntohs(*(u16*)&dnsbody[10]); - - printf("DNS: ID=%04X, flags=%04X, Q=%d, A=%d, auth=%d, add=%d\n", - id, flags, numquestions, numanswers, numauth, numadd); - - // for now we only take 'simple' DNS requests - if (flags & 0x8000) return; - if (numquestions != 1 || numanswers != 0) return; - - u8 resp[1024]; - u8* out = &resp[0]; - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x11; // protocol (UDP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = htonl(kDNSIP); out += 4; // source IP - *(u32*)out = htonl(srcip); out += 4; // destination IP - - // UDP - u8* resp_udpheader = out; - *(u16*)out = htons(53); out += 2; // source port - *(u16*)out = htons(srcport); out += 2; // destination port - *(u16*)out = 0; out += 2; // length - *(u16*)out = 0; out += 2; // checksum - - // DNS - u8* resp_body = out; - *(u16*)out = htons(id); out += 2; // ID - *(u16*)out = htons(0x8000); out += 2; // flags - *(u16*)out = htons(numquestions); out += 2; // num questions - *(u16*)out = htons(numquestions); out += 2; // num answers - *(u16*)out = 0; out += 2; // num authority - *(u16*)out = 0; out += 2; // num additional - - u32 curoffset = 12; - for (u16 i = 0; i < numquestions; i++) - { - if (curoffset >= (len-0x2A)) return; - - u8 bitlength = 0; - while ((bitlength = dnsbody[curoffset++]) != 0) - curoffset += bitlength; - - curoffset += 4; - } - - u32 qlen = curoffset-12; - if (qlen > 512) return; - memcpy(out, &dnsbody[12], qlen); out += qlen; - - curoffset = 12; - for (u16 i = 0; i < numquestions; i++) - { - // assemble the requested domain name - u8 bitlength = 0; - char domainname[256] = ""; int o = 0; - while ((bitlength = dnsbody[curoffset++]) != 0) - { - if ((o+bitlength) >= 255) - { - // welp. atleast try not to explode. - domainname[o++] = '\0'; - break; - } - - strncpy(&domainname[o], (const char *)&dnsbody[curoffset], bitlength); - o += bitlength; - - curoffset += bitlength; - if (dnsbody[curoffset] != 0) - domainname[o++] = '.'; - else - domainname[o++] = '\0'; - } - - u16 type = ntohs(*(u16*)&dnsbody[curoffset]); - u16 cls = ntohs(*(u16*)&dnsbody[curoffset+2]); - - printf("- q%d: %04X %04X %s", i, type, cls, domainname); - - // get answer - struct addrinfo dns_hint; - struct addrinfo* dns_res; - u32 addr_res; - - memset(&dns_hint, 0, sizeof(dns_hint)); - dns_hint.ai_family = AF_INET; // TODO: other address types (INET6, etc) - if (getaddrinfo(domainname, "0", &dns_hint, &dns_res) == 0) - { - struct addrinfo* p = dns_res; - while (p) - { - struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr; - /*printf(" -> %d.%d.%d.%d", - addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, - addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4);*/ - - //addr_res = addr->sin_addr.S_un.S_addr; - addr_res = *(u32*)&addr->sin_addr; - p = p->ai_next; - } - } - else - { - printf(" shat itself :("); - addr_res = 0; - } - - printf("\n"); - curoffset += 4; - - // TODO: betterer support - // (under which conditions does the C00C marker work?) - *(u16*)out = htons(0xC00C); out += 2; - *(u16*)out = htons(type); out += 2; - *(u16*)out = htons(cls); out += 2; - *(u32*)out = htonl(3600); out += 4; // TTL (hardcoded for now) - *(u16*)out = htons(4); out += 2; // address length - *(u32*)out = addr_res; out += 4; // address - } - - u32 framelen = (u32)(out - &resp[0]); - if (framelen & 1) { *out++ = 0; framelen++; } - FinishUDPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void UDP_BuildIncomingFrame(UDPSocket* sock, u8* data, int len) -{ - u8 resp[2048]; - u8* out = &resp[0]; - - if (len > 1536) return; - - // ethernet - memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x11; // protocol (UDP) - *(u16*)out = 0; out += 2; // checksum - memcpy(out, sock->DestIP, 4); out += 4; // source IP - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - - // UDP - u8* resp_tcpheader = out; - *(u16*)out = htons(sock->DestPort); out += 2; // source port - *(u16*)out = htons(sock->SourcePort); out += 2; // destination port - *(u16*)out = htons(len+8); out += 2; // length of header+data - *(u16*)out = 0; out += 2; // checksum - - memcpy(out, data, len); out += len; - - u32 framelen = (u32)(out - &resp[0]); - FinishUDPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void HandleUDPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* udpheader = &data[0x22]; - - // debug - /*for (int j = 0; j < len; j += 16) - { - int rem = len - j; - if (rem > 16) rem = 16; - for (int i = 0; i < rem; i++) - { - printf("%02X ", data[i+j]); - } - printf("\n"); - }*/ - - u16 srcport = ntohs(*(u16*)&udpheader[0]); - u16 dstport = ntohs(*(u16*)&udpheader[2]); - - int sockid = -1; - UDPSocket* sock; - for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) - { - sock = &UDPSocketList[i]; - if (sock->Backend != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && - sock->SourcePort == srcport && sock->DestPort == dstport) - { - sockid = i; - break; - } - } - - if (sockid == -1) - { - sockid = UDPSocketID; - sock = &UDPSocketList[sockid]; - - UDPSocketID++; - if (UDPSocketID >= (sizeof(UDPSocketList)/sizeof(UDPSocket))) - UDPSocketID = 0; - - if (sock->Backend != 0) - { - printf("LANMAGIC: closing previous UDP socket #%d\n", sockid); - closesocket(sock->Backend); - } - - sock->Backend = socket(AF_INET, SOCK_DGRAM, 0); - - memcpy(sock->DestIP, &ipheader[16], 4); - sock->SourcePort = srcport; - sock->DestPort = dstport; - - memset(&sock->BackendAddr, 0, sizeof(sock->BackendAddr)); - sock->BackendAddr.sin_family = AF_INET; - sock->BackendAddr.sin_port = htons(dstport); - memcpy(&sock->BackendAddr.sin_addr, &ipheader[16], 4); - /*if (bind(sock->Backend, (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)) == -1) - { - printf("bind() shat itself :(\n"); - }*/ - - printf("LANMAGIC: opening UDP socket #%d to %d.%d.%d.%d:%d, srcport %d\n", - sockid, - ipheader[16], ipheader[17], ipheader[18], ipheader[19], - dstport, srcport); - } - - u16 udplen = ntohs(*(u16*)&udpheader[4]) - 8; - - printf("UDP: socket %d sending %d bytes\n", sockid, udplen); - sendto(sock->Backend, (char*)&udpheader[8], udplen, 0, - (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)); -} - -void TCP_SYNACK(TCPSocket* sock, u8* data, int len) -{ - u8 resp[128]; - u8* out = &resp[0]; - - u8* ipheader = &data[0xE]; - u8* tcpheader = &data[0x22]; - - u32 seqnum = htonl(*(u32*)&tcpheader[4]); - seqnum++; - sock->AckNum = seqnum; - - //printf("SYNACK SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum); - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x06; // protocol (TCP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = *(u32*)&ipheader[16]; out += 4; // source IP - *(u32*)out = *(u32*)&ipheader[12]; out += 4; // destination IP - - // TCP - u8* resp_tcpheader = out; - *(u16*)out = *(u16*)&tcpheader[2]; out += 2; // source port - *(u16*)out = *(u16*)&tcpheader[0]; out += 2; // destination port - *(u32*)out = htonl(sock->SeqNum); out += 4; sock->SeqNum++; // seq number - *(u32*)out = htonl(seqnum); out += 4; // ack seq number - *(u16*)out = htons(0x8012); out += 2; // flags (SYN+ACK) - *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) - *(u16*)out = 0; out += 2; // checksum - *(u16*)out = 0; out += 2; // urgent pointer - - // TCP options - *out++ = 0x02; *out++ = 0x04; // max segment size - *(u16*)out = htons(0x05B4); out += 2; - *out++ = 0x01; - *out++ = 0x01; - *out++ = 0x04; *out++ = 0x02; // SACK permitted - *out++ = 0x01; - *out++ = 0x03; *out++ = 0x03; // window size - *out++ = 0x08; - - u32 framelen = (u32)(out - &resp[0]); - //if (framelen & 1) { *out++ = 0; framelen++; } - FinishTCPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void TCP_ACK(TCPSocket* sock, bool fin) -{ - u8 resp[64]; - u8* out = &resp[0]; - - u16 flags = 0x5010; - if (fin) flags |= 0x0001; - - //printf("%sACK SEQ=%08X|%08X\n", fin?"FIN":" ", sock->SeqNum, sock->AckNum); - - // ethernet - memcpy(out, Wifi::GetMAC(), 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x06; // protocol (TCP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = *(u32*)&sock->DestIP; out += 4; // source IP - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - - // TCP - u8* resp_tcpheader = out; - *(u16*)out = htonl(sock->DestPort); out += 2; // source port - *(u16*)out = htonl(sock->SourcePort); out += 2; // destination port - *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number - *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number - *(u16*)out = htons(flags); out += 2; // flags - *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) - *(u16*)out = 0; out += 2; // checksum - *(u16*)out = 0; out += 2; // urgent pointer - - u32 framelen = (u32)(out - &resp[0]); - //if (framelen & 1) { *out++ = 0; framelen++; } - FinishTCPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void TCP_BuildIncomingFrame(TCPSocket* sock, u8* data, int len) -{ - u8 resp[2048]; - u8* out = &resp[0]; - - if (len > 1536) return; -//printf("INCOMING SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum); - // ethernet - memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x06; // protocol (TCP) - *(u16*)out = 0; out += 2; // checksum - memcpy(out, sock->DestIP, 4); out += 4; // source IP - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - - // TCP - u8* resp_tcpheader = out; - *(u16*)out = htons(sock->DestPort); out += 2; // source port - *(u16*)out = htons(sock->SourcePort); out += 2; // destination port - *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number - *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number - *(u16*)out = htons(0x5018); out += 2; // flags (ACK, PSH) - *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) - *(u16*)out = 0; out += 2; // checksum - *(u16*)out = 0; out += 2; // urgent pointer - - memcpy(out, data, len); out += len; - - u32 framelen = (u32)(out - &resp[0]); - FinishTCPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; - - sock->SeqNum += len; -} - -void HandleTCPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* tcpheader = &data[0x22]; - - u16 srcport = ntohs(*(u16*)&tcpheader[0]); - u16 dstport = ntohs(*(u16*)&tcpheader[2]); - u16 flags = ntohs(*(u16*)&tcpheader[12]); - - u32 tcpheaderlen = 4 * (flags >> 12); - u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14; - u32 tcpdatalen = tcplen - tcpheaderlen; - - /*printf("tcpflags=%04X header=%d data=%d seq=%08X|%08X\n", - flags, tcpheaderlen, tcpdatalen, - ntohl(*(u32*)&tcpheader[4]), - ntohl(*(u32*)&tcpheader[8]));*/ - - if (flags & 0x002) // SYN - { - int sockid = -1; - TCPSocket* sock; - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - sock = &TCPSocketList[i]; - if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && - sock->SourcePort == srcport && sock->DestPort == dstport) - { - printf("LANMAGIC: duplicate TCP socket\n"); - sockid = i; - break; - } - } - - if (sockid == -1) - { - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - sock = &TCPSocketList[i]; - if (sock->Status == 0) - { - sockid = i; - break; - } - } - } - - if (sockid == -1) - { - printf("LANMAGIC: !! TCP SOCKET LIST FULL\n"); - return; - } - - printf("LANMAGIC: opening TCP socket #%d to %d.%d.%d.%d:%d, srcport %d\n", - sockid, - ipheader[16], ipheader[17], ipheader[18], ipheader[19], - dstport, srcport); - - // keep track of it - sock->Status = 1; - memcpy(sock->DestIP, &ipheader[16], 4); - sock->DestPort = dstport; - sock->SourcePort = srcport; - sock->SeqNum = 0x13370000; - sock->AckNum = 0; - - // open backend socket - if (!sock->Backend) - { - sock->Backend = socket(AF_INET, SOCK_STREAM, 0); - } - - struct sockaddr_in conn_addr; - memset(&conn_addr, 0, sizeof(conn_addr)); - conn_addr.sin_family = AF_INET; - memcpy(&conn_addr.sin_addr, &ipheader[16], 4); - conn_addr.sin_port = htons(dstport); - if (connect(sock->Backend, (sockaddr*)&conn_addr, sizeof(conn_addr)) == -1) - { - printf("connect() shat itself :(\n"); - } - else - { - // acknowledge it - TCP_SYNACK(sock, data, len); - } - } - else - { - int sockid = -1; - TCPSocket* sock; - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - sock = &TCPSocketList[i]; - if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && - sock->SourcePort == srcport && sock->DestPort == dstport) - { - sockid = i; - break; - } - } - - if (sockid == -1) - { - printf("LANMAGIC: bad TCP packet\n"); - return; - } - - // TODO: check those - u32 seqnum = ntohl(*(u32*)&tcpheader[4]); - u32 acknum = ntohl(*(u32*)&tcpheader[8]); - sock->SeqNum = acknum; - sock->AckNum = seqnum + tcpdatalen; - - // send data over the socket - if (tcpdatalen > 0) - { - u8* tcpdata = &tcpheader[tcpheaderlen]; - - printf("TCP: socket %d sending %d bytes (flags=%04X)\n", sockid, tcpdatalen, flags); - send(sock->Backend, (char*)tcpdata, tcpdatalen, 0); - - // kind of a hack, there - TCP_ACK(sock, false); - } - - if (flags & 0x001) // FIN - { - // TODO: timeout etc - printf("TCP: socket %d closing\n", sockid); - - sock->Status = 0; - closesocket(sock->Backend); - sock->Backend = 0; - } - } -} - -void HandleARPFrame(u8* data, int len) -{ - u16 protocol = ntohs(*(u16*)&data[0x10]); - if (protocol != 0x0800) return; - - u16 op = ntohs(*(u16*)&data[0x14]); - u32 targetip = ntohl(*(u32*)&data[0x26]); - - // TODO: handle ARP to the client - // this only handles ARP to the DHCP/router - - if (op == 1) - { - // opcode 1=req 2=reply - // sender MAC - // sender IP - // target MAC - // target IP - - const u8* targetmac; - if (targetip == kServerIP) targetmac = kServerMAC; - else if (targetip == kDNSIP) targetmac = kDNSMAC; - else return; - - u8 resp[64]; - u8* out = &resp[0]; - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0806); out += 2; - - // ARP - *(u16*)out = htons(0x0001); out += 2; // hardware type - *(u16*)out = htons(0x0800); out += 2; // protocol - *out++ = 6; // MAC address size - *out++ = 4; // IP address size - *(u16*)out = htons(0x0002); out += 2; // opcode - memcpy(out, targetmac, 6); out += 6; - *(u32*)out = htonl(targetip); out += 4; - memcpy(out, &data[0x16], 6+4); out += 6+4; - - u32 framelen = (u32)(out - &resp[0]); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; - } - else - { - printf("wat??\n"); - } -} - -void HandlePacket(u8* data, int len) -{ - u16 ethertype = ntohs(*(u16*)&data[0xC]); - - if (ethertype == 0x0800) // IPv4 - { - u8 protocol = data[0x17]; - if (protocol == 0x11) // UDP - { - u16 srcport = ntohs(*(u16*)&data[0x22]); - u16 dstport = ntohs(*(u16*)&data[0x24]); - if (srcport == 68 && dstport == 67) // DHCP - { - printf("LANMAGIC: DHCP packet\n"); - return HandleDHCPFrame(data, len); - } - else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS - { - printf("LANMAGIC: DNS packet\n"); - return HandleDNSFrame(data, len); - } - - printf("LANMAGIC: UDP packet %d->%d\n", srcport, dstport); - return HandleUDPFrame(data, len); - } - else if (protocol == 0x06) // TCP - { - printf("LANMAGIC: TCP packet\n"); - return HandleTCPFrame(data, len); - } - else - printf("LANMAGIC: unsupported IP protocol %02X\n", protocol); - } - else if (ethertype == 0x0806) // ARP - { - printf("LANMAGIC: ARP packet\n"); - return HandleARPFrame(data, len); - } - else - printf("LANMAGIC: unsupported ethernet type %04X\n", ethertype); -} - -int SendPacket(u8* data, int len) -{ - if (len > 2048) - { - printf("LAN_SendPacket: error: packet too long (%d)\n", len); - return 0; - } - - HandlePacket(data, len); - return len; -} - -int RecvPacket(u8* data) -{ - int ret = 0; - if (RXNum > 0) - { - memcpy(data, PacketBuffer, PacketLen); - ret = PacketLen; - RXNum = 0; - } - - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - TCPSocket* sock = &TCPSocketList[i]; - if (sock->Status != 1) continue; - - fd_set fd; - struct timeval tv; - - FD_ZERO(&fd); - FD_SET(sock->Backend, &fd); - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (!select(sock->Backend+1, &fd, 0, 0, &tv)) - { - continue; - } - - u8 recvbuf[1024]; - int recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); - if (recvlen < 1) - { - if (recvlen == 0) - { - // socket has closed from the other side - printf("TCP: socket %d closed from other side\n", i); - sock->Status = 2; - TCP_ACK(sock, true); - } - continue; - } - - printf("TCP: socket %d receiving %d bytes\n", i, recvlen); - TCP_BuildIncomingFrame(sock, recvbuf, recvlen); - - // debug - /*for (int j = 0; j < recvlen; j += 16) - { - int rem = recvlen - j; - if (rem > 16) rem = 16; - for (int k = 0; k < rem; k++) - { - printf("%02X ", recvbuf[k+j]); - } - printf("\n"); - }*/ - - //recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); - //if (recvlen == 0) printf("it closed immediately after\n"); - } - - for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) - { - UDPSocket* sock = &UDPSocketList[i]; - if (sock->Backend == 0) continue; - - fd_set fd; - struct timeval tv; - - FD_ZERO(&fd); - FD_SET(sock->Backend, &fd); - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (!select(sock->Backend+1, &fd, 0, 0, &tv)) - { - continue; - } - - u8 recvbuf[1024]; - sockaddr_t fromAddr; - socklen_t fromLen = sizeof(sockaddr_t); - int recvlen = recvfrom(sock->Backend, (char*)recvbuf, 1024, 0, &fromAddr, &fromLen); - if (recvlen < 1) continue; - - if (fromAddr.sa_family != AF_INET) continue; - struct sockaddr_in* fromAddrIn = (struct sockaddr_in*)&fromAddr; - if (memcmp(&fromAddrIn->sin_addr, sock->DestIP, 4)) continue; - if (ntohs(fromAddrIn->sin_port) != sock->DestPort) continue; - - printf("UDP: socket %d receiving %d bytes\n", i, recvlen); - UDP_BuildIncomingFrame(sock, recvbuf, recvlen); - } - - return ret; -} - -} diff --git a/src/libui_sdl/LAN_Socket.h b/src/libui_sdl/LAN_Socket.h deleted file mode 100644 index 8453a5f4..00000000 --- a/src/libui_sdl/LAN_Socket.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef LAN_SOCKET_H -#define LAN_SOCKET_H - -#include "../types.h" - -namespace LAN_Socket -{ - -// - - -bool Init(); -void DeInit(); - -int SendPacket(u8* data, int len); -int RecvPacket(u8* data); - -} - -#endif // LAN_SOCKET_H diff --git a/src/libui_sdl/MelonCap.cpp b/src/libui_sdl/MelonCap.cpp deleted file mode 100644 index 2658b666..00000000 --- a/src/libui_sdl/MelonCap.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include "MelonCap.h" -#include "libui/ui.h" -#include "../NDS.h" -#include "../GPU.h" - -#include -#include -#include -#include - - -namespace MelonCap -{ - -uiWindow* Window; -uiArea* Area; -uiAreaHandler AreaHandler; -uiDrawBitmap* WinBitmap; -bool WinBitmapInited; - -u32* WinBitmapData; - -// this crap was built from the reverse-engineering of ds_capture.exe -// mixed in with their Linux capture sample code - -GUID InterfaceClass = {0xA0B880F6, 0xD6A5, 0x4700, {0xA8, 0xEA, 0x22, 0x28, 0x2A, 0xCA, 0x55, 0x87}}; -HANDLE CapHandle; -WINUSB_INTERFACE_HANDLE CapUSBHandle; - - -void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) -{ - if (!WinBitmapInited) - { - if (WinBitmap) uiDrawFreeBitmap(WinBitmap); - - WinBitmapInited = true; - WinBitmap = uiDrawNewBitmap(params->Context, 768, 384, 0); - } - - if (!WinBitmap) return; - if (!WinBitmapData) return; - - uiRect rc = {0, 0, 768, 384}; - - uiDrawBitmapUpdate(WinBitmap, WinBitmapData); - uiDrawBitmapDraw(params->Context, WinBitmap, &rc, &rc, 0); -} - -void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt) -{ -} - -void OnAreaMouseCrossed(uiAreaHandler* handler, uiArea* area, int left) -{ -} - -void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) -{ -} - -int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) -{ - return 1; -} - -void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height) -{ -} - - -void Init() -{ - printf("MelonCap init\n"); - - HDEVINFO devinfo = SetupDiGetClassDevsW(&InterfaceClass, NULL, NULL, DIGCF_DEVICEINTERFACE|DIGCF_PRESENT); - if (devinfo == INVALID_HANDLE_VALUE) return; - - int member = 0; - bool good = false; - for (;;) - { - SP_DEVICE_INTERFACE_DATA interfacedata; - memset(&interfacedata, 0, sizeof(interfacedata)); - interfacedata.cbSize = sizeof(interfacedata); - - BOOL ret = SetupDiEnumDeviceInterfaces(devinfo, NULL, &InterfaceClass, member, &interfacedata); - if (!ret) - { - printf("found %d interfaces\n", member); - break; - } - - DWORD requiredsize = 0; - SetupDiGetDeviceInterfaceDetailW(devinfo, &interfacedata, NULL, NULL, &requiredsize, NULL); - printf("%d: required size %d\n", member, requiredsize); - - PSP_DEVICE_INTERFACE_DETAIL_DATA_W interfacedetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)new u8[requiredsize]; - interfacedetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_W); - ret = SetupDiGetDeviceInterfaceDetailW(devinfo, &interfacedata, interfacedetail, requiredsize, NULL, NULL); - if (ret) - { - printf("got interface detail: path=%S\n", interfacedetail->DevicePath); - HANDLE file = CreateFileW(interfacedetail->DevicePath, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file != INVALID_HANDLE_VALUE) - { - WINUSB_INTERFACE_HANDLE usbhandle; - ret = WinUsb_Initialize(file, &usbhandle); - if (ret) - { - int val; - val = 0x1E; - WinUsb_SetPipePolicy(usbhandle, 0x00, PIPE_TRANSFER_TIMEOUT, 4, &val); - val = 0x32; - WinUsb_SetPipePolicy(usbhandle, 0x82, PIPE_TRANSFER_TIMEOUT, 4, &val); - val = 0x01; - WinUsb_SetPipePolicy(usbhandle, 0x82, RAW_IO, 1, &val); - - printf("looking good\n"); - good = true; - - CapHandle = file; - CapUSBHandle = usbhandle; - } - else - CloseHandle(file); - } - } - - delete[] (u8*)interfacedetail; - - if (good) break; - - member++; - } - - SetupDiDestroyDeviceInfoList(devinfo); - - - AreaHandler.Draw = OnAreaDraw; - AreaHandler.MouseEvent = OnAreaMouseEvent; - AreaHandler.MouseCrossed = OnAreaMouseCrossed; - AreaHandler.DragBroken = OnAreaDragBroken; - AreaHandler.KeyEvent = OnAreaKeyEvent; - AreaHandler.Resize = OnAreaResize; - - WinBitmapInited = false; - WinBitmapData = new u32[768*384]; - - Window = uiNewWindow("melonDS - topnotch pixel checker", 768, 384, 0, 0, 0); - Area = uiNewArea(&AreaHandler); - uiWindowSetChild(Window, uiControl(Area)); - - uiControlShow(uiControl(Window)); -} - -void DeInit() -{ - uiControlDestroy(uiControl(Window)); - uiDrawFreeBitmap(WinBitmap); - WinBitmapInited = false; - delete[] WinBitmapData; - - WinUsb_Free(CapUSBHandle); - CloseHandle(CapHandle); -} - - -int VendorIn(u8 req, u16 len, u8* buf) -{ - WINUSB_SETUP_PACKET pkt; - pkt.RequestType = 0xC0; // device to host - pkt.Request = req; - pkt.Value = 0; // ????? - pkt.Index = 0; - pkt.Length = len; - - ULONG ret = 0; - BOOL res = WinUsb_ControlTransfer(CapUSBHandle, pkt, buf, len, &ret, NULL); - if (!res) return -1; - return ret; -} - -int VendorOut(u8 req, u16 val, u16 len, u8* buf) -{ - WINUSB_SETUP_PACKET pkt; - pkt.RequestType = 0x40; // host to device - pkt.Request = req; - pkt.Value = val; - pkt.Index = 0; - pkt.Length = len; - - ULONG ret = 0; - BOOL res = WinUsb_ControlTransfer(CapUSBHandle, pkt, buf, len, &ret, NULL); - if (!res) return -1; - return ret; -} - -int BulkIn(u8* buf, u32 len) -{ - ULONG ret = 0; - BOOL res = WinUsb_ReadPipe(CapUSBHandle, 0x82, buf, len, &ret, NULL); - if (!res) return -1; - return ret; -} - - -u32 ConvertColor(u16 col) -{ - u32 b = col & 0x001F; - u32 g = (col & 0x07E0) >> 5; - u32 r = (col & 0xF800) >> 11; - - u32 ret = 0xFF000000; - ret |= ((r << 3) | (r >> 2)) << 16; - ret |= ((g << 2) | (g >> 4)) << 8; - ret |= (b << 3) | (b >> 2); - return ret; -} - -void CaptureFrame() -{ - u32 ret; - u8 derp; - u32 framelen = 256*384*2; - u16 frame[framelen/2]; - u32 framepos = 0; - u8 frameinfo[64]; - - ret = VendorOut(0x30, 0, 0, &derp); - if (ret < 0) return; - - int tries = 0; - while (framepos < framelen) - { - ret = BulkIn((u8*)&frame[framepos/2], framelen-framepos); - if (ret < 0) break; - if (ret == 0) - { - tries++; - if (tries >= 100) break; - continue; - } - framepos += ret; - } - - ret = VendorIn(0x30, 64, frameinfo); - if (ret < 0) return; - if ((frameinfo[0] & 0x03) != 0x03) return; - if (!frameinfo[52]) return; - - u16* in = &frame[0]; - u32* out = &WinBitmapData[256]; - - for (int y = 0; y < 384; y++) - { - u32* out = &WinBitmapData[((y/2)*768) + ((y&1)*128) + 256]; - - if (!(frameinfo[y>>3] & (1<<(y&7)))) - { - continue; - } - - for (int x = 0; x < 256/2; x++) - { - out[0] = ConvertColor(in[1]); - out[768*192] = ConvertColor(in[0]); - out++; - in += 2; - } - } -} - -void Update() -{ - // melonDS output - - int frontbuf = GPU::FrontBuffer; - - u32* topbuf = GPU::Framebuffer[frontbuf][0]; - if (topbuf) - { - for (int y = 0; y < 192; y++) - { - memcpy(&WinBitmapData[y*768], &topbuf[y*256], 256*4); - } - } - - u32* botbuf = GPU::Framebuffer[frontbuf][1]; - if (botbuf) - { - for (int y = 0; y < 192; y++) - { - memcpy(&WinBitmapData[(y+192)*768], &botbuf[y*256], 256*4); - } - } - - // DS capture - - CaptureFrame(); - - // compare - - for (int y = 0; y < 384; y++) - { - for (int x = 0; x < 256; x++) - { - u32 colA = WinBitmapData[(y*768) + x + 0]; - u32 colB = WinBitmapData[(y*768) + x + 256]; - - // best we get from the capture card is RGB565 - // so we'll ignore the lower bits - const u32 mask = 0x00F8FCF8; - colA &= mask; - colB &= mask; - - if (colA == colB) WinBitmapData[(y*768) + x + 512] = 0xFF000000;//0xFF00FF00; - else WinBitmapData[(y*768) + x + 512] = 0xFFFFFFFF;//0xFFFF0000; - } - } - - uiAreaQueueRedrawAll(Area); -} - -} diff --git a/src/libui_sdl/MelonCap.h b/src/libui_sdl/MelonCap.h deleted file mode 100644 index 33a391bd..00000000 --- a/src/libui_sdl/MelonCap.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef MELONCAP_H -#define MELONCAP_H - -#include "types.h" - -namespace MelonCap -{ - -void Init(); -void DeInit(); - -void Update(); - -} - -#endif // MELONCAP_H diff --git a/src/libui_sdl/OSD.cpp b/src/libui_sdl/OSD.cpp deleted file mode 100644 index a01e39b9..00000000 --- a/src/libui_sdl/OSD.cpp +++ /dev/null @@ -1,435 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include -#include -#include "../types.h" - -#include "libui/ui.h" -#include "../OpenGLSupport.h" - -#include "OSD.h" -#include "font.h" - -#include "PlatformConfig.h" - -extern int WindowWidth, WindowHeight; - -namespace OSD -{ - -const u32 kOSDMargin = 6; - -struct Item -{ - Uint32 Timestamp; - char Text[256]; - u32 Color; - - u32 Width, Height; - u32* Bitmap; - - bool DrawBitmapLoaded; - uiDrawBitmap* DrawBitmap; - - bool GLTextureLoaded; - GLuint GLTexture; - -}; - -std::deque ItemQueue; - -GLint uOSDPos, uOSDSize; -GLuint OSDVertexArray; -GLuint OSDVertexBuffer; - -volatile bool Rendering; - - -bool Init(bool opengl) -{ - if (opengl) - { - GLuint prog; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&prog); - uOSDPos = glGetUniformLocation(prog, "uOSDPos"); - uOSDSize = glGetUniformLocation(prog, "uOSDSize"); - - float vertices[6*2] = - { - 0, 0, - 1, 1, - 1, 0, - 0, 0, - 0, 1, - 1, 1 - }; - - glGenBuffers(1, &OSDVertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glGenVertexArrays(1, &OSDVertexArray); - glBindVertexArray(OSDVertexArray); - glEnableVertexAttribArray(0); // position - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0)); - } - - return true; -} - -void DeInit(bool opengl) -{ - for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) - { - Item& item = *it; - - if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap); - if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture); - if (item.Bitmap) delete[] item.Bitmap; - - it = ItemQueue.erase(it); - } -} - - -int FindBreakPoint(const char* text, int i) -{ - // i = character that went out of bounds - - for (int j = i; j >= 0; j--) - { - if (text[j] == ' ') - return j; - } - - return i; -} - -void LayoutText(const char* text, u32* width, u32* height, int* breaks) -{ - u32 w = 0; - u32 h = 14; - u32 totalw = 0; - u32 maxw = WindowWidth - (kOSDMargin*2); - int lastbreak = -1; - int numbrk = 0; - u16* ptr; - - memset(breaks, 0, sizeof(int)*64); - - for (int i = 0; text[i] != '\0'; ) - { - int glyphsize; - if (text[i] == ' ') - { - glyphsize = 6; - } - else - { - u32 ch = text[i]; - if (ch < 0x10 || ch > 0x7E) ch = 0x7F; - - ptr = &font[(ch-0x10) << 4]; - glyphsize = ptr[0]; - if (!glyphsize) glyphsize = 6; - else glyphsize += 2; // space around the character - } - - w += glyphsize; - if (w > maxw) - { - // wrap shit as needed - if (text[i] == ' ') - { - if (numbrk >= 64) break; - breaks[numbrk++] = i; - i++; - } - else - { - int brk = FindBreakPoint(text, i); - if (brk != lastbreak) i = brk; - - if (numbrk >= 64) break; - breaks[numbrk++] = i; - - lastbreak = brk; - } - - w = 0; - h += 14; - } - else - i++; - - if (w > totalw) totalw = w; - } - - *width = totalw; - *height = h; -} - -u32 RainbowColor(u32 inc) -{ - // inspired from Acmlmboard - - if (inc < 100) return 0xFFFF9B9B + (inc << 8); - else if (inc < 200) return 0xFFFFFF9B - ((inc-100) << 16); - else if (inc < 300) return 0xFF9BFF9B + (inc-200); - else if (inc < 400) return 0xFF9BFFFF - ((inc-300) << 8); - else if (inc < 500) return 0xFF9B9BFF + ((inc-400) << 16); - else return 0xFFFF9BFF - (inc-500); -} - -void RenderText(u32 color, const char* text, Item* item) -{ - u32 w, h; - int breaks[64]; - - bool rainbow = (color == 0); - u32 rainbowinc = ((text[0] * 17) + (SDL_GetTicks() * 13)) % 600; - - color |= 0xFF000000; - const u32 shadow = 0xE0000000; - - LayoutText(text, &w, &h, breaks); - - item->Width = w; - item->Height = h; - item->Bitmap = new u32[w*h]; - memset(item->Bitmap, 0, w*h*sizeof(u32)); - - u32 x = 0, y = 1; - u32 maxw = WindowWidth - (kOSDMargin*2); - int curline = 0; - u16* ptr; - - for (int i = 0; text[i] != '\0'; ) - { - int glyphsize; - if (text[i] == ' ') - { - x += 6; - } - else - { - u32 ch = text[i]; - if (ch < 0x10 || ch > 0x7E) ch = 0x7F; - - ptr = &font[(ch-0x10) << 4]; - int glyphsize = ptr[0]; - if (!glyphsize) x += 6; - else - { - x++; - - if (rainbow) - { - color = RainbowColor(rainbowinc); - rainbowinc = (rainbowinc + 30) % 600; - } - - // draw character - for (int cy = 0; cy < 12; cy++) - { - u16 val = ptr[4+cy]; - - for (int cx = 0; cx < glyphsize; cx++) - { - if (val & (1<Bitmap[((y+cy) * w) + x+cx] = color; - } - } - - x += glyphsize; - x++; - } - } - - i++; - if (breaks[curline] && i >= breaks[curline]) - { - i = breaks[curline++]; - if (text[i] == ' ') i++; - - x = 0; - y += 14; - } - } - - // shadow - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - u32 val; - - val = item->Bitmap[(y * w) + x]; - if ((val >> 24) == 0xFF) continue; - - if (x > 0) val = item->Bitmap[(y * w) + x-1]; - if (x < w-1) val |= item->Bitmap[(y * w) + x+1]; - if (y > 0) - { - if (x > 0) val |= item->Bitmap[((y-1) * w) + x-1]; - val |= item->Bitmap[((y-1) * w) + x]; - if (x < w-1) val |= item->Bitmap[((y-1) * w) + x+1]; - } - if (y < h-1) - { - if (x > 0) val |= item->Bitmap[((y+1) * w) + x-1]; - val |= item->Bitmap[((y+1) * w) + x]; - if (x < w-1) val |= item->Bitmap[((y+1) * w) + x+1]; - } - - if ((val >> 24) == 0xFF) - item->Bitmap[(y * w) + x] = shadow; - } - } -} - - -void AddMessage(u32 color, const char* text) -{ - if (!Config::ShowOSD) return; - - while (Rendering); - - Item item; - - item.Timestamp = SDL_GetTicks(); - strncpy(item.Text, text, 255); item.Text[255] = '\0'; - item.Color = color; - item.Bitmap = NULL; - - item.DrawBitmapLoaded = false; - item.GLTextureLoaded = false; - - ItemQueue.push_back(item); -} - -void WindowResized(bool opengl) -{ - /*for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) - { - Item& item = *it; - - if (item->DrawBitmapLoaded && item->DrawBitmap) uiDrawFreeBitmap(item->DrawBitmap); - //if (item->GLTextureLoaded && opengl) glDeleteTextures(1, &item->GLTexture); - - item->DrawBitmapLoaded = false; - item->GLTextureLoaded = false; - - if (item->Bitmap) delete[] item->Bitmap; - - it++; - }*/ -} - -void Update(bool opengl, uiAreaDrawParams* params) -{ - if (!Config::ShowOSD) - { - Rendering = true; - if (ItemQueue.size() > 0) DeInit(opengl); - Rendering = false; - return; - } - - Rendering = true; - - Uint32 tick_now = SDL_GetTicks(); - Uint32 tick_min = tick_now - 2500; - u32 y = kOSDMargin; - - if (opengl) - { - glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer); - glBindVertexArray(OSDVertexArray); - - glActiveTexture(GL_TEXTURE0); - - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - - for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) - { - Item& item = *it; - - if (item.Timestamp < tick_min) - { - if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap); - if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture); - if (item.Bitmap) delete[] item.Bitmap; - - it = ItemQueue.erase(it); - continue; - } - - if (!item.Bitmap) - { - RenderText(item.Color, item.Text, &item); - } - - if (opengl) - { - if (!item.GLTextureLoaded) - { - glGenTextures(1, &item.GLTexture); - glBindTexture(GL_TEXTURE_2D, item.GLTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, item.Width, item.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, item.Bitmap); - - item.GLTextureLoaded = true; - } - - glBindTexture(GL_TEXTURE_2D, item.GLTexture); - glUniform2i(uOSDPos, kOSDMargin, y); - glUniform2i(uOSDSize, item.Width, item.Height); - glDrawArrays(GL_TRIANGLES, 0, 2*3); - } - else - { - if (!item.DrawBitmapLoaded) - { - item.DrawBitmap = uiDrawNewBitmap(params->Context, item.Width, item.Height, 1); - uiDrawBitmapUpdate(item.DrawBitmap, item.Bitmap); - - item.DrawBitmapLoaded = true; - } - - uiRect rc_src = {0, 0, item.Width, item.Height}; - uiRect rc_dst = {kOSDMargin, y, item.Width, item.Height}; - - uiDrawBitmapDraw(params->Context, item.DrawBitmap, &rc_src, &rc_dst, 0); - } - - y += item.Height; - it++; - } - - Rendering = false; -} - -} diff --git a/src/libui_sdl/OSD.h b/src/libui_sdl/OSD.h deleted file mode 100644 index 12294ea7..00000000 --- a/src/libui_sdl/OSD.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef OSD_H -#define OSD_H - -namespace OSD -{ - -bool Init(bool opengl); -void DeInit(bool opengl); - -void AddMessage(u32 color, const char* text); - -void WindowResized(bool opengl); -void Update(bool opengl, uiAreaDrawParams* params); - -} - -#endif // OSD_H diff --git a/src/libui_sdl/Platform.cpp b/src/libui_sdl/Platform.cpp deleted file mode 100644 index 54fa568a..00000000 --- a/src/libui_sdl/Platform.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include -#include -#include "../Platform.h" -#include "PlatformConfig.h" -#include "LAN_Socket.h" -#include "LAN_PCap.h" -#include "libui/ui.h" -#include - -#ifdef __WIN32__ - #define NTDDI_VERSION 0x06000000 // GROSS FUCKING HACK - #include - //#include // FUCK THAT SHIT - extern "C" const GUID DECLSPEC_SELECTANY FOLDERID_RoamingAppData = {0x3eb685db, 0x65f9, 0x4cf6, {0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d}}; - #include - #include - #include - #define socket_t SOCKET - #define sockaddr_t SOCKADDR -#else - #include - #include - #include - #include - #include - #include - #define socket_t int - #define sockaddr_t struct sockaddr - #define closesocket close -#endif - -#ifndef INVALID_SOCKET -#define INVALID_SOCKET (socket_t)-1 -#endif - - -extern char* EmuDirectory; - -void Stop(bool internal); - - -namespace Platform -{ - - -typedef struct -{ - SDL_Thread* ID; - void (*Func)(); - -} ThreadData; - -int ThreadEntry(void* data) -{ - ThreadData* thread = (ThreadData*)data; - thread->Func(); - return 0; -} - - -socket_t MPSocket; -sockaddr_t MPSendAddr; -u8 PacketBuffer[2048]; - -#define NIFI_VER 1 - - -void StopEmu() -{ - Stop(true); -} - - -FILE* OpenFile(const char* path, const char* mode, bool mustexist) -{ - FILE* ret; - -#ifdef __WIN32__ - - int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); - if (len < 1) return NULL; - WCHAR* fatpath = new WCHAR[len]; - int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, fatpath, len); - if (res != len) { delete[] fatpath; return NULL; } // checkme? - - // this will be more than enough - WCHAR fatmode[4]; - fatmode[0] = mode[0]; - fatmode[1] = mode[1]; - fatmode[2] = mode[2]; - fatmode[3] = 0; - - if (mustexist) - { - ret = _wfopen(fatpath, L"rb"); - if (ret) ret = _wfreopen(fatpath, fatmode, ret); - } - else - ret = _wfopen(fatpath, fatmode); - - delete[] fatpath; - -#else - - if (mustexist) - { - ret = fopen(path, "rb"); - if (ret) ret = freopen(path, mode, ret); - } - else - ret = fopen(path, mode); - -#endif - - return ret; -} - -#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) - -FILE* OpenLocalFile(const char* path, const char* mode) -{ - std::string fullpath; - if (path[0] == '/') - { - // If it's an absolute path, just open that. - fullpath = std::string(path); - } - else - { - // Check user configuration directory - std::string confpath = std::string(g_get_user_config_dir()) + "/melonDS/"; - g_mkdir_with_parents(confpath.c_str(), 0755); - fullpath = confpath + path; - } - - return OpenFile(fullpath.c_str(), mode, mode[0] != 'w'); -} - -FILE* OpenDataFile(const char* path) -{ - const char* melondir = "melonDS"; - const char* const* sys_dirs = g_get_system_data_dirs(); - const char* user_dir = g_get_user_data_dir(); - - // First check the user's data directory - char* fullpath = g_build_path("/", user_dir, melondir, path, NULL); - if (access(fullpath, R_OK) == 0) - { - FILE* f = fopen(fullpath, "r"); - g_free(fullpath); - return f; - } - free(fullpath); - - // Then check the system data directories - for (size_t i = 0; sys_dirs[i] != NULL; i++) - { - const char* dir = sys_dirs[i]; - char* fullpath = g_build_path("/", dir, melondir, path, NULL); - - if (access(fullpath, R_OK) == 0) - { - FILE* f = fopen(fullpath, "r"); - g_free(fullpath); - return f; - } - free(fullpath); - } - - FILE* f = fopen(path, "rb"); - if (f) return f; - - return NULL; -} - -#else - -FILE* OpenLocalFile(const char* path, const char* mode) -{ - bool relpath = false; - int pathlen = strlen(path); - -#ifdef __WIN32__ - if (pathlen > 3) - { - if (path[1] == ':' && path[2] == '\\') - return OpenFile(path, mode); - } -#else - if (pathlen > 1) - { - if (path[0] == '/') - return OpenFile(path, mode); - } -#endif - - if (pathlen >= 3) - { - if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path[2] == '\\')) - relpath = true; - } - - int emudirlen = strlen(EmuDirectory); - char* emudirpath; - if (emudirlen) - { - int len = emudirlen + 1 + pathlen + 1; - emudirpath = new char[len]; - strncpy(&emudirpath[0], EmuDirectory, emudirlen); - emudirpath[emudirlen] = '/'; - strncpy(&emudirpath[emudirlen+1], path, pathlen); - emudirpath[emudirlen+1+pathlen] = '\0'; - } - else - { - emudirpath = new char[pathlen+1]; - strncpy(&emudirpath[0], path, pathlen); - emudirpath[pathlen] = '\0'; - } - - // Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonDS on Linux - - FILE* f; - - // First check current working directory - f = OpenFile(path, mode, true); - if (f) { delete[] emudirpath; return f; } - - // then emu directory - f = OpenFile(emudirpath, mode, true); - if (f) { delete[] emudirpath; return f; } - -#ifdef __WIN32__ - - // a path relative to AppData wouldn't make much sense - if (!relpath) - { - // Now check AppData - PWSTR appDataPath = NULL; - SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath); - if (!appDataPath) - { - delete[] emudirpath; - return NULL; - } - - // this will be more than enough - WCHAR fatperm[4]; - fatperm[0] = mode[0]; - fatperm[1] = mode[1]; - fatperm[2] = mode[2]; - fatperm[3] = 0; - - int fnlen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); - if (fnlen < 1) { delete[] emudirpath; return NULL; } - WCHAR* wfileName = new WCHAR[fnlen]; - int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, wfileName, fnlen); - if (res != fnlen) { delete[] wfileName; delete[] emudirpath; return NULL; } // checkme? - - const WCHAR* appdir = L"\\melonDS\\"; - - int pos = wcslen(appDataPath); - void* ptr = CoTaskMemRealloc(appDataPath, (pos+wcslen(appdir)+fnlen+1)*sizeof(WCHAR)); - if (!ptr) { delete[] wfileName; delete[] emudirpath; return NULL; } // oh well - appDataPath = (PWSTR)ptr; - - wcscpy(&appDataPath[pos], appdir); pos += wcslen(appdir); - wcscpy(&appDataPath[pos], wfileName); - - f = _wfopen(appDataPath, L"rb"); - if (f) f = _wfreopen(appDataPath, fatperm, f); - CoTaskMemFree(appDataPath); - delete[] wfileName; - if (f) { delete[] emudirpath; return f; } - } - -#else - - if (!relpath) - { - // Now check XDG_CONFIG_HOME - // TODO: check for memory leak there - std::string fullpath = std::string(g_get_user_config_dir()) + "/melonDS/" + path; - f = OpenFile(fullpath.c_str(), mode, true); - if (f) { delete[] emudirpath; return f; } - } - -#endif - - if (mode[0] != 'r') - { - f = OpenFile(emudirpath, mode); - if (f) { delete[] emudirpath; return f; } - } - - delete[] emudirpath; - return NULL; -} - -FILE* OpenDataFile(const char* path) -{ - return OpenLocalFile(path, "rb"); -} - -#endif - - -void* Thread_Create(void (*func)()) -{ - ThreadData* data = new ThreadData; - data->Func = func; - data->ID = SDL_CreateThread(ThreadEntry, "melonDS core thread", data); - return data; -} - -void Thread_Free(void* thread) -{ - delete (ThreadData*)thread; -} - -void Thread_Wait(void* thread) -{ - SDL_WaitThread((SDL_Thread*)((ThreadData*)thread)->ID, NULL); -} - - -void* Semaphore_Create() -{ - return SDL_CreateSemaphore(0); -} - -void Semaphore_Free(void* sema) -{ - SDL_DestroySemaphore((SDL_sem*)sema); -} - -void Semaphore_Reset(void* sema) -{ - while (SDL_SemTryWait((SDL_sem*)sema) == 0); -} - -void Semaphore_Wait(void* sema) -{ - SDL_SemWait((SDL_sem*)sema); -} - -void Semaphore_Post(void* sema) -{ - SDL_SemPost((SDL_sem*)sema); -} - - -void* GL_GetProcAddress(const char* proc) -{ - return uiGLGetProcAddress(proc); -} - - -bool MP_Init() -{ - int opt_true = 1; - int res; - -#ifdef __WIN32__ - WSADATA wsadata; - if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) - { - return false; - } -#endif // __WIN32__ - - MPSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (MPSocket < 0) - { - return false; - } - - res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); - if (res < 0) - { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; - return false; - } - - sockaddr_t saddr; - saddr.sa_family = AF_INET; - *(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK); - *(u16*)&saddr.sa_data[0] = htons(7064); - res = bind(MPSocket, &saddr, sizeof(sockaddr_t)); - if (res < 0) - { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; - return false; - } - - res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); - if (res < 0) - { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; - return false; - } - - MPSendAddr.sa_family = AF_INET; - *(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST); - *(u16*)&MPSendAddr.sa_data[0] = htons(7064); - - return true; -} - -void MP_DeInit() -{ - if (MPSocket >= 0) - closesocket(MPSocket); - -#ifdef __WIN32__ - WSACleanup(); -#endif // __WIN32__ -} - -int MP_SendPacket(u8* data, int len) -{ - if (MPSocket < 0) - return 0; - - if (len > 2048-8) - { - printf("MP_SendPacket: error: packet too long (%d)\n", len); - return 0; - } - - *(u32*)&PacketBuffer[0] = htonl(0x4946494E); // NIFI - PacketBuffer[4] = NIFI_VER; - PacketBuffer[5] = 0; - *(u16*)&PacketBuffer[6] = htons(len); - memcpy(&PacketBuffer[8], data, len); - - int slen = sendto(MPSocket, (const char*)PacketBuffer, len+8, 0, &MPSendAddr, sizeof(sockaddr_t)); - if (slen < 8) return 0; - return slen - 8; -} - -int MP_RecvPacket(u8* data, bool block) -{ - if (MPSocket < 0) - return 0; - - fd_set fd; - struct timeval tv; - - FD_ZERO(&fd); - FD_SET(MPSocket, &fd); - tv.tv_sec = 0; - tv.tv_usec = block ? 5000 : 0; - - if (!select(MPSocket+1, &fd, 0, 0, &tv)) - { - return 0; - } - - sockaddr_t fromAddr; - socklen_t fromLen = sizeof(sockaddr_t); - int rlen = recvfrom(MPSocket, (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen); - if (rlen < 8+24) - { - return 0; - } - rlen -= 8; - - if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E) - { - return 0; - } - - if (PacketBuffer[4] != NIFI_VER) - { - return 0; - } - - if (ntohs(*(u16*)&PacketBuffer[6]) != rlen) - { - return 0; - } - - memcpy(data, &PacketBuffer[8], rlen); - return rlen; -} - - - -bool LAN_Init() -{ - if (Config::DirectLAN) - { - if (!LAN_PCap::Init(true)) - return false; - } - else - { - if (!LAN_Socket::Init()) - return false; - } - - return true; -} - -void LAN_DeInit() -{ - // checkme. blarg - //if (Config::DirectLAN) - // LAN_PCap::DeInit(); - //else - // LAN_Socket::DeInit(); - LAN_PCap::DeInit(); - LAN_Socket::DeInit(); -} - -int LAN_SendPacket(u8* data, int len) -{ - if (Config::DirectLAN) - return LAN_PCap::SendPacket(data, len); - else - return LAN_Socket::SendPacket(data, len); -} - -int LAN_RecvPacket(u8* data) -{ - if (Config::DirectLAN) - return LAN_PCap::RecvPacket(data); - else - return LAN_Socket::RecvPacket(data); -} - - -} diff --git a/src/libui_sdl/PlatformConfig.cpp b/src/libui_sdl/PlatformConfig.cpp deleted file mode 100644 index f78b1957..00000000 --- a/src/libui_sdl/PlatformConfig.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include -#include "PlatformConfig.h" - -namespace Config -{ - -int KeyMapping[12]; -int JoyMapping[12]; - -int HKKeyMapping[HK_MAX]; -int HKJoyMapping[HK_MAX]; - -int JoystickID; - -int WindowWidth; -int WindowHeight; -int WindowMaximized; - -int ScreenRotation; -int ScreenGap; -int ScreenLayout; -int ScreenSizing; -int ScreenFilter; - -int ScreenUseGL; -int ScreenVSync; -int ScreenRatio; - -int LimitFPS; -int AudioSync; -int ShowOSD; - -int DirectBoot; - -int SocketBindAnyAddr; -char LANDevice[128]; -int DirectLAN; - -int SavestateRelocSRAM; - -int AudioVolume; -int MicInputType; -char MicWavPath[512]; - -char LastROMFolder[512]; - - -ConfigEntry PlatformConfigFile[] = -{ - {"Key_A", 0, &KeyMapping[0], 32, NULL, 0}, - {"Key_B", 0, &KeyMapping[1], 31, NULL, 0}, - {"Key_Select", 0, &KeyMapping[2], 57, NULL, 0}, - {"Key_Start", 0, &KeyMapping[3], 28, NULL, 0}, - {"Key_Right", 0, &KeyMapping[4], 333, NULL, 0}, - {"Key_Left", 0, &KeyMapping[5], 331, NULL, 0}, - {"Key_Up", 0, &KeyMapping[6], 328, NULL, 0}, - {"Key_Down", 0, &KeyMapping[7], 336, NULL, 0}, - {"Key_R", 0, &KeyMapping[8], 54, NULL, 0}, - {"Key_L", 0, &KeyMapping[9], 86, NULL, 0}, - {"Key_X", 0, &KeyMapping[10], 17, NULL, 0}, - {"Key_Y", 0, &KeyMapping[11], 30, NULL, 0}, - - {"Joy_A", 0, &JoyMapping[0], -1, NULL, 0}, - {"Joy_B", 0, &JoyMapping[1], -1, NULL, 0}, - {"Joy_Select", 0, &JoyMapping[2], -1, NULL, 0}, - {"Joy_Start", 0, &JoyMapping[3], -1, NULL, 0}, - {"Joy_Right", 0, &JoyMapping[4], -1, NULL, 0}, - {"Joy_Left", 0, &JoyMapping[5], -1, NULL, 0}, - {"Joy_Up", 0, &JoyMapping[6], -1, NULL, 0}, - {"Joy_Down", 0, &JoyMapping[7], -1, NULL, 0}, - {"Joy_R", 0, &JoyMapping[8], -1, NULL, 0}, - {"Joy_L", 0, &JoyMapping[9], -1, NULL, 0}, - {"Joy_X", 0, &JoyMapping[10], -1, NULL, 0}, - {"Joy_Y", 0, &JoyMapping[11], -1, NULL, 0}, - - {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0}, - {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0}, - {"HKKey_Pause", 0, &HKKeyMapping[HK_Pause], -1, NULL, 0}, - {"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0}, - {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0}, - {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, - {"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], 0x4B, NULL, 0}, - {"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], 0x4D, NULL, 0}, - - {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0}, - {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0}, - {"HKJoy_Pause", 0, &HKJoyMapping[HK_Pause], -1, NULL, 0}, - {"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0}, - {"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -1, NULL, 0}, - {"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FastForwardToggle], -1, NULL, 0}, - {"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, NULL, 0}, - {"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, NULL, 0}, - - {"JoystickID", 0, &JoystickID, 0, NULL, 0}, - - {"WindowWidth", 0, &WindowWidth, 256, NULL, 0}, - {"WindowHeight", 0, &WindowHeight, 384, NULL, 0}, - {"WindowMax", 0, &WindowMaximized, 0, NULL, 0}, - - {"ScreenRotation", 0, &ScreenRotation, 0, NULL, 0}, - {"ScreenGap", 0, &ScreenGap, 0, NULL, 0}, - {"ScreenLayout", 0, &ScreenLayout, 0, NULL, 0}, - {"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0}, - {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0}, - - {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, - {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, - {"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0}, - - {"LimitFPS", 0, &LimitFPS, 0, NULL, 0}, - {"AudioSync", 0, &AudioSync, 1, NULL, 0}, - {"ShowOSD", 0, &ShowOSD, 1, NULL, 0}, - - {"DirectBoot", 0, &DirectBoot, 1, NULL, 0}, - - {"SockBindAnyAddr", 0, &SocketBindAnyAddr, 0, NULL, 0}, - {"LANDevice", 1, LANDevice, 0, "", 127}, - {"DirectLAN", 0, &DirectLAN, 0, NULL, 0}, - - {"SavStaRelocSRAM", 0, &SavestateRelocSRAM, 0, NULL, 0}, - - {"AudioVolume", 0, &AudioVolume, 256, NULL, 0}, - {"MicInputType", 0, &MicInputType, 1, NULL, 0}, - {"MicWavPath", 1, MicWavPath, 0, "", 511}, - - {"LastROMFolder", 1, LastROMFolder, 0, "", 511}, - - {"", -1, NULL, 0, NULL, 0} -}; - -} diff --git a/src/libui_sdl/PlatformConfig.h b/src/libui_sdl/PlatformConfig.h deleted file mode 100644 index 9e02862f..00000000 --- a/src/libui_sdl/PlatformConfig.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef PLATFORMCONFIG_H -#define PLATFORMCONFIG_H - -#include "../Config.h" - -enum -{ - HK_Lid = 0, - HK_Mic, - HK_Pause, - HK_Reset, - HK_FastForward, - HK_FastForwardToggle, - HK_SolarSensorDecrease, - HK_SolarSensorIncrease, - HK_MAX -}; - -namespace Config -{ - -extern int KeyMapping[12]; -extern int JoyMapping[12]; - -extern int HKKeyMapping[HK_MAX]; -extern int HKJoyMapping[HK_MAX]; - -extern int JoystickID; - -extern int WindowWidth; -extern int WindowHeight; -extern int WindowMaximized; - -extern int ScreenRotation; -extern int ScreenGap; -extern int ScreenLayout; -extern int ScreenSizing; -extern int ScreenFilter; - -extern int ScreenUseGL; -extern int ScreenVSync; -extern int ScreenRatio; - -extern int LimitFPS; -extern int AudioSync; -extern int ShowOSD; - -extern int DirectBoot; - -extern int SocketBindAnyAddr; -extern char LANDevice[128]; -extern int DirectLAN; - -extern int SavestateRelocSRAM; - -extern int AudioVolume; -extern int MicInputType; -extern char MicWavPath[512]; - -extern char LastROMFolder[512]; - -} - -#endif // PLATFORMCONFIG_H diff --git a/src/libui_sdl/font.h b/src/libui_sdl/font.h deleted file mode 100644 index f2e4f878..00000000 --- a/src/libui_sdl/font.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef FONT_H -#define FONT_H -unsigned short font[] = { - 12, 0, 0, 0,0x0C03, 0x0E07, 0x070E, 0x039C, 0x01F8, 0x00F0, 0x00F0, 0x01F8, 0x039C, 0x070E, 0x0E07, 0x0C03, - 12, 0, 0, 0,0x01C0, 0x00E0, 0x0060, 0x0860, 0x0C60, 0x0FE0, 0x07F0, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0000, 0x0000, - 9, 0, 0, 0,0x01EF, 0x01EF, 0x018C, 0x01CE, 0x00E7, 0x0063, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 10, 0, 0, 0,0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x0000, 0x0000, - 8, 0, 0, 0,0x0018, 0x00FE, 0x00FF, 0x001B, 0x007F, 0x00FE, 0x00D8, 0x00FF, 0x007F, 0x0018, 0x0000, 0x0000, - 10, 0, 0, 0,0x0306, 0x038F, 0x01CF, 0x00E6, 0x0070, 0x0038, 0x019C, 0x03CE, 0x03C7, 0x0183, 0x0000, 0x0000, - 10, 0, 0, 0,0x007C, 0x00FE, 0x00C6, 0x00EE, 0x007C, 0x037E, 0x03E7, 0x01F3, 0x03BF, 0x031E, 0x0000, 0x0000, - 4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 4, 0, 0, 0,0x000C, 0x000E, 0x0007, 0x0003, 0x0003, 0x0003, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000, - 4, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x000C, 0x000C, 0x000C, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, - 10, 0, 0, 0,0x0030, 0x0333, 0x03B7, 0x01FE, 0x00FC, 0x00FC, 0x01FE, 0x03B7, 0x0333, 0x0030, 0x0000, 0x0000, - 10, 0, 0, 0,0x0030, 0x0030, 0x0030, 0x0030, 0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, - 4, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003, - 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 3, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0007, 0x0000, 0x0000, - 10, 0, 0, 0,0x0300, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, - 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, - 4, 0, 0, 0,0x0006, 0x0007, 0x0007, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x000F, 0x000F, 0x0000, 0x0000, - 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C0, 0x00FE, 0x007F, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0000, 0x0000, - 8, 0, 0, 0,0x007F, 0x00FF, 0x00C0, 0x00C0, 0x007C, 0x00FC, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000, - 8, 0, 0, 0,0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x00FF, 0x00FE, 0x0060, 0x0060, 0x0000, 0x0000, - 8, 0, 0, 0,0x00FF, 0x00FF, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000, - 8, 0, 0, 0,0x007E, 0x007F, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, - 8, 0, 0, 0,0x00FF, 0x00FF, 0x00C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000C, 0x000C, 0x000C, 0x0000, 0x0000, - 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, - 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x00FE, 0x00C0, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000, - 3, 0, 0, 0,0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000, - 4, 0, 0, 0,0x0000, 0x0000, 0x000E, 0x000E, 0x0000, 0x0000, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, - 6, 0, 0, 0,0x0030, 0x0038, 0x001C, 0x000E, 0x0007, 0x0007, 0x000E, 0x001C, 0x0038, 0x0030, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x0000, - 6, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, - 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00F0, 0x0078, 0x0018, 0x0000, 0x0018, 0x0018, 0x0000, 0x0000, - 10, 0, 0, 0,0x00FC, 0x01FE, 0x0387, 0x0333, 0x037B, 0x03FB, 0x01F3, 0x0007, 0x03FE, 0x03FC, 0x0000, 0x0000, - 9, 0, 0, 0,0x00FE, 0x01FF, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000, - 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0000, 0x0000, - 8, 0, 0, 0,0x00FE, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00FF, 0x00FE, 0x0000, 0x0000, - 9, 0, 0, 0,0x007F, 0x00FF, 0x01C3, 0x0183, 0x0183, 0x0183, 0x0183, 0x01C3, 0x00FF, 0x007F, 0x0000, 0x0000, - 9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x01FF, 0x01FF, 0x0000, 0x0000, - 9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, - 9, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01F3, 0x01F3, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000, - 9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000, - 6, 0, 0, 0,0x003F, 0x003F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x003F, 0x003F, 0x0000, 0x0000, - 9, 0, 0, 0,0x01F0, 0x01F0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, - 9, 0, 0, 0,0x0183, 0x01C3, 0x00E3, 0x0073, 0x003F, 0x003F, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000, - 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007F, 0x0000, 0x0000, - 10, 0, 0, 0,0x0303, 0x0387, 0x03CF, 0x03FF, 0x037B, 0x0333, 0x0303, 0x0303, 0x0303, 0x0303, 0x0000, 0x0000, - 10, 0, 0, 0,0x0303, 0x0307, 0x030F, 0x031F, 0x033B, 0x0373, 0x03E3, 0x03C3, 0x0383, 0x0303, 0x0000, 0x0000, - 10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x03FF, 0x01FE, 0x0000, 0x0000, - 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, - 10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0333, 0x0373, 0x03E3, 0x01C3, 0x03FF, 0x037E, 0x0000, 0x0000, - 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000, - 10, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01FF, 0x03FE, 0x0300, 0x0300, 0x03FE, 0x01FE, 0x0000, 0x0000, - 10, 0, 0, 0,0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, - 9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000, - 10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000, - 10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000, - 10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0078, 0x00FC, 0x01CE, 0x0387, 0x0303, 0x0000, 0x0000, - 10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, - 10, 0, 0, 0,0x03FF, 0x03FF, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x03FF, 0x03FF, 0x0000, 0x0000, - 4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000F, 0x0000, 0x0000, - 10, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0300, 0x0000, 0x0000, - 4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000F, 0x000F, 0x0000, 0x0000, - 8, 0, 0, 0,0x0018, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF, - 4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007E, 0x0060, 0x007E, 0x007F, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000, - 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x003F, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007E, 0x0000, 0x0000, - 7, 0, 0, 0,0x0060, 0x0060, 0x0060, 0x007E, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007F, 0x0063, 0x007F, 0x003F, 0x0003, 0x003F, 0x003E, 0x0000, 0x0000, - 6, 0, 0, 0,0x003C, 0x003E, 0x0006, 0x0006, 0x001F, 0x001F, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x007E, 0x003E, - 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000, - 2, 0, 0, 0,0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, - 7, 0, 0, 0,0x0060, 0x0060, 0x0000, 0x0000, 0x0060, 0x0060, 0x0060, 0x0060, 0x0060, 0x0063, 0x007F, 0x003E, - 8, 0, 0, 0,0x0003, 0x0003, 0x00E3, 0x0073, 0x003B, 0x001F, 0x001F, 0x003B, 0x0073, 0x00E3, 0x0000, 0x0000, - 4, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000E, 0x0000, 0x0000, - 10, 0, 0, 0,0x0000, 0x0000, 0x01FF, 0x03FF, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000, - 8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x007F, 0x003F, 0x0003, 0x0003, 0x0003, 0x0003, - 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x0060, 0x0060, - 7, 0, 0, 0,0x0000, 0x0000, 0x003B, 0x007F, 0x0067, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, - 8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x007F, 0x00FE, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000, - 6, 0, 0, 0,0x0006, 0x0006, 0x003F, 0x003F, 0x0006, 0x0006, 0x0006, 0x0006, 0x003E, 0x003C, 0x0000, 0x0000, - 7, 0, 0, 0,0x0000, 0x0000, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000, - 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000, - 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000, - 8, 0, 0, 0,0x0000, 0x0000, 0x00C3, 0x00E7, 0x007E, 0x003C, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000, - 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0307, 0x038E, 0x01DC, 0x00F8, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006, - 8, 0, 0, 0,0x0000, 0x0000, 0x00FF, 0x00FF, 0x0070, 0x0038, 0x001C, 0x000E, 0x00FF, 0x00FF, 0x0000, 0x0000, - 6, 0, 0, 0,0x0038, 0x003C, 0x000C, 0x000C, 0x000F, 0x000F, 0x000C, 0x000C, 0x003C, 0x0038, 0x0000, 0x0000, - 2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, - 6, 0, 0, 0,0x0007, 0x000F, 0x000C, 0x000C, 0x003C, 0x003C, 0x000C, 0x000C, 0x000F, 0x0007, 0x0000, 0x0000, - 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x031C, 0x03BE, 0x01F7, 0x00E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 11, 0, 0, 0,0x0555, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0555, 0x0000, -}; -#endif diff --git a/src/libui_sdl/libui/.travis.yml b/src/libui_sdl/libui/.travis.yml deleted file mode 100644 index d271bd8e..00000000 --- a/src/libui_sdl/libui/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -os: - - linux - - osx - -# This makes us use Ubuntu 14 instead of 12 -dist: trusty - -# Notes: -# - Travis uses cmake 3.0.2 on OS X; we need 3.1 or newer (thanks tbodt) - -language: c -script: - - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update; fi - - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install libgtk-3-dev -y || sudo apt-cache search libgtk3; fi - - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update; fi - - mkdir build - - cd build - - cmake --version - - cmake .. -G "Unix Makefiles" - - make tester examples - - rm -rf * - - cmake .. -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF - - make tester examples diff --git a/src/libui_sdl/libui/ANNOUNCE.md b/src/libui_sdl/libui/ANNOUNCE.md deleted file mode 100644 index 4db42eb4..00000000 --- a/src/libui_sdl/libui/ANNOUNCE.md +++ /dev/null @@ -1,22 +0,0 @@ -# Old Announcements - -* **29 May 2016** - * **Alpha 3 is here!** Get it [here](https://github.com/andlabs/libui/releases/tag/alpha3). - * The next packaged release will introduce: - * uiGrid, another way to lay out controls, a la GtkGrid - * uiOpenGLArea, a way to render OpenGL content in a libui uiArea - * uiTable, a data grid control that may or may not have tree facilities (if it does, it will be called uiTree instead) - * a complete, possibly rewritten, drawing and text rendering infrastructure - -* **24 May 2016** - * You can now help choose [a potential new build system for libui](https://github.com/andlabs/libui/issues/62). - * Tomorrow I will decide if OS X 10.7 will also be dropped alongside GTK+ 3.4-3.8 this Saturday. Stay tuned. - -* **22 May 2016** - * Two more open questions I'd like your feedback on are available [here](https://github.com/andlabs/libui/issues/48) and [here](https://github.com/andlabs/libui/issues/25). - * Sometime in the next 48 hours (before 23:59 EDT on 24 May 2016) I will split `uiCombobox` into two separate controls, `uiCombobox` and `uiEditableCombobox`, each with slightly different events and "selected item" mechanics. Prepare your existing code. - -* **21 May 2016** - * I will now post announcements and updates here. - * Now that Ubuntu 16.04 LTS is here, no earlier than next Saturday, 28 May 2016 at noon EDT, **I will bump the minimum GTK+ version from 3.4 to 3.10**. This will add a lot of new features that I can now add to libui, such as search-oriented uiEntries, lists of arbitrary control layouts, and more. If you are still running a Linux distribution that doesn't come with 3.10, you will either need to upgrade or use jhbuild to set up a newer version of GTK+ in a private environment. - * You can decide if I should also drop OS X 10.7 [here](https://github.com/andlabs/libui/issues/46). diff --git a/src/libui_sdl/libui/CMakeLists.txt b/src/libui_sdl/libui/CMakeLists.txt deleted file mode 100644 index eb1696d9..00000000 --- a/src/libui_sdl/libui/CMakeLists.txt +++ /dev/null @@ -1,219 +0,0 @@ -# 3 june 2016 -# see https://cmake.org/gitweb?p=cmake.git;a=commit;h=95cdf132489c79e88a10fdf7a7566fa002c7680b (thanks ngladitz in irc.freenode.net/#cmake) -cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) - -# TODOs -# - silence entering/leaving messages? -# - uname -s for more refined OS control -# - Haiku for haiku -# - debian DESTDIR? https://github.com/andlabs/libui/pull/10 -# - libui-combined* needs to be deleted so that custom command can run every time -# - add notelemetry.obj to *ALL TARGETS* on VS2015 and up - https://www.infoq.com/news/2016/06/visual-cpp-telemetry -# - switch to 3.1.0 features - -# the docs say we need to set this up prior to project() -set(CMAKE_OSX_DEPLOYMENT_TARGET "10.8") - -# we want to disable incremental linking -# see also: -# - https://github.com/bulletphysics/bullet3/blob/master/CMakeLists.txt#L43 -# - https://cmake.org/pipermail/cmake/2010-February/035174.html -# this must also go before project() -set(MSVC_INCREMENTAL_DEFAULT ON) - -# default to debug builds -# do this before project() just to be safe -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE DEBUG CACHE STRING "" FORCE) -endif() - -project(libui) -option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON) - -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out") -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out") -set(CMAKE_PDB_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/out") - -if(APPLE) - set(_OSNAME darwin) - set(_HASVERSION TRUE) - set(_VERSION "A") - - # always use our rpath - set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - # the / is required by some older versions of OS X - set(CMAKE_INSTALL_RPATH "@executable_path/") - set(CMAKE_MACOSX_RPATH TRUE) -elseif(WIN32) - set(_OSNAME windows) - - # and don't include the default libraries with ANY of the builds - # note the CACHE FORCE stuff is required here - set(CMAKE_C_STANDARD_LIBRARIES CACHE STRING "" FORCE) - set(CMAKE_CXX_STANDARD_LIBRARIES CACHE STRING "" FORCE) -else() - set(_OSNAME unix) - set(_HASVERSION TRUE) - set(_VERSION "0") - - # always use our rpath - set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - set(CMAKE_INSTALL_RPATH "\$ORIGIN") -endif() - -# common flags -if(MSVC) - # TODO subsystem version - - # TODO /Wall does too much - # TODO -Wno-switch equivalent - # TODO /sdl turns C4996 into an ERROR - # don't use /analyze; that requires us to write annotations everywhere - # TODO undecided flags from qo? - # /RTCc is not supplied because it's discouraged as of VS2015; see https://www.reddit.com/r/cpp/comments/46mhne/rtcc_rejects_conformant_code_with_visual_c_2015/d06auq5 - # /EHsc is to shut the compiler up in some cases - # TODO make /EHsc C++-only - set(_COMMON_CFLAGS - /W4 /wd4100 - /bigobj /nologo - /RTC1 /RTCs /RTCu - /EHsc - ) - - # note the /MANIFEST:NO (which must be / and uppercase); thanks FraGag (https://github.com/andlabs/libui/issues/93#issuecomment-223183436) - # TODO warnings on undefined symbols - set(_COMMON_LDFLAGS - /LARGEADDRESSAWARE - /NOLOGO - /INCREMENTAL:NO - /MANIFEST:NO - ) - - # TODO autogenerate a .def file? - - # more incremental linking fixes - # TODO actually get rid of incremental linking here -else() - set(_COMMON_CFLAGS - -Wall -Wextra -pedantic - -Wno-unused-parameter - -Wno-switch - -fvisibility=hidden - ) - # don't use C_VERSION or CXX_VERSION because they use GNU standards - # TODO we can actually do this; set both C_EXTENSIONS and CXX_EXTENSIONS to OFF - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --std=c99") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11") - - set(_COMMON_LDFLAGS - -fvisibility=hidden - ) - - # don't require shipping the MinGW-w64 DLLs - if(WIN32) - list(APPEND _COMMON_LDFLAGS - -static - -static-libgcc - -static-libstdc++ - ) - endif() -endif() - -# problem: -# - target_link_libraries() only supports - for flags -# - but cmake only doesn't generate the manifest if the flag has a / -macro(_target_link_options_private _target) - foreach(_opt IN LISTS ${ARGN}) - set_property(TARGET ${_target} APPEND_STRING PROPERTY - LINK_FLAGS " ${_opt}") - endforeach() -endmacro() - -add_subdirectory("common") -add_subdirectory("${_OSNAME}") -add_library(${_LIBUINAME} ${_LIBUI_SOURCES}) -target_include_directories(${_LIBUINAME} - PUBLIC . - PRIVATE ${_LIBUI_INCLUEDIRS}) -target_compile_definitions(${_LIBUINAME} - PRIVATE ${_LIBUI_DEFS}) -# cmake produces this for us by default but only for shared libraries -target_compile_definitions(${_LIBUINAME} - PRIVATE libui_EXPORTS) -target_compile_options(${_LIBUINAME} - PUBLIC ${_COMMON_CFLAGS} - PRIVATE ${_LIBUI_CFLAGS}) -# TODO link directories? -if(BUILD_SHARED_LIBS) - target_link_libraries(${_LIBUINAME} - PRIVATE ${_LIBUI_LIBS}) -endif() -# TODO INTERFACE libs don't inherit to grandhcildren? -# on Windows the linker for static libraries is different; don't give it the flags -if(BUILD_SHARED_LIBS) - _target_link_options_private(${_LIBUINAME} - _COMMON_LDFLAGS - _LIBUI_LDFLAGS) -endif() -if(NOT BUILD_SHARED_LIBS) - _handle_static() - # TODO figure out a way to tell libui that it's static - target_compile_definitions(${_LIBUINAME} - PUBLIC _UI_STATIC) -endif() -if(NOT MSVC) - # on non-MSVC compilers cmake adds an extra lib- - # note that we apply this to libui, not to any intermediates - set_target_properties(libui PROPERTIES - OUTPUT_NAME ui) - - # flags for warning on undefined symbols - # TODO figure out why FreeBSD follows linked libraries here - # TODO figure out MSVC equivalents - if(BUILD_SHARED_LIBS) - if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)) - # on OS X we don't need to do this; Apple's linker warns about undefined symbols in -shared builds! - if(NOT APPLE) - target_link_libraries(libui - PRIVATE -Wl,--no-undefined -Wl,--no-allow-shlib-undefined - ) - endif() - endif() - endif() -endif() -if(BUILD_SHARED_LIBS) - if(_HASVERSION) - set_target_properties(${_LIBUINAME} PROPERTIES - SOVERSION "${_VERSION}") - endif() -endif() - -macro(_add_exec _name) - add_executable(${_name} - WIN32 EXCLUDE_FROM_ALL - ${ARGN}) - target_link_libraries(${_name} libui ${_LIBUI_STATIC_RES}) - _target_link_options_private(${_name} - _COMMON_LDFLAGS) - # make shared-linked executables PIC too - if(BUILD_SHARED_LIBS) - set_property(TARGET ${_name} PROPERTY - POSITION_INDEPENDENT_CODE True) - endif() - # TODO see above about INTERFACE - if(NOT BUILD_SHARED_LIBS) - target_link_libraries(${_name} - ${_LIBUI_LIBS}) - endif() - - # TODOfor some reason these don't propagate - if(NOT WIN32) - target_include_directories(${_name} - PUBLIC .) - target_compile_options(${_name} - PUBLIC ${_COMMON_CFLAGS}) - endif() -endmacro() -add_subdirectory("test") -add_subdirectory("examples") diff --git a/src/libui_sdl/libui/Changelog.md b/src/libui_sdl/libui/Changelog.md deleted file mode 100644 index 29fac274..00000000 --- a/src/libui_sdl/libui/Changelog.md +++ /dev/null @@ -1,33 +0,0 @@ -# Old Updates - -* **29 May 2016** - * Thanks to @pcwalton, we can now statically link libui! Simply do `make STATIC=1` instead of just `make`. - * On Windows you must link both `libui.lib` and `libui.res` AND provide a Common Controls 6 manifest for output static binaries to work properly. - -* **28 May 2016** - * As promised, **the minimum system requirements are now OS X 10.8 and GTK+ 3.10 for OS X and Unix, respectively**. - -* **26 May 2016** - * Two OS X-specific functions have been added: `uiDarwinMarginAmount()` and `uiDarwinPaddingAmount()`. These return the amount of margins and padding, respectively, to give to a control, and are intended for container implementations. These are suitable for the constant of a NSLayoutConstraint. They both take a pointer parameter that is reserved for future use and should be `NULL`. - -* **25 May 2016** - * uiDrawTextLayout attributes are now specified in units of *graphemes* on all platforms. This means characters as seen from a user's perspective, not Unicode codepoints or UTF-8 bytes. So a long string of combining marker codepoints after one codepoint would still count as one grapheme. - -* **24 May 2016** - * As promised, `uiCombobox` is now split into `uiCombobox` for non-editable comboboxes and `uiEditableCombobox` for editable comboboxes. Mind the function changes as well :) - * There is a new function `uiMainStep()`, which runs one iteration of the main loop. It takes a single boolean argument, indicating whether to wait for an event to occur or not. It returns true if an event was processed (or if no event is available if you don't want to wait) and false if the event loop was told to stop (for instance, `uiQuit()` was called). - -* **23 May 2016** - * Fixed surrogate pair drawing on OS X. - -* **22 May 2016** - * Removed `uiControlVerifyDestroy()`; that is now part of `uiFreeControl()` itself. - * Added `uiPi`, a constant for π. This is provided for C and C++ programmers, where there is no standard named constant for π; bindings authors shouldn't need to worry about this. - * Fixed uiMultilineEntry not properly having line breaks on Windows. - * Added `uiNewNonWrappingMultilineEntry()`, which creates a uiMultilineEntry that scrolls horizontally instead of wrapping lines. (This is not documented as being changeable after the fact on Windows, hence it's a creation-time choice.) - * uiAreas on Windows and some internal Direct2D areas now respond to `WM_PRINTCLIENT` properly, which should hopefully increase the quality of screenshots. - * uiDateTimePicker on GTK+ works properly on RTL layouts and no longer disappears off the bottom of the screen if not enough room is available. It will also no longer be marked for localization of the time format (what the separator should be and whether to use 24-hour time), as that information is not provided by the locale system. :( - * Added `uiUserBugCannotSetParentOnToplevel()`, which should be used by implementations of toplevel controls in their `SetParent()` implementations. This will also be the beginning of consolidating common user bug messages into a single place, though this will be one of the only few exported user bug functions. - * uiSpinbox and uiSlider now merely swap their min and max if min ≥ max. They will no longer panic and do nothing, respectively. - * Matrix scaling will no longer leave the matrix in an invalid state on OS X and GTK+. - * `uiMultilineEntrySetText()` and `uiMutlilineEntryAppend()` on GTK+ no longer fire `OnChanged()` events. diff --git a/src/libui_sdl/libui/Compatibility.md b/src/libui_sdl/libui/Compatibility.md deleted file mode 100644 index bc16f1bf..00000000 --- a/src/libui_sdl/libui/Compatibility.md +++ /dev/null @@ -1,141 +0,0 @@ -# Useful things in newer versions - -## Windows -### Windows 7 -http://channel9.msdn.com/blogs/pdc2008/pc43 - -TODO look up PDC 2008 talk "new shell user interface" - -- new animation and text engine -- ribbon control (didn't this have some additional license?) -- LVITEM.piColFmt - -### Windows 8 - -### Windows 8.1 - -### Windows 10 - -## GTK+ -TODO what ships with Ubuntu Quantal (12.10)? - -### GTK+ 3.6 -ships with: Ubuntu Raring (13.04) - -- GtkEntry and GtkTextView have input purposes and input hints for external input methods but do not change input themselves - - according to Company, we connect to insert-text for that -- GtkLevelBar -- GtkMenuButton -- **GtkSearchEntry** - -### GTK+ 3.8 -ships with: Ubuntu Saucy (13.10) - -Not many interesting new things to us here, unless you count widget-internal tickers and single-click instead of double-click to select list items (a la KDE)... and oh yeah, also widget opacity. - -### GTK+ 3.10 -ships with: **Ubuntu Trusty (14.04 LTS)** -
GLib version: 2.40 - -- tab character stops in GtkEntry -- GtkHeaderBar - - intended for titlebar overrides; GtkInfoBar is what I keep thinking GtkHeaderBar is -- **GtkListBox** -- GtkRevealer for smooth animations of disclosure triangles -- GtkSearchBar for custom search popups -- **GtkStack and GtkStackSwitcher** -- titlebar overrides (seems to be the hot new thing) - -### GTK+ 3.12 -ships with: Ubuntu Utopic (14.10) -
GLib version: 2.42 - -- GtkActionBar (basically like the bottom-of-the-window toolbars in Mac programs) -- gtk_get_locale_direction(), for internationalization -- more control over GtkHeaderBar -- **GtkPopover** - - GtkPopovers on GtkMenuButtons -- GtkStack signaling -- **gtk_tree_path_new_from_indicesv()** (for when we add Table if we have trees too) - -### GTK+ 3.14 -ships with: **Debian Jessie**, Ubuntu Vivid (15.04) -
GLib version: Debian: 2.42, Ubuntu: 2.44 - -- gestures -- better GtkListbox selection handling -- more style classes (TODO also prior?) -- delayed switch changes on GtkSwitch - -### GTK+ 3.16 -ships with: Ubuntu Wily (15.10) -
GLib version: 2.46 - -- gtk_clipboard_get_default() (???) -- **GtkGLArea** -- proper xalign and yalign for GtkLabel; should get rid of runtime deprecation warnings -- better control of GtkListBox model-based creation (probably not relevant but) -- GtkModelButton (for GActions; probably not relevant?) -- wide handles on GtkPaned -- GtkPopoverMenu -- IPP paper names in GtkPaperSize (TODO will this be important for printing?) -- multiple matches in GtkSearchEntry (TODO evaluate priority) -- **GtkStackSidebar** -- GTK_STYLE_CLASS_LABEL, GTK_STYLE_CLASS_MONOSPACE, GTK_STYLE_CLASS_STATUSBAR, GTK_STYLE_CLASS_TOUCH_SELECTION, GTK_STYLE_CLASS_WIDE (TODO figure out which of these are useful) -- GtkTextView: extend-selection -- GtkTextView: font fallbacks - -### GTK+ 3.18 - -### GTK+ 3.20 - -## Cocoa -### Mac OS X 10.8 - -- Foundation ([full details](https://developer.apple.com/library/mac/releasenotes/Foundation/RN-FoundationOlderNotes/#//apple_ref/doc/uid/TP40008080-TRANSLATED_CHAPTER_965-TRANSLATED_DEST_999B)) - - NSDateComponents supports leap months - - NSNumberFormatter and NSDateFormatter default to 10.4 behavior by default (need to explicitly do this on 10.7) - - **NSUserNotification and NSUserNotificationCenter for Growl-style notifications** - - better linguistic triggers for Spanish and Italian - - NSByteCountFormatter -- AppKit ([full details](https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/#X10_8Notes)) - - view-based NSTableView/NSOutlineView have expansion tooltips - - NSScrollView magnification - - Quick Look events; TODO see if they conflict with keyboard handling in Area - - NSPageController (maybe useful?) - - not useful for package UI, but may be useful for a new library (probably not by me): NSSharingService - - NSOpenPanel and NSSavePanel are now longer NSPanels or NSWindows in sandboxed applications; this may be an issue should anyone dare to enable sandboxing on a program that uses package ui - - NSTextAlternatives - - -[NSOpenGLContext setFullScreen] now ineffective - - +[NSColor underPageBackgroundColor] - -### Mac OS X 10.9 - -- Foundation ([full details](https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/)) - - system-provided progress reporting/cancellation support - - NSURLComponents - - **NSCalendar, NSDateFormatter, and NSNumberFormatter are now thread-safe** - - various NSCalendar and NSDateComponents improvements -- AppKit ([full details](https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKit/)) - - sheet handling is now block-based, queued, and in NSWindow; the delegate-based NSApplication API will still exist, except without the queue - - similar changes to NSAlert - - **return value changes to NSAlert** - - window visibility APIs (occlusion) - - NSApplicationActivationPolicyAccessory - - fullscreen toolbar behavior changes - - status items for multiple menu bars - - better NSSharingService support - - a special accelerated scrolling mode, Responsive Scrolling; won't matter for us since I plan to support the scroll wheel and it won't - - NSScrollView live scrolling notifications - - NSScrollView floating (anchored/non-scrolling) subviews - - better multimonitor support - - better key-value observing for NSOpenPanel/NSSavePanel (might want to look this up to see if we can override some other juicy details... TODO) - - better accessory view key-view handling in NSOpenPanel/NSSavePanel - - NSAppearance - - **-[NSTableView moveRowAtIndex:toIndex:] bug regarding first responders fixed** - - view-specific RTL overrides - -### Mac OS X 10.10 - -### Mac OS X 10.11 -* **NSLayoutGuide** diff --git a/src/libui_sdl/libui/LICENSE b/src/libui_sdl/libui/LICENSE deleted file mode 100644 index 2351d66d..00000000 --- a/src/libui_sdl/libui/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) 2014 Pietro Gagliardi - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -(this is called the MIT License or Expat License; see http://www.opensource.org/licenses/MIT) diff --git a/src/libui_sdl/libui/README.md b/src/libui_sdl/libui/README.md deleted file mode 100644 index 01275c0e..00000000 --- a/src/libui_sdl/libui/README.md +++ /dev/null @@ -1,185 +0,0 @@ -# libui: a portable GUI library for C - -This README is being written.
-[![Build Status](https://travis-ci.org/andlabs/libui.svg)](https://travis-ci.org/andlabs/libui) - -## Announcements - -* **27 November 2016** - * Decided to split the table stuff into its own branch. It will be developed independently of everything else, along with a few other features. - -* **2 November 2016** - * Added two new functions to replace the deleted `uiWindowPosition()` and friends: `uiAreaBeginUserWindowMove()` and `uiAreaBeginUserWindowResize()`. When used in a `uiAreaHandler.Mouse()` event handler, these let you initiate a user-driven mouse move or mouse resize of the window at any point in a uiArea. - -* **31 October 2016** - * @krakjoe noticed that I accidentally used thread-unsafe code in uiQueueMain() on Unix. Fixed. - -* **24 October 2016** - * `uiWindowSetContentSize()` on Unix no longer needs to call up the GTK+ main loop. As a result, bugs related to strange behavior using that function (and the now-deleted `uiWindowSetPosition()` and `uiWindowCenter()`) should go away. I'll need to go through the bugs to verify as much, though. - -* **22 October 2016** - * Due to being unable to guarantee they will work (especially as we move toward capability-driven window systems like Wayland), or being unable to work without hacking that breaks other things, the following functions have been removed: `uiWindowPosition()`, `uiWindowSetPosition()`, `uiWindowCenter()`, and `uiWindowOnPositionChanged()`. Centering may come back at some point in the future, albeit in a possibly restricted form. A function to initiate a user move when a part of a uiArea is clicked will be provided soon. - -* **21 October 2016** - * `uiDrawTextWeightUltraBold` is now spelled correctly. Thanks to @krakjoe. - -* **18 June 2016** - * Help decide [the design of tables and trees in libui](https://github.com/andlabs/libui/issues/159); the implementation starts within the next few days, if not tomorrow! - -* **17 June 2016** - * **CMake 3.1.0 is now required.** This is due to CMake's rapid development pace in the past few years adding things libui needs to build on as many systems as possible. If your OS is supported by libui but its repositories ship with an older version of CMake, you will need to find an updated one somewhere. - * Please help [plan out a better menu API](https://github.com/andlabs/libui/issues/152). - -* **5 June 2016** - * **Alpha 3.1 is here.** This was a much-needed update to Alpha 3 that changes a few things: - * **The build system is now cmake.** cmake 2.8.11 or higher is needed. - * Static linking is now fully possible. - * MinGW linking is back, but static only. - -*Old announcements can be found in the ANNOUNCE.md file.* - -## Updates - -*Note that today's entry (Eastern Time) may be updated later today.* - -* ** And the blue outline on those buttons [ALL clicked buttons on Windows 7] won't go away - - I get this too - - not anymore -- SWP_NOCOPYBITS to avoid button redraw issues on Windows when not in tab, but only when making resize faster -- secondary side alignment control in uiBox -- Windows: don't abort if a cleanup function fails? - -- 32-bit Mac OS X support (requires lots of code changes) - - change the build system to be more receptive to arch changes - -notes to self -- explicitly document label position at top-left corner -- explicitly document that if number of radio buttons >= 1 there will always be a selection -- mark that uiControlShow() on a uiWindow() will bring to front and give keyboard focus because of OS X - - make sure ShowWindow() is sufficient for zorder on Windows -- document that you CAN use InsertAt functions to insert at the first invalid index, even if the array is empty -- note that uiTabInsertAt() does NOT change the current tab page (it may change its index if inserting before the current page) -- note that the default action for uiWindowOnClosing() is to return 0 (keep the window open) -- note that uiInitOptions should be initialized to zero -- explicitly document that uiCheckboxSetChecked() and uiEntrySetText() do not fire uiCheckboxOnToggled() and uiEntryOnChanged(), respectively -- note that if a menu is requested on systems with menubars on windows but no menus are defined, the result is a blank menubar, with whatever that means left up to the OS to decide -- note that handling of multiple consecutive separators in menus, leading separators in menus, and trailing separators in menus are all OS-defined -- note that uiDrawMatrixInvert() does not change the matrix if it fails -- note that the use of strings that are not strictly valid UTF-8 results in undefined behavior - -- test RTL - - automate RTL -- now that stock items are deprecated, I have to maintain translations of the Cancel, Open, and Save buttons on GTK+ myself (thanks baedert in irc.gimp.net/#gtk+) - - either that or keep using stock items - -- http://blogs.msdn.com/b/oldnewthing/archive/2014/02/26/10503148.aspx - -- build optimizations - -- use http://www.appveyor.com/ to do Windows build CI since people want CI - - - - - - -- consider just having the windows backend in C++ - - consider having it all in C++ - - - -don't forget LONGTERMs as well - -notes -- http://blogs.msdn.com/b/oldnewthing/archive/2004/03/29/101121.aspx on accelerators - -- group and tab should act as if they have no child if the child is hidden -on windows - - - -- a way to do recursive main loops - - how do we handle 0 returns from non-recursive uiMainStep() calls that aren't the main loop? (event handlers, for instance) -- should repeated calls to uiMainStep() after uiQuit() return 0 reliably? this will be needed for non-recursive loops - -http://stackoverflow.com/questions/38338426/meaning-of-ampersand-in-rc-files/38338841?noredirect=1#comment64093084_38338841 - -label shortcut keys - -- remove whining from source code - -[01:41:47] Hi. does pango support "fgalpha". I see that foreground="112233xx" works ( alpha=xx ), but fgalpha is a no-op -[01:52:29] pango_attr_foreground_alpha_new (32767) seems to be called in either case, but only the "foreground" attr works -[01:56:09] lolek (lolek@ip-91-244-230-76.simant.pl) joined the channel -[01:57:48] ok. seems like "foreground" is mandatory attr, 1. "foreground-without-alpha" + "alpha" works 2. "foreground-with-alpha" works. 3. "alpha" alone doesn -[01:57:52] 't work -[01:58:29] Is there a way to just specify alpha on the current foreground color ? -[02:00:23] lolek (lolek@ip-91-244-230-76.simant.pl) left the channel -[02:07:41] mjog (mjog@uniwide-pat-pool-129-94-8-98.gw.unsw.edu.au) left IRC (Quit: mjog) -[02:08:10] seb128 (seb128@53542B83.cm-6-5a.dynamic.ziggo.nl) joined the channel -[02:12:37] huh -[02:12:41] what version of pango? -[02:13:05] the latest . -[02:15:00] 1.40.3 -[02:20:46] I'll ahve to keep this in mind then, thanks -[02:20:59] if only there was a cairo-specific attribute for alpha... diff --git a/src/libui_sdl/libui/_abort/windowevents/darwin_window.m b/src/libui_sdl/libui/_abort/windowevents/darwin_window.m deleted file mode 100644 index 76180d84..00000000 --- a/src/libui_sdl/libui/_abort/windowevents/darwin_window.m +++ /dev/null @@ -1,90 +0,0 @@ -struct uiWindow { - // constraints - void (*onPositionChanged)(uiWindow *, void *); - void *onPositionChangedData; - BOOL suppressPositionChanged; - // onContentSizeChanged -}; - -@interface windowDelegateClass : NSObject { -// windowShouldClose: -- (void)windowDidMove:(NSNotification *)note; -// windowDidResize: -@end - -@implementation windowDelegateClass - -// - (BOOL)windowShouldClose:(id)sender - -// TODO doesn't happen live -- (void)windowDidMove:(NSNotification *)note -{ - uiWindow *w; - - w = [self lookupWindow:((NSWindow *) [note object])]; - if (!w->suppressPositionChanged) - (*(w->onPositionChanged))(w, w->onPositionChangedData); -} - -// - (void)windowDidResize:(NSNotification *)note - -// void uiWindowSetTitle(uiWindow *w, const char *title) - -void uiWindowPosition(uiWindow *w, int *x, int *y) -{ - NSScreen *screen; - NSRect r; - - r = [w->window frame]; - *x = r.origin.x; - // this is the right screen to use; thanks mikeash in irc.freenode.net/#macdev - // -mainScreen is useless for positioning (it's just the key window's screen) - // and we use -frame, not -visibleFrame, for dealing with absolute positions - screen = (NSScreen *) [[NSScreen screens] objectAtIndex:0]; - *y = ([screen frame].size.height - r.origin.y) - r.size.height; -} - -void uiWindowSetPosition(uiWindow *w, int x, int y) -{ - // -[NSWindow setFrameTopLeftPoint:] is acting weird so... - NSRect r; - NSScreen *screen; - - // this fires windowDidMove: - w->suppressPositionChanged = YES; - r = [w->window frame]; - r.origin.x = x; - screen = (NSScreen *) [[NSScreen screens] objectAtIndex:0]; - r.origin.y = [screen frame].size.height - (y + r.size.height); - [w->window setFrameOrigin:r.origin]; - w->suppressPositionChanged = NO; -} - -void uiWindowCenter(uiWindow *w) -{ - w->suppressPositionChanged = YES; - [w->window center]; - w->suppressPositionChanged = NO; -} - -void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onPositionChanged = f; - w->onPositionChangedData = data; -} - -// void uiWindowContentSize(uiWindow *w, int *width, int *height) - -// static int defaultOnClosing(uiWindow *w, void *data) - -static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) -{ - // do nothing -} - -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) -{ -// uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL); -// uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); -} diff --git a/src/libui_sdl/libui/_abort/windowevents/page15.c b/src/libui_sdl/libui/_abort/windowevents/page15.c deleted file mode 100644 index 0cceba86..00000000 --- a/src/libui_sdl/libui/_abort/windowevents/page15.c +++ /dev/null @@ -1,65 +0,0 @@ -static uiSpinbox *x, *y; - -static void moveX(uiSpinbox *s, void *data) -{ - uiWindow *w = uiWindow(data); - int xp, yp; - - uiWindowPosition(w, &xp, &yp); - xp = uiSpinboxValue(x); - uiWindowSetPosition(w, xp, yp); -} - -static void moveY(uiSpinbox *s, void *data) -{ - uiWindow *w = uiWindow(data); - int xp, yp; - - uiWindowPosition(w, &xp, &yp); - yp = uiSpinboxValue(y); - uiWindowSetPosition(w, xp, yp); -} - -static void updatepos(uiWindow *w) -{ - int xp, yp; - - uiWindowPosition(w, &xp, &yp); - uiSpinboxSetValue(x, xp); - uiSpinboxSetValue(y, yp); -} - -static void center(uiButton *b, void *data) -{ - uiWindow *w = uiWindow(data); - - uiWindowCenter(w); - updatepos(w); -} - -void onMove(uiWindow *w, void *data) -{ - printf("move\n"); - updatepos(w); -} - -uiBox *makePage15(uiWindow *w) -{ - hbox = newHorizontalBox(); - // TODO if I make this 1 and not add anything else AND not call uiWindowOnPositionChanged(), on OS X the box won't be able to grow vertically - uiBoxAppend(page15, uiControl(hbox), 0); - - uiBoxAppend(hbox, uiControl(uiNewLabel("Position")), 0); - x = uiNewSpinbox(INT_MIN, INT_MAX); - uiBoxAppend(hbox, uiControl(x), 1); - y = uiNewSpinbox(INT_MIN, INT_MAX); - uiBoxAppend(hbox, uiControl(y), 1); - button = uiNewButton("Center"); - uiBoxAppend(hbox, uiControl(button), 0); - - uiSpinboxOnChanged(x, moveX, w); - uiSpinboxOnChanged(y, moveY, w); - uiButtonOnClicked(button, center, w); - uiWindowOnPositionChanged(w, onMove, NULL); - updatepos(w); -} diff --git a/src/libui_sdl/libui/_abort/windowevents/ui.h b/src/libui_sdl/libui/_abort/windowevents/ui.h deleted file mode 100644 index e0d24c7f..00000000 --- a/src/libui_sdl/libui/_abort/windowevents/ui.h +++ /dev/null @@ -1,6 +0,0 @@ -// uiWindowSetTitle -_UI_EXTERN void uiWindowPosition(uiWindow *w, int *x, int *y); -_UI_EXTERN void uiWindowSetPosition(uiWindow *w, int x, int y); -_UI_EXTERN void uiWindowCenter(uiWindow *w); -_UI_EXTERN void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data); -// uiWindowContentSize diff --git a/src/libui_sdl/libui/_abort/windowevents/unix_window.c b/src/libui_sdl/libui/_abort/windowevents/unix_window.c deleted file mode 100644 index 96af26aa..00000000 --- a/src/libui_sdl/libui/_abort/windowevents/unix_window.c +++ /dev/null @@ -1,97 +0,0 @@ -struct uiWindow { -// void *onClosingData; - void (*onPositionChanged)(uiWindow *, void *); - void *onPositionChangedData; - gboolean changingPosition; -// void (*onContentSizeChanged)(uiWindow *, void *); -}; - -// static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data) - -static gboolean onConfigure(GtkWidget *win, GdkEvent *e, gpointer data) -{ - uiWindow *w = uiWindow(data); - - // there doesn't seem to be a way to determine if only moving or only resizing is happening :/ - if (w->changingPosition) - w->changingPosition = FALSE; - else - (*(w->onPositionChanged))(w, w->onPositionChangedData); - // always continue handling - return FALSE; -} - -// static void onSizeAllocate(GtkWidget *widget, GdkRectangle *allocation, gpointer data) - -// static int defaultOnClosing(uiWindow *w, void *data) - -static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) -{ - // do nothing -} - -// static void uiWindowDestroy(uiControl *c) - -// void uiWindowSetTitle(uiWindow *w, const char *title) - -// TODO allow specifying either as NULL on all platforms -void uiWindowPosition(uiWindow *w, int *x, int *y) -{ - gint rx, ry; - - gtk_window_get_position(w->window, &rx, &ry); - *x = rx; - *y = ry; -} - -void uiWindowSetPosition(uiWindow *w, int x, int y) -{ - w->changingPosition = TRUE; - gtk_window_move(w->window, x, y); - // gtk_window_move() is asynchronous - // we need to wait for a configure-event - // thanks to hergertme in irc.gimp.net/#gtk+ - while (w->changingPosition) - if (!uiMainStep(1)) - break; // stop early if uiQuit() called -} - -void uiWindowCenter(uiWindow *w) -{ - gint x, y; - GtkAllocation winalloc; - GdkWindow *gdkwin; - GdkScreen *screen; - GdkRectangle workarea; - - gtk_widget_get_allocation(w->widget, &winalloc); - gdkwin = gtk_widget_get_window(w->widget); - screen = gdk_window_get_screen(gdkwin); - gdk_screen_get_monitor_workarea(screen, - gdk_screen_get_monitor_at_window(screen, gdkwin), - &workarea); - - x = (workarea.width - winalloc.width) / 2; - y = (workarea.height - winalloc.height) / 2; - // TODO move up slightly? see what Mutter or GNOME Shell or GNOME Terminal do(es)? - uiWindowSetPosition(w, x, y); -} - -// TODO this and size changed get set during uiWindowDestroy -void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onPositionChanged = f; - w->onPositionChangedData = data; -} - -// void uiWindowContentSize(uiWindow *w, int *width, int *height) - -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) -{ -// g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w); - g_signal_connect(w->widget, "configure-event", G_CALLBACK(onConfigure), w); -// g_signal_connect(w->childHolderWidget, "size-allocate", G_CALLBACK(onSizeAllocate), w); -// uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL); -// uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); -} diff --git a/src/libui_sdl/libui/_abort/windowevents/windows_window.cpp b/src/libui_sdl/libui/_abort/windowevents/windows_window.cpp deleted file mode 100644 index 769c6db9..00000000 --- a/src/libui_sdl/libui/_abort/windowevents/windows_window.cpp +++ /dev/null @@ -1,86 +0,0 @@ -struct uiWindow { -// BOOL hasMenubar; - void (*onPositionChanged)(uiWindow *, void *); - void *onPositionChangedData; - BOOL changingPosition; // to avoid triggering the above when programmatically doing this -// void (*onContentSizeChanged)(uiWindow *, void *); -}; - -static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - case WM_WINDOWPOSCHANGED: - if ((wp->flags & SWP_NOMOVE) == 0) - if (!w->changingPosition) - (*(w->onPositionChanged))(w, w->onPositionChangedData); - // and continue anyway -// if ((wp->flags & SWP_NOSIZE) != 0) -} - -// static int defaultOnClosing(uiWindow *w, void *data) - -static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) -{ - // do nothing -} - -// static std::map windows; - -// void uiWindowSetTitle(uiWindow *w, const char *title) - -void uiWindowPosition(uiWindow *w, int *x, int *y) -{ - RECT r; - - uiWindowsEnsureGetWindowRect(w->hwnd, &r); - *x = r.left; - *y = r.top; -} - -void uiWindowSetPosition(uiWindow *w, int x, int y) -{ - w->changingPosition = TRUE; - if (SetWindowPos(w->hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER) == 0) - logLastError(L"error moving window"); - w->changingPosition = FALSE; -} - -// static void windowMonitorRect(HWND hwnd, RECT *r) - -// TODO use the work rect instead? -void uiWindowCenter(uiWindow *w) -{ - RECT wr, mr; - int x, y; - LONG wwid, mwid; - LONG wht, mht; - - uiWindowsEnsureGetWindowRect(w->hwnd, &wr); - windowMonitorRect(w->hwnd, &mr); - wwid = wr.right - wr.left; - mwid = mr.right - mr.left; - x = (mwid - wwid) / 2; - wht = wr.bottom - wr.top; - mht = mr.bottom - mr.top; - y = (mht - wht) / 2; - // y is now evenly divided, however https://msdn.microsoft.com/en-us/library/windows/desktop/dn742502(v=vs.85).aspx says that 45% should go above and 55% should go below - // so just move 5% of the way up - // TODO should this be on the work area? - // TODO is this calculation correct? - y -= y / 20; - uiWindowSetPosition(w, x, y); -} - -void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onPositionChanged = f; - w->onPositionChangedData = data; -} - -// void uiWindowContentSize(uiWindow *w, int *width, int *height) - -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) -{ -// uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL); -// uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); -} diff --git a/src/libui_sdl/libui/_wip/rules.darwin b/src/libui_sdl/libui/_wip/rules.darwin deleted file mode 100644 index e736a144..00000000 --- a/src/libui_sdl/libui/_wip/rules.darwin +++ /dev/null @@ -1,6 +0,0 @@ -every rule in ui_darwin.h -SetParent must be followed by SetSuperview and SyncEnableState - TODO can child cache it? -adding a child must be followed by a call to SyncEnableState -SyncEnableState() must call ShouldStopSyncEnableState() first thing -Enable() and Disable() must call SyncEnableState() AFTER CHANGING WHAT Enabled() WILL RETURN diff --git a/src/libui_sdl/libui/_wip/rules.unix b/src/libui_sdl/libui/_wip/rules.unix deleted file mode 100644 index 24765a97..00000000 --- a/src/libui_sdl/libui/_wip/rules.unix +++ /dev/null @@ -1,3 +0,0 @@ -every rule in ui_unix.h -SetParent must be followed by SetContainer - TODO can child cache it? diff --git a/src/libui_sdl/libui/_wip/sv/normal b/src/libui_sdl/libui/_wip/sv/normal deleted file mode 100644 index 8b6af87e..00000000 --- a/src/libui_sdl/libui/_wip/sv/normal +++ /dev/null @@ -1,25 +0,0 @@ -2016-05-26 22:38:12.877 svtest[81790:544681] backgroundColor NSNamedColorSpace System controlColor -2016-05-26 22:38:12.877 svtest[81790:544681] drawsBackground 1 -2016-05-26 22:38:12.877 svtest[81790:544681] borderType 2 -2016-05-26 22:38:12.877 svtest[81790:544681] documentCursor (null) -2016-05-26 22:38:12.877 svtest[81790:544681] hasHorizontalScroller 1 -2016-05-26 22:38:12.877 svtest[81790:544681] hasVerticalScroller 1 -2016-05-26 22:38:12.877 svtest[81790:544681] autohidesScrollers 0 -2016-05-26 22:38:12.877 svtest[81790:544681] hasHorizontalRuler 0 -2016-05-26 22:38:12.878 svtest[81790:544681] hasVerticalRuler 0 -2016-05-26 22:38:12.878 svtest[81790:544681] rulersVisible 0 -2016-05-26 22:38:12.878 svtest[81790:544681] 10.10 autoAdjContentInsets 1 -2016-05-26 22:38:12.878 svtest[81790:544681] scrollerKnobStyle 0 -2016-05-26 22:38:12.878 svtest[81790:544681] scrollerStyle 1 -2016-05-26 22:38:12.878 svtest[81790:544681] horizontalLineScroll 10 -2016-05-26 22:38:12.878 svtest[81790:544681] verticalLineScroll 10 -2016-05-26 22:38:12.886 svtest[81790:544681] horizontalPageScroll 10 -2016-05-26 22:38:12.886 svtest[81790:544681] verticalPageScroll 10 -2016-05-26 22:38:12.886 svtest[81790:544681] scrollsDynamically 1 -2016-05-26 22:38:12.886 svtest[81790:544681] findBarPosition 1 -2016-05-26 22:38:12.886 svtest[81790:544681] usesPredomAxisScroll 0 -2016-05-26 22:38:12.886 svtest[81790:544681] horizontalElasticity 0 -2016-05-26 22:38:12.886 svtest[81790:544681] verticalElasticity 0 -2016-05-26 22:38:12.887 svtest[81790:544681] 10.8 allowsMagnification 0 -2016-05-26 22:38:12.887 svtest[81790:544681] 10.8 maxMagnification 4 -2016-05-26 22:38:12.887 svtest[81790:544681] 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/normal.nots b/src/libui_sdl/libui/_wip/sv/normal.nots deleted file mode 100644 index 411d1d6d..00000000 --- a/src/libui_sdl/libui/_wip/sv/normal.nots +++ /dev/null @@ -1,25 +0,0 @@ - backgroundColor NSNamedColorSpace System controlColor - drawsBackground 1 - borderType 2 - documentCursor (null) - hasHorizontalScroller 1 - hasVerticalScroller 1 - autohidesScrollers 0 - hasHorizontalRuler 0 - hasVerticalRuler 0 - rulersVisible 0 - 10.10 autoAdjContentInsets 1 - scrollerKnobStyle 0 - scrollerStyle 1 - horizontalLineScroll 10 - verticalLineScroll 10 - horizontalPageScroll 10 - verticalPageScroll 10 - scrollsDynamically 1 - findBarPosition 1 - usesPredomAxisScroll 0 - horizontalElasticity 0 - verticalElasticity 0 - 10.8 allowsMagnification 0 - 10.8 maxMagnification 4 - 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/outlineview b/src/libui_sdl/libui/_wip/sv/outlineview deleted file mode 100644 index 67a30877..00000000 --- a/src/libui_sdl/libui/_wip/sv/outlineview +++ /dev/null @@ -1,25 +0,0 @@ -2016-05-26 22:42:16.208 svtest[82103:547159] backgroundColor NSNamedColorSpace System controlBackgroundColor -2016-05-26 22:42:16.208 svtest[82103:547159] drawsBackground 1 -2016-05-26 22:42:16.208 svtest[82103:547159] borderType 2 -2016-05-26 22:42:16.208 svtest[82103:547159] documentCursor (null) -2016-05-26 22:42:16.209 svtest[82103:547159] hasHorizontalScroller 1 -2016-05-26 22:42:16.209 svtest[82103:547159] hasVerticalScroller 1 -2016-05-26 22:42:16.209 svtest[82103:547159] autohidesScrollers 1 -2016-05-26 22:42:16.209 svtest[82103:547159] hasHorizontalRuler 0 -2016-05-26 22:42:16.209 svtest[82103:547159] hasVerticalRuler 0 -2016-05-26 22:42:16.209 svtest[82103:547159] rulersVisible 0 -2016-05-26 22:42:16.209 svtest[82103:547159] 10.10 autoAdjContentInsets 1 -2016-05-26 22:42:16.209 svtest[82103:547159] scrollerKnobStyle 0 -2016-05-26 22:42:16.209 svtest[82103:547159] scrollerStyle 1 -2016-05-26 22:42:16.209 svtest[82103:547159] horizontalLineScroll 19 -2016-05-26 22:42:16.209 svtest[82103:547159] verticalLineScroll 19 -2016-05-26 22:42:16.217 svtest[82103:547159] horizontalPageScroll 10 -2016-05-26 22:42:16.218 svtest[82103:547159] verticalPageScroll 10 -2016-05-26 22:42:16.218 svtest[82103:547159] scrollsDynamically 1 -2016-05-26 22:42:16.218 svtest[82103:547159] findBarPosition 1 -2016-05-26 22:42:16.218 svtest[82103:547159] usesPredomAxisScroll 0 -2016-05-26 22:42:16.218 svtest[82103:547159] horizontalElasticity 0 -2016-05-26 22:42:16.218 svtest[82103:547159] verticalElasticity 0 -2016-05-26 22:42:16.218 svtest[82103:547159] 10.8 allowsMagnification 0 -2016-05-26 22:42:16.218 svtest[82103:547159] 10.8 maxMagnification 4 -2016-05-26 22:42:16.218 svtest[82103:547159] 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/outlineview.nots b/src/libui_sdl/libui/_wip/sv/outlineview.nots deleted file mode 100644 index fcf18493..00000000 --- a/src/libui_sdl/libui/_wip/sv/outlineview.nots +++ /dev/null @@ -1,25 +0,0 @@ - backgroundColor NSNamedColorSpace System controlBackgroundColor - drawsBackground 1 - borderType 2 - documentCursor (null) - hasHorizontalScroller 1 - hasVerticalScroller 1 - autohidesScrollers 1 - hasHorizontalRuler 0 - hasVerticalRuler 0 - rulersVisible 0 - 10.10 autoAdjContentInsets 1 - scrollerKnobStyle 0 - scrollerStyle 1 - horizontalLineScroll 19 - verticalLineScroll 19 - horizontalPageScroll 10 - verticalPageScroll 10 - scrollsDynamically 1 - findBarPosition 1 - usesPredomAxisScroll 0 - horizontalElasticity 0 - verticalElasticity 0 - 10.8 allowsMagnification 0 - 10.8 maxMagnification 4 - 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/sourcelist b/src/libui_sdl/libui/_wip/sv/sourcelist deleted file mode 100644 index 010d6525..00000000 --- a/src/libui_sdl/libui/_wip/sv/sourcelist +++ /dev/null @@ -1,25 +0,0 @@ -2016-05-26 22:43:58.600 svtest[82237:548359] backgroundColor (null) -2016-05-26 22:43:58.600 svtest[82237:548359] drawsBackground 0 -2016-05-26 22:43:58.600 svtest[82237:548359] borderType 2 -2016-05-26 22:43:58.600 svtest[82237:548359] documentCursor (null) -2016-05-26 22:43:58.600 svtest[82237:548359] hasHorizontalScroller 1 -2016-05-26 22:43:58.600 svtest[82237:548359] hasVerticalScroller 1 -2016-05-26 22:43:58.600 svtest[82237:548359] autohidesScrollers 1 -2016-05-26 22:43:58.600 svtest[82237:548359] hasHorizontalRuler 0 -2016-05-26 22:43:58.600 svtest[82237:548359] hasVerticalRuler 0 -2016-05-26 22:43:58.600 svtest[82237:548359] rulersVisible 0 -2016-05-26 22:43:58.601 svtest[82237:548359] 10.10 autoAdjContentInsets 1 -2016-05-26 22:43:58.601 svtest[82237:548359] scrollerKnobStyle 0 -2016-05-26 22:43:58.601 svtest[82237:548359] scrollerStyle 1 -2016-05-26 22:43:58.601 svtest[82237:548359] horizontalLineScroll 19 -2016-05-26 22:43:58.601 svtest[82237:548359] verticalLineScroll 19 -2016-05-26 22:43:58.645 svtest[82237:548359] horizontalPageScroll 10 -2016-05-26 22:43:58.645 svtest[82237:548359] verticalPageScroll 10 -2016-05-26 22:43:58.645 svtest[82237:548359] scrollsDynamically 1 -2016-05-26 22:43:58.645 svtest[82237:548359] findBarPosition 1 -2016-05-26 22:43:58.645 svtest[82237:548359] usesPredomAxisScroll 0 -2016-05-26 22:43:58.645 svtest[82237:548359] horizontalElasticity 0 -2016-05-26 22:43:58.646 svtest[82237:548359] verticalElasticity 0 -2016-05-26 22:43:58.646 svtest[82237:548359] 10.8 allowsMagnification 0 -2016-05-26 22:43:58.646 svtest[82237:548359] 10.8 maxMagnification 4 -2016-05-26 22:43:58.646 svtest[82237:548359] 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/sourcelist.nots b/src/libui_sdl/libui/_wip/sv/sourcelist.nots deleted file mode 100644 index 742f41ea..00000000 --- a/src/libui_sdl/libui/_wip/sv/sourcelist.nots +++ /dev/null @@ -1,25 +0,0 @@ - backgroundColor (null) - drawsBackground 0 - borderType 2 - documentCursor (null) - hasHorizontalScroller 1 - hasVerticalScroller 1 - autohidesScrollers 1 - hasHorizontalRuler 0 - hasVerticalRuler 0 - rulersVisible 0 - 10.10 autoAdjContentInsets 1 - scrollerKnobStyle 0 - scrollerStyle 1 - horizontalLineScroll 19 - verticalLineScroll 19 - horizontalPageScroll 10 - verticalPageScroll 10 - scrollsDynamically 1 - findBarPosition 1 - usesPredomAxisScroll 0 - horizontalElasticity 0 - verticalElasticity 0 - 10.8 allowsMagnification 0 - 10.8 maxMagnification 4 - 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/tableview b/src/libui_sdl/libui/_wip/sv/tableview deleted file mode 100644 index 558b6e19..00000000 --- a/src/libui_sdl/libui/_wip/sv/tableview +++ /dev/null @@ -1,25 +0,0 @@ -2016-05-26 22:41:26.514 svtest[82032:546554] backgroundColor NSNamedColorSpace System controlBackgroundColor -2016-05-26 22:41:26.514 svtest[82032:546554] drawsBackground 1 -2016-05-26 22:41:26.514 svtest[82032:546554] borderType 2 -2016-05-26 22:41:26.514 svtest[82032:546554] documentCursor (null) -2016-05-26 22:41:26.515 svtest[82032:546554] hasHorizontalScroller 1 -2016-05-26 22:41:26.515 svtest[82032:546554] hasVerticalScroller 1 -2016-05-26 22:41:26.515 svtest[82032:546554] autohidesScrollers 1 -2016-05-26 22:41:26.515 svtest[82032:546554] hasHorizontalRuler 0 -2016-05-26 22:41:26.516 svtest[82032:546554] hasVerticalRuler 0 -2016-05-26 22:41:26.516 svtest[82032:546554] rulersVisible 0 -2016-05-26 22:41:26.516 svtest[82032:546554] 10.10 autoAdjContentInsets 1 -2016-05-26 22:41:26.516 svtest[82032:546554] scrollerKnobStyle 0 -2016-05-26 22:41:26.516 svtest[82032:546554] scrollerStyle 1 -2016-05-26 22:41:26.516 svtest[82032:546554] horizontalLineScroll 19 -2016-05-26 22:41:26.516 svtest[82032:546554] verticalLineScroll 19 -2016-05-26 22:41:26.528 svtest[82032:546554] horizontalPageScroll 10 -2016-05-26 22:41:26.528 svtest[82032:546554] verticalPageScroll 10 -2016-05-26 22:41:26.528 svtest[82032:546554] scrollsDynamically 1 -2016-05-26 22:41:26.528 svtest[82032:546554] findBarPosition 1 -2016-05-26 22:41:26.528 svtest[82032:546554] usesPredomAxisScroll 0 -2016-05-26 22:41:26.528 svtest[82032:546554] horizontalElasticity 0 -2016-05-26 22:41:26.528 svtest[82032:546554] verticalElasticity 0 -2016-05-26 22:41:26.528 svtest[82032:546554] 10.8 allowsMagnification 0 -2016-05-26 22:41:26.528 svtest[82032:546554] 10.8 maxMagnification 4 -2016-05-26 22:41:26.528 svtest[82032:546554] 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/tableview.nots b/src/libui_sdl/libui/_wip/sv/tableview.nots deleted file mode 100644 index fcf18493..00000000 --- a/src/libui_sdl/libui/_wip/sv/tableview.nots +++ /dev/null @@ -1,25 +0,0 @@ - backgroundColor NSNamedColorSpace System controlBackgroundColor - drawsBackground 1 - borderType 2 - documentCursor (null) - hasHorizontalScroller 1 - hasVerticalScroller 1 - autohidesScrollers 1 - hasHorizontalRuler 0 - hasVerticalRuler 0 - rulersVisible 0 - 10.10 autoAdjContentInsets 1 - scrollerKnobStyle 0 - scrollerStyle 1 - horizontalLineScroll 19 - verticalLineScroll 19 - horizontalPageScroll 10 - verticalPageScroll 10 - scrollsDynamically 1 - findBarPosition 1 - usesPredomAxisScroll 0 - horizontalElasticity 0 - verticalElasticity 0 - 10.8 allowsMagnification 0 - 10.8 maxMagnification 4 - 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/textview b/src/libui_sdl/libui/_wip/sv/textview deleted file mode 100644 index e6363625..00000000 --- a/src/libui_sdl/libui/_wip/sv/textview +++ /dev/null @@ -1,25 +0,0 @@ -2016-05-26 22:40:02.050 svtest[81927:545793] backgroundColor NSCalibratedWhiteColorSpace 1 1 -2016-05-26 22:40:02.050 svtest[81927:545793] drawsBackground 1 -2016-05-26 22:40:02.051 svtest[81927:545793] borderType 2 -2016-05-26 22:40:02.052 svtest[81927:545793] documentCursor -2016-05-26 22:40:02.052 svtest[81927:545793] hasHorizontalScroller 0 -2016-05-26 22:40:02.052 svtest[81927:545793] hasVerticalScroller 1 -2016-05-26 22:40:02.052 svtest[81927:545793] autohidesScrollers 0 -2016-05-26 22:40:02.052 svtest[81927:545793] hasHorizontalRuler 0 -2016-05-26 22:40:02.052 svtest[81927:545793] hasVerticalRuler 0 -2016-05-26 22:40:02.052 svtest[81927:545793] rulersVisible 0 -2016-05-26 22:40:02.052 svtest[81927:545793] 10.10 autoAdjContentInsets 1 -2016-05-26 22:40:02.052 svtest[81927:545793] scrollerKnobStyle 0 -2016-05-26 22:40:02.052 svtest[81927:545793] scrollerStyle 1 -2016-05-26 22:40:02.054 svtest[81927:545793] horizontalLineScroll 10 -2016-05-26 22:40:02.055 svtest[81927:545793] verticalLineScroll 10 -2016-05-26 22:40:02.062 svtest[81927:545793] horizontalPageScroll 10 -2016-05-26 22:40:02.062 svtest[81927:545793] verticalPageScroll 10 -2016-05-26 22:40:02.062 svtest[81927:545793] scrollsDynamically 1 -2016-05-26 22:40:02.062 svtest[81927:545793] findBarPosition 1 -2016-05-26 22:40:02.062 svtest[81927:545793] usesPredomAxisScroll 0 -2016-05-26 22:40:02.062 svtest[81927:545793] horizontalElasticity 0 -2016-05-26 22:40:02.062 svtest[81927:545793] verticalElasticity 0 -2016-05-26 22:40:02.062 svtest[81927:545793] 10.8 allowsMagnification 0 -2016-05-26 22:40:02.062 svtest[81927:545793] 10.8 maxMagnification 4 -2016-05-26 22:40:02.063 svtest[81927:545793] 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/sv/textview.nots b/src/libui_sdl/libui/_wip/sv/textview.nots deleted file mode 100644 index 7476b0ea..00000000 --- a/src/libui_sdl/libui/_wip/sv/textview.nots +++ /dev/null @@ -1,25 +0,0 @@ - backgroundColor NSCalibratedWhiteColorSpace 1 1 - drawsBackground 1 - borderType 2 - documentCursor - hasHorizontalScroller 0 - hasVerticalScroller 1 - autohidesScrollers 0 - hasHorizontalRuler 0 - hasVerticalRuler 0 - rulersVisible 0 - 10.10 autoAdjContentInsets 1 - scrollerKnobStyle 0 - scrollerStyle 1 - horizontalLineScroll 10 - verticalLineScroll 10 - horizontalPageScroll 10 - verticalPageScroll 10 - scrollsDynamically 1 - findBarPosition 1 - usesPredomAxisScroll 0 - horizontalElasticity 0 - verticalElasticity 0 - 10.8 allowsMagnification 0 - 10.8 maxMagnification 4 - 10.8 minMagnification 0.25 diff --git a/src/libui_sdl/libui/_wip/table/test_page9.c b/src/libui_sdl/libui/_wip/table/test_page9.c deleted file mode 100644 index f2351f2c..00000000 --- a/src/libui_sdl/libui/_wip/table/test_page9.c +++ /dev/null @@ -1,80 +0,0 @@ -// 18 october 2015 -#include "test.h" - -// TODO manage the memory of the uiTableModel - -static intmax_t nColumns = 4; -static uiTableColumnType coltypes[] = { - uiTableColumnText, - uiTableColumnText, - uiTableColumnCheckbox, - uiTableColumnCheckbox, -}; - -static intmax_t nRows = 6; - -static intmax_t modelNumRows(uiTableModel *m, void *mData) -{ - return nRows; -} - -void *modelCellValue(uiTableModel *m, void *mData, intmax_t row, intmax_t column) -{ - char line[20]; - - line[0] = 'R'; - line[1] = 'o'; - line[2] = 'w'; - line[3] = ' '; - line[4] = row + '0'; - line[5] = '\0'; - switch (column) { - case 0: - case 1: - return uiTableModelFromString(line); - case 2: - return uiTableModelFromBool(row % 2 == 0); - case 3: - return uiTableModelFromBool(row % 3 == 0); - } - // TODO - return NULL; -} - -// TODO make this not need to be static -uiTableModelSpec spec; - -void modelSetCellValue(uiTableModel *m, void *mData, intmax_t row, intmax_t column, void *value) -{ - // TODO -} - -uiBox *makePage9(void) -{ - uiBox *page9; - uiTable *table; - uiTableModel *model; - uiTableColumnParams p; - intmax_t i; - - page9 = newVerticalBox(); - - table = uiNewTable(); - uiBoxAppend(page9, uiControl(table), 1); - - spec.NumRows = modelNumRows; - spec.CellValue = modelCellValue; - spec.SetCellValue = modelSetCellValue; - model = uiNewTableModel(nColumns, coltypes, &spec, NULL); - uiTableSetModel(table, model); - - for (i = 0; i < nColumns; i++) { - p.Name = "Column"; - p.Type = coltypes[i]; - p.Mutable = i % 2 == 1; - p.ValueColumn = i; - uiTableAppendColumn(table, &p); - } - - return page9; -} diff --git a/src/libui_sdl/libui/_wip/table/ui.h b/src/libui_sdl/libui/_wip/table/ui.h deleted file mode 100644 index a5c30c8b..00000000 --- a/src/libui_sdl/libui/_wip/table/ui.h +++ /dev/null @@ -1,46 +0,0 @@ -typedef struct uiTable uiTable; -typedef struct uiTableModel uiTableModel; -typedef struct uiTableModelSpec uiTableModelSpec; -typedef struct uiTableColumnParams uiTableColumnParams; -typedef enum uiTableColumnType uiTableColumnType; -typedef enum uiTableNotification uiTableNotification; - -_UI_EXTERN uintmax_t uiTableType(void); -#define uiTable(this) ((uiTable *) uiIsA((this), uiTableType(), 1)) -_UI_EXTERN void uiTableSetModel(uiTable *t, uiTableModel *m); -_UI_EXTERN void uiTableAppendColumn(uiTable *t, uiTableColumnParams *p); -_UI_EXTERN uiTable *uiNewTable(void); - -enum uiTableColumnType { - uiTableColumnText, -//TODO uiTableColumnImage, - uiTableColumnCheckbox, -}; - -struct uiTableModelSpec { - intmax_t (*NumRows)(uiTableModel *m, void *mData); - void *(*CellValue)(uiTableModel *m, void *mData, intmax_t row, intmax_t column); - void (*SetCellValue)(uiTableModel *m, void *mData, intmax_t row, intmax_t column, void *value); -}; - -enum uiTableNotification { - uiTableRowInserted, - uiTableRowDeleted, - uiTableCellChanged, -}; - -_UI_EXTERN uiTableModel *uiNewTableModel(uintmax_t nCols, uiTableColumnType *types, uiTableModelSpec *spec, void *mData); -_UI_EXTERN void uiFreeTableModel(uiTableModel *m); -_UI_EXTERN void uiTableModelNotify(uiTableModel *m, uiTableNotification notification, intmax_t row, intmax_t column); - -#define uiTableModelFromBool(b) ((void *) ((intptr_t) (b))) -_UI_EXTERN void *uiTableModelFromString(const char *str); - -struct uiTableColumnParams { - const char *Name; - // TODO make this unnecessary - uiTableColumnType Type; - int Mutable; // TODO move to the model? - intmax_t ValueColumn; - // TODO background color -}; diff --git a/src/libui_sdl/libui/_wip/table/unix_table.c b/src/libui_sdl/libui/_wip/table/unix_table.c deleted file mode 100644 index 825cf675..00000000 --- a/src/libui_sdl/libui/_wip/table/unix_table.c +++ /dev/null @@ -1,87 +0,0 @@ -// 18 october 2015 -#include "uipriv_unix.h" - -struct uiTable { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *scontainer; - GtkScrolledWindow *sw; - GtkWidget *treeWidget; - GtkTreeView *treeview; - GtkTreeSelection *selection; - uiTableModel *model; -}; - -uiUnixDefineControl( - uiTable // type name -) - -void uiTableSetModel(uiTable *t, uiTableModel *m) -{ - t->model = m; - gtk_tree_view_set_model(t->treeview, GTK_TREE_MODEL(t->model)); -} - -void uiTableAppendColumn(uiTable *t, uiTableColumnParams *p) -{ - GtkTreeViewColumn *col; - GtkCellRenderer *r; - const char *attribute; - const char *mutableAttr; - gboolean mutable; - - switch (p->Type) { - case uiTableColumnText: - r = gtk_cell_renderer_text_new(); - attribute = "text"; - mutableAttr = "editable"; - break; -//TODO case uiTableColumnImage: - // TODO - case uiTableColumnCheckbox: - r = gtk_cell_renderer_toggle_new(); - attribute = "active"; - mutableAttr = "activatable"; - break; - default: - complain("unknown table column type %d in uiTableAppendColumn()", p->Type); - } - mutable = FALSE; - if (p->Mutable) - mutable = TRUE; - g_object_set(r, - mutableAttr, mutable, - NULL); - col = gtk_tree_view_column_new_with_attributes(p->Name, r, - attribute, p->ValueColumn, - NULL); - // allow columns to be resized - gtk_tree_view_column_set_resizable(col, TRUE); - gtk_tree_view_append_column(t->treeview, col); -} - -uiTable *uiNewTable(void) -{ - uiTable *t; - - t = (uiTable *) uiNewControl(uiTableType()); - - t->widget = gtk_scrolled_window_new(NULL, NULL); - t->scontainer = GTK_CONTAINER(t->widget); - t->sw = GTK_SCROLLED_WINDOW(t->widget); - - t->treeWidget = gtk_tree_view_new(); - t->treeview = GTK_TREE_VIEW(t->treeWidget); - - t->selection = gtk_tree_view_get_selection(t->treeview); - - // give a border and add the table - gtk_scrolled_window_set_shadow_type(t->sw, GTK_SHADOW_IN); - gtk_container_add(t->scontainer, t->treeWidget); - // and make the table visible; only the scrolled window's visibility is controlled by libui - gtk_widget_show(t->treeWidget); - - uiUnixFinishNewControl(t, uiTable); - - return t; -} diff --git a/src/libui_sdl/libui/_wip/table/unix_tablemodel.c b/src/libui_sdl/libui/_wip/table/unix_tablemodel.c deleted file mode 100644 index 02234657..00000000 --- a/src/libui_sdl/libui/_wip/table/unix_tablemodel.c +++ /dev/null @@ -1,303 +0,0 @@ -// 18 october 2015 -#include "uipriv_unix.h" - -// On GTK+, uiTableModel is a GtkTreeModel. - -#define uiTableModelType (uiTableModel_get_type()) -#define uiTableModel(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), uiTableModelType, uiTableModel)) -#define isAreaWidget(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), uiTableModelType)) -#define uiTableModelClass(class) (G_TYPE_CHECK_CLASS_CAST((class), uiTableModelType, uiTableModelClass)) -#define isAreaWidgetClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), uiTableModel)) -#define getAreaWidgetClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), uiTableModelType, uiTableModelClass)) - -typedef struct uiTableModel uiTableModel; -typedef struct uiTableModelClass uiTableModelClass; - -struct uiTableModel { - GObject parent_instance; - uiTableModelSpec *spec; - void *mData; - intmax_t nColumns; - GType *coltypes; -}; - -struct uiTableModelClass { - GObjectClass parent_class; -}; - -static void uiTableModel_treeModel_init(GtkTreeModelIface *); - -G_DEFINE_TYPE_WITH_CODE(uiTableModel, uiTableModel, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, uiTableModel_treeModel_init)) - -static void uiTableModel_init(uiTableModel *m) -{ - // do nothing -} - -static void uiTableModel_dispose(GObject *obj) -{ - G_OBJECT_CLASS(uiTableModel_parent_class)->dispose(obj); -} - -static void uiTableModel_finalize(GObject *obj) -{ - uiTableModel *m = uiTableModel(obj); - - uiFree(m->coltypes); - G_OBJECT_CLASS(uiTableModel_parent_class)->finalize(obj); -} - -static GtkTreeModelFlags uiTableModel_get_flags(GtkTreeModel *mb) -{ - return GTK_TREE_MODEL_LIST_ONLY; -} - -static gint uiTableModel_get_n_columns(GtkTreeModel *mb) -{ - uiTableModel *m = uiTableModel(mb); - - return m->nColumns; -} - -static GType uiTableModel_get_column_type(GtkTreeModel *mb, gint index) -{ - uiTableModel *m = uiTableModel(mb); - - return m->coltypes[index]; -} - -/* -how our GtkTreeIters are stored: - stamp: either GOOD_STAMP or BAD_STAMP - user_data: row index -Thanks to Company in irc.gimp.net/#gtk+ for suggesting the GSIZE_TO_POINTER() t -rick. -*/ -#define GOOD_STAMP 0x1234 -#define BAD_STAMP 0x5678 -#define FROM(x) ((gint) GPOINTER_TO_SIZE((x))) -#define TO(x) GSIZE_TO_POINTER((gsize) (x)) - -#define numRows(m) ((*((m)->spec->NumRows))((m), (m)->mData)) -#define cellValue(m, row, col) ((*((m)->spec->CellValue))((m), (m)->mData, row, column)) - -static gboolean uiTableModel_get_iter(GtkTreeModel *mb, GtkTreeIter *iter, GtkTreePath *path) -{ - uiTableModel *m = uiTableModel(mb); - gint index; - - if (gtk_tree_path_get_depth(path) != 1) - goto bad; - index = gtk_tree_path_get_indices(path)[0]; - if (index < 0) - goto bad; - if (index >= numRows(m)) - goto bad; - iter->stamp = GOOD_STAMP; - iter->user_data = TO(index); - return TRUE; -bad: - iter->stamp = BAD_STAMP; - return FALSE; -} - -static GtkTreePath *uiTableModel_get_path(GtkTreeModel *mb, GtkTreeIter *iter) -{ - // note: from this point forward, the GOOD_STAMP checks ensure that the index stored in iter is nonnegative - if (iter->stamp != GOOD_STAMP) - return NULL; // this is what both GtkListStore and GtkTreeStore do - return gtk_tree_path_new_from_indices(FROM(iter->user_data), -1); -} - -void *uiTableModelFromString(const char *str) -{ - return g_strdup(str); -} - -#define toBool(v) ((int) ((intptr_t) (v))) -#define toStr(v) ((char *) (v)) - -static void uiTableModel_get_value(GtkTreeModel *mb, GtkTreeIter *iter, gint column, GValue *value) -{ - uiTableModel *m = uiTableModel(mb); - void *v; - GType type; - - if (iter->stamp != GOOD_STAMP) - return; // this is what both GtkListStore and GtkTreeStore do - v = cellValue(m, FROM(iter->user_data), column); - type = m->coltypes[column]; - g_value_init(value, type); - if (type == G_TYPE_STRING) - g_value_take_string(value, toStr(v)); - // the GValue now manages the memory of the string that was g_strdup()'d before - // TODO image - else if (type == G_TYPE_BOOLEAN) - g_value_set_boolean(value, toBool(v)); - else - complain("unknown GType in uiTableModel_get_value()"); -} - -static gboolean uiTableModel_iter_next(GtkTreeModel *mb, GtkTreeIter *iter) -{ - uiTableModel *m = uiTableModel(mb); - gint index; - - if (iter->stamp != GOOD_STAMP) - return FALSE; // this is what both GtkListStore and GtkTreeStore do - index = FROM(iter->user_data); - index++; - if (index >= numRows(m)) { - iter->stamp = BAD_STAMP; - return FALSE; - } - iter->user_data = TO(index); - return TRUE; -} - -static gboolean uiTableModel_iter_previous(GtkTreeModel *mb, GtkTreeIter *iter) -{ - uiTableModel *m = uiTableModel(mb); - gint index; - - if (iter->stamp != GOOD_STAMP) - return FALSE; // this is what both GtkListStore and GtkTreeStore do - index = FROM(iter->user_data); - if (index <= 0) { - iter->stamp = BAD_STAMP; - return FALSE; - } - index--; - iter->user_data = TO(index); - return TRUE; -} - -static gboolean uiTableModel_iter_children(GtkTreeModel *mb, GtkTreeIter *iter, GtkTreeIter *parent) -{ - uiTableModel *m = uiTableModel(mb); - - if (parent == NULL && numRows(m) > 0) { - iter->stamp = GOOD_STAMP; - iter->user_data = 0; - return TRUE; - } - iter->stamp = BAD_STAMP; - return FALSE; -} - -static gboolean uiTableModel_iter_has_child(GtkTreeModel *mb, GtkTreeIter *iter) -{ - return FALSE; -} - -static gint uiTableModel_iter_n_children(GtkTreeModel *mb, GtkTreeIter *iter) -{ - uiTableModel *m = uiTableModel(mb); - - if (iter == NULL) - return numRows(m); - return 0; -} - -static gboolean uiTableModel_iter_nth_child(GtkTreeModel *mb, GtkTreeIter *iter, GtkTreeIter *parent, gint n) -{ - uiTableModel *m = uiTableModel(mb); - - if (parent == NULL && n >= 0 && n < numRows(m)) { - iter->stamp = GOOD_STAMP; - iter->user_data = TO(n); - return TRUE; - } - iter->stamp = BAD_STAMP; - return FALSE; -} - -static gboolean uiTableModel_iter_parent(GtkTreeModel *mb, GtkTreeIter *iter, GtkTreeIter *child) -{ - iter->stamp = BAD_STAMP; - return FALSE; -} - -static void uiTableModel_class_init(uiTableModelClass *class) -{ - G_OBJECT_CLASS(class)->dispose = uiTableModel_dispose; - G_OBJECT_CLASS(class)->finalize = uiTableModel_finalize; -} - -static void uiTableModel_treeModel_init(GtkTreeModelIface *iface) -{ - iface->get_flags = uiTableModel_get_flags; - iface->get_n_columns = uiTableModel_get_n_columns; - iface->get_column_type = uiTableModel_get_column_type; - iface->get_iter = uiTableModel_get_iter; - iface->get_path = uiTableModel_get_path; - iface->get_value = uiTableModel_get_value; - iface->iter_next = uiTableModel_iter_next; - iface->iter_previous = uiTableModel_iter_previous; - iface->iter_children = uiTableModel_iter_children; - iface->iter_has_child = uiTableModel_iter_has_child; - iface->iter_n_children = uiTableModel_iter_n_children; - iface->iter_nth_child = uiTableModel_iter_nth_child; - iface->iter_parent = uiTableModel_iter_parent; - // no need for ref_node or unref_node -} - -uiTableModel *uiNewTableModel(uintmax_t nCols, uiTableColumnType *types, uiTableModelSpec *spec, void *mData) -{ - uiTableModel *m; - intmax_t i; - - m = uiTableModel(g_object_new(uiTableModelType, NULL)); - m->spec = spec; - m->mData = mData; - m->nColumns = nCols; - m->coltypes = (GType *) uiAlloc(m->nColumns * sizeof (GType), "GType[]"); - for (i = 0; i < m->nColumns; i++) - switch (types[i]) { - case uiTableColumnText: - m->coltypes[i] = G_TYPE_STRING; - break; -//TODO case uiTableColumnImage: - // TODO - case uiTableColumnCheckbox: - m->coltypes[i] = G_TYPE_BOOLEAN; - break; - default: - complain("unknown column type %d in uiNewTableModel()", types[i]); - } - return m; -} - -// TODO ensure no tables are subscribed -void uiFreeTableModel(uiTableModel *m) -{ - g_object_unref(m); -} - -void uiTableModelNotify(uiTableModel *m, uiTableNotification notification, intmax_t row, intmax_t column) -{ - GtkTreeModel *model = GTK_TREE_MODEL(m); - GtkTreePath *path; - GtkTreeIter iter; - - path = gtk_tree_path_new_from_indices(row, -1); - switch (notification) { - case uiTableRowInserted: - if (gtk_tree_model_get_iter(model, &iter, path) == FALSE) - complain("invalid row given to row inserted in uiTableModelNotify()"); - gtk_tree_model_row_inserted(model, path, &iter); - break; - case uiTableRowDeleted: - gtk_tree_model_row_deleted(model, path); - break; - case uiTableCellChanged: - if (gtk_tree_model_get_iter(model, &iter, path) == FALSE) - complain("invalid row given to row changed in uiTableModelNotify()"); - gtk_tree_model_row_changed(model, path, &iter); - break; - default: - complain("unknown uiTable notification %d in uiTableModelNotify()", notification); - } - gtk_tree_path_free(path); -} diff --git a/src/libui_sdl/libui/common/CMakeLists.txt b/src/libui_sdl/libui/common/CMakeLists.txt deleted file mode 100644 index 91d79493..00000000 --- a/src/libui_sdl/libui/common/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# 3 june 2016 - -list(APPEND _LIBUI_SOURCES - common/areaevents.c - common/control.c - common/debug.c - common/matrix.c - common/shouldquit.c - common/userbugs.c -) -set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) - -list(APPEND _LIBUI_INCLUDEDIRS - common -) -set(_LIBUI_INCLUDEDIRS ${_LIBUI_INCLUDEDIRS} PARENT_SCOPE) diff --git a/src/libui_sdl/libui/common/areaevents.c b/src/libui_sdl/libui/common/areaevents.c deleted file mode 100644 index cf3c288c..00000000 --- a/src/libui_sdl/libui/common/areaevents.c +++ /dev/null @@ -1,167 +0,0 @@ -// 29 march 2014 -#include "../ui.h" -#include "uipriv.h" - -/* -Windows and GTK+ have a limit of 2 and 3 clicks, respectively, natively supported. Fortunately, we can simulate the double/triple-click behavior to build higher-order clicks. We can use the same algorithm Windows uses on both: - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx -For GTK+, we pull the double-click time and double-click distance, which work the same as the equivalents on Windows (so the distance is in all directions), from the GtkSettings system. - -On GTK+ this will also allow us to discard the GDK_BUTTON_2PRESS and GDK_BUTTON_3PRESS events, so the button press stream will be just like on other platforms. - -Thanks to mclasen, garnacho_, halfline, and tristan in irc.gimp.net/#gtk+. -*/ - -// x, y, xdist, ydist, and c.rect must have the same units -// so must time, maxTime, and c.prevTime -int clickCounterClick(clickCounter *c, int button, int x, int y, uintptr_t time, uintptr_t maxTime, int32_t xdist, int32_t ydist) -{ - // different button than before? if so, don't count - if (button != c->curButton) - c->count = 0; - - // (x, y) in the allowed region for a double-click? if not, don't count - if (x < c->rectX0) - c->count = 0; - if (y < c->rectY0) - c->count = 0; - if (x >= c->rectX1) - c->count = 0; - if (y >= c->rectY1) - c->count = 0; - - // too slow? if so, don't count - // note the below expression; time > (c.prevTime + maxTime) can overflow! - if ((time - c->prevTime) > maxTime) // too slow; don't count - c->count = 0; - - c->count++; // if either of the above ifs happened, this will make the click count 1; otherwise it will make the click count 2, 3, 4, 5, ... - - // now we need to update the internal structures for the next test - c->curButton = button; - c->prevTime = time; - c->rectX0 = x - xdist; - c->rectY0 = y - ydist; - c->rectX1 = x + xdist; - c->rectY1 = y + ydist; - - return c->count; -} - -void clickCounterReset(clickCounter *c) -{ - c->curButton = 0; - c->rectX0 = 0; - c->rectY0 = 0; - c->rectX1 = 0; - c->rectY1 = 0; - c->prevTime = 0; - c->count = 0; -} - -/* -For position independence across international keyboard layouts, typewriter keys are read using scancodes (which are always set 1). -Windows provides the scancodes directly in the LPARAM. -GTK+ provides the scancodes directly from the underlying window system via GdkEventKey.hardware_keycode. -On X11, this is scancode + 8 (because X11 keyboard codes have a range of [8,255]). -Wayland is guaranteed to give the same result (thanks ebassi in irc.gimp.net/#gtk+). -On Linux, where evdev is used instead of polling scancodes directly from the keyboard, evdev's typewriter section key code constants are the same as scancodes anyway, so the rules above apply. -Typewriter section scancodes are the same across international keyboards with some exceptions that have been accounted for (see KeyEvent's documentation); see http://www.quadibloc.com/comp/scan.htm for details. -Non-typewriter keys can be handled safely using constants provided by the respective backend API. - -Because GTK+ keysyms may or may not obey Num Lock, we also handle the 0-9 and . keys on the numeric keypad with scancodes (they match too). -*/ - -// use uintptr_t to be safe; the size of the scancode/hardware key code field on each platform is different -static const struct { - uintptr_t scancode; - char equiv; -} scancodeKeys[] = { - { 0x02, '1' }, - { 0x03, '2' }, - { 0x04, '3' }, - { 0x05, '4' }, - { 0x06, '5' }, - { 0x07, '6' }, - { 0x08, '7' }, - { 0x09, '8' }, - { 0x0A, '9' }, - { 0x0B, '0' }, - { 0x0C, '-' }, - { 0x0D, '=' }, - { 0x0E, '\b' }, - { 0x0F, '\t' }, - { 0x10, 'q' }, - { 0x11, 'w' }, - { 0x12, 'e' }, - { 0x13, 'r' }, - { 0x14, 't' }, - { 0x15, 'y' }, - { 0x16, 'u' }, - { 0x17, 'i' }, - { 0x18, 'o' }, - { 0x19, 'p' }, - { 0x1A, '[' }, - { 0x1B, ']' }, - { 0x1C, '\n' }, - { 0x1E, 'a' }, - { 0x1F, 's' }, - { 0x20, 'd' }, - { 0x21, 'f' }, - { 0x22, 'g' }, - { 0x23, 'h' }, - { 0x24, 'j' }, - { 0x25, 'k' }, - { 0x26, 'l' }, - { 0x27, ';' }, - { 0x28, '\'' }, - { 0x29, '`' }, - { 0x2B, '\\' }, - { 0x2C, 'z' }, - { 0x2D, 'x' }, - { 0x2E, 'c' }, - { 0x2F, 'v' }, - { 0x30, 'b' }, - { 0x31, 'n' }, - { 0x32, 'm' }, - { 0x33, ',' }, - { 0x34, '.' }, - { 0x35, '/' }, - { 0x39, ' ' }, - { 0xFFFF, 0 }, -}; - -static const struct { - uintptr_t scancode; - uiExtKey equiv; -} scancodeExtKeys[] = { - { 0x47, uiExtKeyN7 }, - { 0x48, uiExtKeyN8 }, - { 0x49, uiExtKeyN9 }, - { 0x4B, uiExtKeyN4 }, - { 0x4C, uiExtKeyN5 }, - { 0x4D, uiExtKeyN6 }, - { 0x4F, uiExtKeyN1 }, - { 0x50, uiExtKeyN2 }, - { 0x51, uiExtKeyN3 }, - { 0x52, uiExtKeyN0 }, - { 0x53, uiExtKeyNDot }, - { 0xFFFF, 0 }, -}; - -int fromScancode(uintptr_t scancode, uiAreaKeyEvent *ke) -{ - int i; - - for (i = 0; scancodeKeys[i].scancode != 0xFFFF; i++) - if (scancodeKeys[i].scancode == scancode) { - ke->Key = scancodeKeys[i].equiv; - return 1; - } - for (i = 0; scancodeExtKeys[i].scancode != 0xFFFF; i++) - if (scancodeExtKeys[i].scancode == scancode) { - ke->ExtKey = scancodeExtKeys[i].equiv; - return 1; - } - return 0; -} diff --git a/src/libui_sdl/libui/common/control.c b/src/libui_sdl/libui/common/control.c deleted file mode 100644 index 78d1e5f8..00000000 --- a/src/libui_sdl/libui/common/control.c +++ /dev/null @@ -1,117 +0,0 @@ -// 26 may 2015 -#include "../ui.h" -#include "uipriv.h" - -void uiControlDestroy(uiControl *c) -{ - (*(c->Destroy))(c); -} - -uintptr_t uiControlHandle(uiControl *c) -{ - return (*(c->Handle))(c); -} - -uiControl *uiControlParent(uiControl *c) -{ - return (*(c->Parent))(c); -} - -void uiControlSetParent(uiControl *c, uiControl *parent) -{ - (*(c->SetParent))(c, parent); -} - -int uiControlToplevel(uiControl *c) -{ - return (*(c->Toplevel))(c); -} - -int uiControlVisible(uiControl *c) -{ - return (*(c->Visible))(c); -} - -void uiControlShow(uiControl *c) -{ - (*(c->Show))(c); -} - -void uiControlHide(uiControl *c) -{ - (*(c->Hide))(c); -} - -int uiControlEnabled(uiControl *c) -{ - return (*(c->Enabled))(c); -} - -void uiControlEnable(uiControl *c) -{ - (*(c->Enable))(c); -} - -void uiControlDisable(uiControl *c) -{ - (*(c->Disable))(c); -} - -void uiControlSetFocus(uiControl *c) -{ - (*(c->SetFocus))(c); -} - -void uiControlSetMinSize(uiControl *c, int w, int h) -{ - c->MinWidth = w; - c->MinHeight = h; - (*(c->SetMinSize))(c, w, h); -} - -#define uiControlSignature 0x7569436F - -uiControl *uiAllocControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr) -{ - uiControl *c; - - c = (uiControl *) uiAlloc(size, typenamestr); - c->Signature = uiControlSignature; - c->OSSignature = OSsig; - c->TypeSignature = typesig; - - c->MinWidth = -1; - c->MinHeight = -1; - - return c; -} - -void uiFreeControl(uiControl *c) -{ - if (uiControlParent(c) != NULL) - userbug("You cannot destroy a uiControl while it still has a parent. (control: %p)", c); - uiFree(c); -} - -void uiControlVerifySetParent(uiControl *c, uiControl *parent) -{ - uiControl *curParent; - - if (uiControlToplevel(c)) - userbug("You cannot give a toplevel uiControl a parent. (control: %p)", c); - curParent = uiControlParent(c); - if (parent != NULL && curParent != NULL) - userbug("You cannot give a uiControl a parent while it already has one. (control: %p; current parent: %p; new parent: %p)", c, curParent, parent); - if (parent == NULL && curParent == NULL) - implbug("attempt to double unparent uiControl %p", c); -} - -int uiControlEnabledToUser(uiControl *c) -{ - while (c != NULL) { - if (!uiControlEnabled(c)) - return 0; - c = uiControlParent(c); - } - return 1; -} diff --git a/src/libui_sdl/libui/common/controlsigs.h b/src/libui_sdl/libui/common/controlsigs.h deleted file mode 100644 index 1cbf18d5..00000000 --- a/src/libui_sdl/libui/common/controlsigs.h +++ /dev/null @@ -1,25 +0,0 @@ -// 24 april 2016 - -#define uiAreaSignature 0x41726561 -#define uiBoxSignature 0x426F784C -#define uiButtonSignature 0x42746F6E -#define uiCheckboxSignature 0x43686B62 -#define uiColorButtonSignature 0x436F6C42 -#define uiComboboxSignature 0x436F6D62 -#define uiDateTimePickerSignature 0x44545069 -#define uiEditableComboboxSignature 0x45644362 -#define uiEntrySignature 0x456E7472 -#define uiFontButtonSignature 0x466F6E42 -#define uiFormSignature 0x466F726D -#define uiGridSignature 0x47726964 -#define uiGroupSignature 0x47727062 -#define uiLabelSignature 0x4C61626C -#define uiMultilineEntrySignature 0x4D6C6E45 -#define uiProgressBarSignature 0x50426172 -#define uiRadioButtonsSignature 0x5264696F -#define uiSeparatorSignature 0x53657061 -#define uiSliderSignature 0x536C6964 -#define uiSpinboxSignature 0x5370696E -#define uiTabSignature 0x54616273 -#define uiTableSignature 0x5461626C -#define uiWindowSignature 0x57696E64 diff --git a/src/libui_sdl/libui/common/debug.c b/src/libui_sdl/libui/common/debug.c deleted file mode 100644 index 97280b47..00000000 --- a/src/libui_sdl/libui/common/debug.c +++ /dev/null @@ -1,21 +0,0 @@ -// 13 may 2016 -#include "../ui.h" -#include "uipriv.h" - -void _implbug(const char *file, const char *line, const char *func, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - realbug(file, line, func, "POSSIBLE IMPLEMENTATION BUG; CONTACT ANDLABS:\n", format, ap); - va_end(ap); -} - -void _userbug(const char *file, const char *line, const char *func, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - realbug(file, line, func, "You have a bug: ", format, ap); - va_end(ap); -} diff --git a/src/libui_sdl/libui/common/matrix.c b/src/libui_sdl/libui/common/matrix.c deleted file mode 100644 index 676885d1..00000000 --- a/src/libui_sdl/libui/common/matrix.c +++ /dev/null @@ -1,50 +0,0 @@ -// 11 october 2015 -#include -#include "../ui.h" -#include "uipriv.h" - -void uiDrawMatrixSetIdentity(uiDrawMatrix *m) -{ - m->M11 = 1; - m->M12 = 0; - m->M21 = 0; - m->M22 = 1; - m->M31 = 0; - m->M32 = 0; -} - -// The rest of this file provides basic utilities in case the platform doesn't provide any of its own for these tasks. -// Keep these as minimal as possible. They should generally not call other fallbacks. - -// see https://msdn.microsoft.com/en-us/library/windows/desktop/ff684171%28v=vs.85%29.aspx#skew_transform -// TODO see if there's a way we can avoid the multiplication -void fallbackSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount) -{ - uiDrawMatrix n; - - uiDrawMatrixSetIdentity(&n); - // TODO explain this - n.M12 = tan(yamount); - n.M21 = tan(xamount); - n.M31 = -y * tan(xamount); - n.M32 = -x * tan(yamount); - uiDrawMatrixMultiply(m, &n); -} - -void scaleCenter(double xCenter, double yCenter, double *x, double *y) -{ - *x = xCenter - (*x * xCenter); - *y = yCenter - (*y * yCenter); -} - -// the basic algorithm is from cairo -// but it's the same algorithm as the transform point, just without M31 and M32 taken into account, so let's just do that instead -void fallbackTransformSize(uiDrawMatrix *m, double *x, double *y) -{ - uiDrawMatrix m2; - - m2 = *m; - m2.M31 = 0; - m2.M32 = 0; - uiDrawMatrixTransformPoint(&m2, x, y); -} diff --git a/src/libui_sdl/libui/common/shouldquit.c b/src/libui_sdl/libui/common/shouldquit.c deleted file mode 100644 index 4e7aa5c3..00000000 --- a/src/libui_sdl/libui/common/shouldquit.c +++ /dev/null @@ -1,22 +0,0 @@ -// 9 may 2015 -#include "../ui.h" -#include "uipriv.h" - -static int defaultOnShouldQuit(void *data) -{ - return 0; -} - -static int (*onShouldQuit)(void *) = defaultOnShouldQuit; -static void *onShouldQuitData; - -void uiOnShouldQuit(int (*f)(void *), void *data) -{ - onShouldQuit = f; - onShouldQuitData = data; -} - -int shouldQuit(void) -{ - return (*onShouldQuit)(onShouldQuitData); -} diff --git a/src/libui_sdl/libui/common/uipriv.h b/src/libui_sdl/libui/common/uipriv.h deleted file mode 100644 index d6b54e89..00000000 --- a/src/libui_sdl/libui/common/uipriv.h +++ /dev/null @@ -1,58 +0,0 @@ -// 6 april 2015 -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "controlsigs.h" - -extern uiInitOptions options; - -extern void *uiAlloc(size_t, const char *); -#define uiNew(T) ((T *) uiAlloc(sizeof (T), #T)) -extern void *uiRealloc(void *, size_t, const char *); -extern void uiFree(void *); - -// ugh, this was only introduced in MSVC 2015... -#ifdef _MSC_VER -#define __func__ __FUNCTION__ -#endif -extern void realbug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap); -#define _ns2(s) #s -#define _ns(s) _ns2(s) -extern void _implbug(const char *file, const char *line, const char *func, const char *format, ...); -#define implbug(...) _implbug(__FILE__, _ns(__LINE__), __func__, __VA_ARGS__) -extern void _userbug(const char *file, const char *line, const char *func, const char *format, ...); -#define userbug(...) _userbug(__FILE__, _ns(__LINE__), __func__, __VA_ARGS__) - -// control.c -extern uiControl *newControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr); - -// shouldquit.c -extern int shouldQuit(void); - -// areaevents.c -typedef struct clickCounter clickCounter; -// you should call Reset() to zero-initialize a new instance -// it doesn't matter that all the non-count fields are zero: the first click will fail the curButton test straightaway, so it'll return 1 and set the rest of the structure accordingly -struct clickCounter { - int curButton; - int rectX0; - int rectY0; - int rectX1; - int rectY1; - uintptr_t prevTime; - int count; -}; -int clickCounterClick(clickCounter *c, int button, int x, int y, uintptr_t time, uintptr_t maxTime, int32_t xdist, int32_t ydist); -extern void clickCounterReset(clickCounter *); -extern int fromScancode(uintptr_t, uiAreaKeyEvent *); - -// matrix.c -extern void fallbackSkew(uiDrawMatrix *, double, double, double, double); -extern void scaleCenter(double, double, double *, double *); -extern void fallbackTransformSize(uiDrawMatrix *, double *, double *); - -#ifdef __cplusplus -} -#endif diff --git a/src/libui_sdl/libui/common/userbugs.c b/src/libui_sdl/libui/common/userbugs.c deleted file mode 100644 index 0a85874c..00000000 --- a/src/libui_sdl/libui/common/userbugs.c +++ /dev/null @@ -1,8 +0,0 @@ -// 22 may 2016 -#include "../ui.h" -#include "uipriv.h" - -void uiUserBugCannotSetParentOnToplevel(const char *type) -{ - userbug("You cannot make a %s a child of another uiControl,", type); -} diff --git a/src/libui_sdl/libui/darwin/CMakeLists.txt b/src/libui_sdl/libui/darwin/CMakeLists.txt deleted file mode 100644 index dbef5d43..00000000 --- a/src/libui_sdl/libui/darwin/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -# 3 june 2016 - -list(APPEND _LIBUI_SOURCES - darwin/alloc.m - darwin/area.m - darwin/areaevents.m - darwin/autolayout.m - darwin/box.m - darwin/button.m - darwin/checkbox.m - darwin/colorbutton.m - darwin/combobox.m - darwin/control.m - darwin/datetimepicker.m - darwin/debug.m - darwin/draw.m - darwin/drawtext.m - darwin/editablecombo.m - darwin/entry.m - darwin/fontbutton.m - darwin/form.m - darwin/grid.m - darwin/group.m - darwin/image.m - darwin/label.m - darwin/main.m - darwin/map.m - darwin/menu.m - darwin/multilineentry.m - darwin/progressbar.m - darwin/radiobuttons.m - darwin/scrollview.m - darwin/separator.m - darwin/slider.m - darwin/spinbox.m - darwin/stddialogs.m - darwin/tab.m - darwin/text.m - darwin/util.m - darwin/window.m - darwin/winmoveresize.m -) -set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) - -list(APPEND _LIBUI_INCLUDEDIRS - darwin -) -set(_LIBUI_INCLUDEDIRS _LIBUI_INCLUDEDIRS PARENT_SCOPE) - -set(_LIBUINAME libui PARENT_SCOPE) -if(NOT BUILD_SHARED_LIBS) - set(_LIBUINAME libui-temporary PARENT_SCOPE) -endif() -# thanks to Mr-Hide in irc.freenode.net/#cmake -macro(_handle_static) - set_target_properties(${_LIBUINAME} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") - set(_aname $) - set(_lname libui-combined.list) - set(_oname libui-combined.o) - add_custom_command( - OUTPUT ${_oname} - COMMAND - nm -m ${_aname} | sed -E -n "'s/^[0-9a-f]* \\([A-Z_]+,[a-z_]+\\) external //p'" > ${_lname} - COMMAND - ld -exported_symbols_list ${_lname} -r -all_load ${_aname} -o ${_oname} - COMMENT "Removing hidden symbols") - add_library(libui STATIC ${_oname}) - # otherwise cmake won't know which linker to use - set_target_properties(libui PROPERTIES - LINKER_LANGUAGE C) - set(_aname) - set(_lname) - set(_oname) -endmacro() - -set(_LIBUI_LIBS - objc "-framework Foundation" "-framework AppKit" -PARENT_SCOPE) diff --git a/src/libui_sdl/libui/darwin/alloc.m b/src/libui_sdl/libui/darwin/alloc.m deleted file mode 100644 index e271b90e..00000000 --- a/src/libui_sdl/libui/darwin/alloc.m +++ /dev/null @@ -1,89 +0,0 @@ -// 4 december 2014 -#import -#import "uipriv_darwin.h" - -static NSMutableArray *allocations; -NSMutableArray *delegates; - -void initAlloc(void) -{ - allocations = [NSMutableArray new]; - delegates = [NSMutableArray new]; -} - -#define UINT8(p) ((uint8_t *) (p)) -#define PVOID(p) ((void *) (p)) -#define EXTRA (sizeof (size_t) + sizeof (const char **)) -#define DATA(p) PVOID(UINT8(p) + EXTRA) -#define BASE(p) PVOID(UINT8(p) - EXTRA) -#define SIZE(p) ((size_t *) (p)) -#define CCHAR(p) ((const char **) (p)) -#define TYPE(p) CCHAR(UINT8(p) + sizeof (size_t)) - -void uninitAlloc(void) -{ - NSMutableString *str; - NSValue *v; - - [delegates release]; - if ([allocations count] == 0) { - [allocations release]; - return; - } - str = [NSMutableString new]; - for (v in allocations) { - void *ptr; - - ptr = [v pointerValue]; - [str appendString:[NSString stringWithFormat:@"%p %s\n", ptr, *TYPE(ptr)]]; - } - userbug("Some data was leaked; either you left a uiControl lying around or there's a bug in libui itself. Leaked data:\n%s", [str UTF8String]); - [str release]; -} - -void *uiAlloc(size_t size, const char *type) -{ - void *out; - - out = malloc(EXTRA + size); - if (out == NULL) { - fprintf(stderr, "memory exhausted in uiAlloc()\n"); - abort(); - } - memset(DATA(out), 0, size); - *SIZE(out) = size; - *TYPE(out) = type; - [allocations addObject:[NSValue valueWithPointer:out]]; - return DATA(out); -} - -void *uiRealloc(void *p, size_t new, const char *type) -{ - void *out; - size_t *s; - - if (p == NULL) - return uiAlloc(new, type); - p = BASE(p); - out = realloc(p, EXTRA + new); - if (out == NULL) { - fprintf(stderr, "memory exhausted in uiRealloc()\n"); - abort(); - } - s = SIZE(out); - if (new <= *s) - memset(((uint8_t *) DATA(out)) + *s, 0, new - *s); - *s = new; - [allocations removeObject:[NSValue valueWithPointer:p]]; - [allocations addObject:[NSValue valueWithPointer:out]]; - return DATA(out); -} - -void uiFree(void *p) -{ - if (p == NULL) - implbug("attempt to uiFree(NULL)"); - p = BASE(p); - free(p); - [allocations removeObject:[NSValue valueWithPointer:p]]; -} diff --git a/src/libui_sdl/libui/darwin/area.m b/src/libui_sdl/libui/darwin/area.m deleted file mode 100644 index 23162e6c..00000000 --- a/src/libui_sdl/libui/darwin/area.m +++ /dev/null @@ -1,475 +0,0 @@ -// 9 september 2015 -#import "uipriv_darwin.h" - -// 10.8 fixups -#define NSEventModifierFlags NSUInteger - -@interface areaView : NSView { - uiArea *libui_a; - NSTrackingArea *libui_ta; - NSSize libui_ss; - BOOL libui_enabled; -} -- (id)initWithFrame:(NSRect)r area:(uiArea *)a; -- (uiModifiers)parseModifiers:(NSEvent *)e; -- (void)doMouseEvent:(NSEvent *)e; -- (int)sendKeyEvent:(uiAreaKeyEvent *)ke; -- (int)doKeyDownUp:(NSEvent *)e up:(int)up; -- (int)doKeyDown:(NSEvent *)e; -- (int)doKeyUp:(NSEvent *)e; -- (int)doFlagsChanged:(NSEvent *)e; -- (void)setupNewTrackingArea; -- (void)setScrollingSize:(NSSize)s; -- (BOOL)isEnabled; -- (void)setEnabled:(BOOL)e; -@end - -struct uiArea { - uiDarwinControl c; - NSView *view; // either sv or area depending on whether it is scrolling - NSScrollView *sv; - areaView *area; - struct scrollViewData *d; - uiAreaHandler *ah; - BOOL scrolling; - NSEvent *dragevent; -}; - -@implementation areaView - -- (id)initWithFrame:(NSRect)r area:(uiArea *)a -{ - self = [super initWithFrame:r]; - if (self) { - self->libui_a = a; - [self setupNewTrackingArea]; - self->libui_ss = r.size; - self->libui_enabled = YES; - } - return self; -} - -- (void)drawRect:(NSRect)r -{ - uiArea *a = self->libui_a; - CGContextRef c; - uiAreaDrawParams dp; - - c = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; - // see draw.m under text for why we need the height - dp.Context = newContext(c, [self bounds].size.height); - - dp.AreaWidth = 0; - dp.AreaHeight = 0; - if (!a->scrolling) { - dp.AreaWidth = [self frame].size.width; - dp.AreaHeight = [self frame].size.height; - } - - dp.ClipX = r.origin.x; - dp.ClipY = r.origin.y; - dp.ClipWidth = r.size.width; - dp.ClipHeight = r.size.height; - - // no need to save or restore the graphics state to reset transformations; Cocoa creates a brand-new context each time - (*(a->ah->Draw))(a->ah, a, &dp); - - freeContext(dp.Context); -} - -- (BOOL)isFlipped -{ - return YES; -} - -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -- (uiModifiers)parseModifiers:(NSEvent *)e -{ - NSEventModifierFlags mods; - uiModifiers m; - - m = 0; - mods = [e modifierFlags]; - if ((mods & NSControlKeyMask) != 0) - m |= uiModifierCtrl; - if ((mods & NSAlternateKeyMask) != 0) - m |= uiModifierAlt; - if ((mods & NSShiftKeyMask) != 0) - m |= uiModifierShift; - if ((mods & NSCommandKeyMask) != 0) - m |= uiModifierSuper; - return m; -} - -- (void)setupNewTrackingArea -{ - self->libui_ta = [[NSTrackingArea alloc] initWithRect:[self bounds] - options:(NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveAlways | - NSTrackingInVisibleRect | - NSTrackingEnabledDuringMouseDrag) - owner:self - userInfo:nil]; - [self addTrackingArea:self->libui_ta]; -} - -- (void)updateTrackingAreas -{ - [self removeTrackingArea:self->libui_ta]; - [self->libui_ta release]; - [self setupNewTrackingArea]; -} - -// capture on drag is done automatically on OS X -- (void)doMouseEvent:(NSEvent *)e -{ - uiArea *a = self->libui_a; - uiAreaMouseEvent me; - NSPoint point; - int buttonNumber; - NSUInteger pmb; - unsigned int i, max; - - // this will convert point to drawing space - // thanks swillits in irc.freenode.net/#macdev - point = [self convertPoint:[e locationInWindow] fromView:nil]; - me.X = point.x; - me.Y = point.y; - - me.AreaWidth = 0; - me.AreaHeight = 0; - if (!a->scrolling) { - me.AreaWidth = [self frame].size.width; - me.AreaHeight = [self frame].size.height; - } - - buttonNumber = [e buttonNumber] + 1; - // swap button numbers 2 and 3 (right and middle) - if (buttonNumber == 2) - buttonNumber = 3; - else if (buttonNumber == 3) - buttonNumber = 2; - - me.Down = 0; - me.Up = 0; - me.Count = 0; - switch ([e type]) { - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - me.Down = buttonNumber; - me.Count = [e clickCount]; - break; - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - me.Up = buttonNumber; - break; - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - // we include the button that triggered the dragged event in the Held fields - buttonNumber = 0; - break; - } - - me.Modifiers = [self parseModifiers:e]; - - pmb = [NSEvent pressedMouseButtons]; - me.Held1To64 = 0; - if (buttonNumber != 1 && (pmb & 1) != 0) - me.Held1To64 |= 1; - if (buttonNumber != 2 && (pmb & 4) != 0) - me.Held1To64 |= 2; - if (buttonNumber != 3 && (pmb & 2) != 0) - me.Held1To64 |= 4; - // buttons 4..32 - // https://developer.apple.com/library/mac/documentation/Carbon/Reference/QuartzEventServicesRef/index.html#//apple_ref/c/tdef/CGMouseButton says Quartz only supports up to 32 buttons - max = 32; - for (i = 4; i <= max; i++) { - uint64_t j; - - if (buttonNumber == i) - continue; - j = 1 << (i - 1); - if ((pmb & j) != 0) - me.Held1To64 |= j; - } - - if (self->libui_enabled) { - // and allow dragging here - a->dragevent = e; - (*(a->ah->MouseEvent))(a->ah, a, &me); - a->dragevent = nil; - } -} - -#define mouseEvent(name) \ - - (void)name:(NSEvent *)e \ - { \ - [self doMouseEvent:e]; \ - } -mouseEvent(mouseMoved) -mouseEvent(mouseDragged) -mouseEvent(rightMouseDragged) -mouseEvent(otherMouseDragged) -mouseEvent(mouseDown) -mouseEvent(rightMouseDown) -mouseEvent(otherMouseDown) -mouseEvent(mouseUp) -mouseEvent(rightMouseUp) -mouseEvent(otherMouseUp) - -- (void)mouseEntered:(NSEvent *)e -{ - uiArea *a = self->libui_a; - - if (self->libui_enabled) - (*(a->ah->MouseCrossed))(a->ah, a, 0); -} - -- (void)mouseExited:(NSEvent *)e -{ - uiArea *a = self->libui_a; - - if (self->libui_enabled) - (*(a->ah->MouseCrossed))(a->ah, a, 1); -} - -// note: there is no equivalent to WM_CAPTURECHANGED on Mac OS X; there literally is no way to break a grab like that -// even if I invoke the task switcher and switch processes, the mouse grab will still be held until I let go of all buttons -// therefore, no DragBroken() - -- (int)sendKeyEvent:(uiAreaKeyEvent *)ke -{ - uiArea *a = self->libui_a; - - return (*(a->ah->KeyEvent))(a->ah, a, ke); -} - -- (int)doKeyDownUp:(NSEvent *)e up:(int)up -{ - uiAreaKeyEvent ke; - - ke.Key = 0; - ke.ExtKey = 0; - ke.Modifier = 0; - - ke.Modifiers = [self parseModifiers:e]; - - ke.Up = up; - - if (!fromKeycode([e keyCode], &ke)) - return 0; - return [self sendKeyEvent:&ke]; -} - -- (int)doKeyDown:(NSEvent *)e -{ - return [self doKeyDownUp:e up:0]; -} - -- (int)doKeyUp:(NSEvent *)e -{ - return [self doKeyDownUp:e up:1]; -} - -- (int)doFlagsChanged:(NSEvent *)e -{ - uiAreaKeyEvent ke; - uiModifiers whichmod; - - ke.Key = 0; - ke.ExtKey = 0; - - // Mac OS X sends this event on both key up and key down. - // Fortunately -[e keyCode] IS valid here, so we can simply map from key code to Modifiers, get the value of [e modifierFlags], and check if the respective bit is set or not — that will give us the up/down state - if (!keycodeModifier([e keyCode], &whichmod)) - return 0; - ke.Modifier = whichmod; - ke.Modifiers = [self parseModifiers:e]; - ke.Up = (ke.Modifiers & ke.Modifier) == 0; - // and then drop the current modifier from Modifiers - ke.Modifiers &= ~ke.Modifier; - return [self sendKeyEvent:&ke]; -} - -- (void)setFrameSize:(NSSize)size -{ - uiArea *a = self->libui_a; - - [super setFrameSize:size]; - if (!a->scrolling) - // we must redraw everything on resize because Windows requires it - [self setNeedsDisplay:YES]; -} - -// TODO does this update the frame? -- (void)setScrollingSize:(NSSize)s -{ - self->libui_ss = s; - [self invalidateIntrinsicContentSize]; -} - -- (NSSize)intrinsicContentSize -{ - if (!self->libui_a->scrolling) - return [super intrinsicContentSize]; - return self->libui_ss; -} - -- (BOOL)becomeFirstResponder -{ - return [self isEnabled]; -} - -- (BOOL)isEnabled -{ - return self->libui_enabled; -} - -- (void)setEnabled:(BOOL)e -{ - self->libui_enabled = e; - if (!self->libui_enabled && [self window] != nil) - if ([[self window] firstResponder] == self) - [[self window] makeFirstResponder:nil]; -} - -@end - -uiDarwinControlAllDefaultsExceptDestroy(uiArea, view) - -static void uiAreaDestroy(uiControl *c) -{ - uiArea *a = uiArea(c); - - if (a->scrolling) - scrollViewFreeData(a->sv, a->d); - [a->area release]; - if (a->scrolling) - [a->sv release]; - uiFreeControl(uiControl(a)); -} - -// called by subclasses of -[NSApplication sendEvent:] -// by default, NSApplication eats some key events -// this prevents that from happening with uiArea -// see http://stackoverflow.com/questions/24099063/how-do-i-detect-keyup-in-my-nsview-with-the-command-key-held and http://lists.apple.com/archives/cocoa-dev/2003/Oct/msg00442.html -int sendAreaEvents(NSEvent *e) -{ - NSEventType type; - id focused; - areaView *view; - - type = [e type]; - if (type != NSKeyDown && type != NSKeyUp && type != NSFlagsChanged) - return 0; - focused = [[e window] firstResponder]; - if (focused == nil) - return 0; - if (![focused isKindOfClass:[areaView class]]) - return 0; - view = (areaView *) focused; - switch (type) { - case NSKeyDown: - return [view doKeyDown:e]; - case NSKeyUp: - return [view doKeyUp:e]; - case NSFlagsChanged: - return [view doFlagsChanged:e]; - } - return 0; -} - -void uiAreaSetSize(uiArea *a, int width, int height) -{ - if (!a->scrolling) - userbug("You cannot call uiAreaSetSize() on a non-scrolling uiArea. (area: %p)", a); - [a->area setScrollingSize:NSMakeSize(width, height)]; -} - -void uiAreaQueueRedrawAll(uiArea *a) -{ - [a->area setNeedsDisplay:YES]; -} - -void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height) -{ - if (!a->scrolling) - userbug("You cannot call uiAreaScrollTo() on a non-scrolling uiArea. (area: %p)", a); - [a->area scrollRectToVisible:NSMakeRect(x, y, width, height)]; - // don't worry about the return value; it just says whether scrolling was needed -} - -void uiAreaBeginUserWindowMove(uiArea *a) -{ - libuiNSWindow *w; - - w = (libuiNSWindow *) [a->area window]; - if (w == nil) - return; // TODO - if (a->dragevent == nil) - return; // TODO - [w libui_doMove:a->dragevent]; -} - -void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge) -{ - libuiNSWindow *w; - - w = (libuiNSWindow *) [a->area window]; - if (w == nil) - return; // TODO - if (a->dragevent == nil) - return; // TODO - [w libui_doResize:a->dragevent on:edge]; -} - -uiArea *uiNewArea(uiAreaHandler *ah) -{ - uiArea *a; - - uiDarwinNewControl(uiArea, a); - - a->ah = ah; - a->scrolling = NO; - - a->area = [[areaView alloc] initWithFrame:NSZeroRect area:a]; - - a->view = a->area; - - return a; -} - -uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height) -{ - uiArea *a; - struct scrollViewCreateParams p; - - uiDarwinNewControl(uiArea, a); - - a->ah = ah; - a->scrolling = YES; - - a->area = [[areaView alloc] initWithFrame:NSMakeRect(0, 0, width, height) - area:a]; - - memset(&p, 0, sizeof (struct scrollViewCreateParams)); - p.DocumentView = a->area; - p.BackgroundColor = [NSColor controlColor]; - p.DrawsBackground = 1; - p.Bordered = NO; - p.HScroll = YES; - p.VScroll = YES; - a->sv = mkScrollView(&p, &(a->d)); - - a->view = a->sv; - - return a; -} diff --git a/src/libui_sdl/libui/darwin/areaevents.m b/src/libui_sdl/libui/darwin/areaevents.m deleted file mode 100644 index d7ceaaad..00000000 --- a/src/libui_sdl/libui/darwin/areaevents.m +++ /dev/null @@ -1,159 +0,0 @@ -// 30 march 2014 -#import "uipriv_darwin.h" - -/* -Mac OS X uses its own set of hardware key codes that are different from PC keyboard scancodes, but are positional (like PC keyboard scancodes). These are defined in , a Carbon header. As far as I can tell, there's no way to include this header without either using an absolute path or linking Carbon into the program, so the constant values are used here instead. - -The Cocoa docs do guarantee that -[NSEvent keyCode] results in key codes that are the same as those returned by Carbon; that is, these codes. -*/ - -// use uintptr_t to be safe -static const struct { - uintptr_t keycode; - char equiv; -} keycodeKeys[] = { - { 0x00, 'a' }, - { 0x01, 's' }, - { 0x02, 'd' }, - { 0x03, 'f' }, - { 0x04, 'h' }, - { 0x05, 'g' }, - { 0x06, 'z' }, - { 0x07, 'x' }, - { 0x08, 'c' }, - { 0x09, 'v' }, - { 0x0B, 'b' }, - { 0x0C, 'q' }, - { 0x0D, 'w' }, - { 0x0E, 'e' }, - { 0x0F, 'r' }, - { 0x10, 'y' }, - { 0x11, 't' }, - { 0x12, '1' }, - { 0x13, '2' }, - { 0x14, '3' }, - { 0x15, '4' }, - { 0x16, '6' }, - { 0x17, '5' }, - { 0x18, '=' }, - { 0x19, '9' }, - { 0x1A, '7' }, - { 0x1B, '-' }, - { 0x1C, '8' }, - { 0x1D, '0' }, - { 0x1E, ']' }, - { 0x1F, 'o' }, - { 0x20, 'u' }, - { 0x21, '[' }, - { 0x22, 'i' }, - { 0x23, 'p' }, - { 0x25, 'l' }, - { 0x26, 'j' }, - { 0x27, '\'' }, - { 0x28, 'k' }, - { 0x29, ';' }, - { 0x2A, '\\' }, - { 0x2B, ',' }, - { 0x2C, '/' }, - { 0x2D, 'n' }, - { 0x2E, 'm' }, - { 0x2F, '.' }, - { 0x32, '`' }, - { 0x24, '\n' }, - { 0x30, '\t' }, - { 0x31, ' ' }, - { 0x33, '\b' }, - { 0xFFFF, 0 }, -}; - -static const struct { - uintptr_t keycode; - uiExtKey equiv; -} keycodeExtKeys[] = { - { 0x41, uiExtKeyNDot }, - { 0x43, uiExtKeyNMultiply }, - { 0x45, uiExtKeyNAdd }, - { 0x4B, uiExtKeyNDivide }, - { 0x4C, uiExtKeyNEnter }, - { 0x4E, uiExtKeyNSubtract }, - { 0x52, uiExtKeyN0 }, - { 0x53, uiExtKeyN1 }, - { 0x54, uiExtKeyN2 }, - { 0x55, uiExtKeyN3 }, - { 0x56, uiExtKeyN4 }, - { 0x57, uiExtKeyN5 }, - { 0x58, uiExtKeyN6 }, - { 0x59, uiExtKeyN7 }, - { 0x5B, uiExtKeyN8 }, - { 0x5C, uiExtKeyN9 }, - { 0x35, uiExtKeyEscape }, - { 0x60, uiExtKeyF5 }, - { 0x61, uiExtKeyF6 }, - { 0x62, uiExtKeyF7 }, - { 0x63, uiExtKeyF3 }, - { 0x64, uiExtKeyF8 }, - { 0x65, uiExtKeyF9 }, - { 0x67, uiExtKeyF11 }, - { 0x6D, uiExtKeyF10 }, - { 0x6F, uiExtKeyF12 }, - { 0x72, uiExtKeyInsert }, // listed as the Help key but it's in the same position on an Apple keyboard as the Insert key on a Windows keyboard; thanks to SeanieB from irc.badnik.net and Psy in irc.freenode.net/#macdev for confirming they have the same code - { 0x73, uiExtKeyHome }, - { 0x74, uiExtKeyPageUp }, - { 0x75, uiExtKeyDelete }, - { 0x76, uiExtKeyF4 }, - { 0x77, uiExtKeyEnd }, - { 0x78, uiExtKeyF2 }, - { 0x79, uiExtKeyPageDown }, - { 0x7A, uiExtKeyF1 }, - { 0x7B, uiExtKeyLeft }, - { 0x7C, uiExtKeyRight }, - { 0x7D, uiExtKeyDown }, - { 0x7E, uiExtKeyUp }, - { 0xFFFF, 0 }, -}; - -static const struct { - uintptr_t keycode; - uiModifiers equiv; -} keycodeModifiers[] = { - { 0x37, uiModifierSuper }, // left command - { 0x38, uiModifierShift }, // left shift - { 0x3A, uiModifierAlt }, // left option - { 0x3B, uiModifierCtrl }, // left control - { 0x3C, uiModifierShift }, // right shift - { 0x3D, uiModifierAlt }, // right alt - { 0x3E, uiModifierCtrl }, // right control - // the following is not in Events.h for some reason - // thanks to Nicole and jedivulcan from irc.badnik.net - { 0x36, uiModifierSuper }, // right command - { 0xFFFF, 0 }, -}; - -BOOL fromKeycode(unsigned short keycode, uiAreaKeyEvent *ke) -{ - int i; - - for (i = 0; keycodeKeys[i].keycode != 0xFFFF; i++) - if (keycodeKeys[i].keycode == keycode) { - ke->Key = keycodeKeys[i].equiv; - return YES; - } - for (i = 0; keycodeExtKeys[i].keycode != 0xFFFF; i++) - if (keycodeExtKeys[i].keycode == keycode) { - ke->ExtKey = keycodeExtKeys[i].equiv; - return YES; - } - return NO; -} - -BOOL keycodeModifier(unsigned short keycode, uiModifiers *mod) -{ - int i; - - for (i = 0; keycodeModifiers[i].keycode != 0xFFFF; i++) - if (keycodeModifiers[i].keycode == keycode) { - *mod = keycodeModifiers[i].equiv; - return YES; - } - return NO; -} diff --git a/src/libui_sdl/libui/darwin/autolayout.m b/src/libui_sdl/libui/darwin/autolayout.m deleted file mode 100644 index 9964155f..00000000 --- a/src/libui_sdl/libui/darwin/autolayout.m +++ /dev/null @@ -1,161 +0,0 @@ -// 15 august 2015 -#import "uipriv_darwin.h" - -NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc) -{ - NSLayoutConstraint *constraint; - - constraint = [NSLayoutConstraint constraintWithItem:view1 - attribute:attr1 - relatedBy:relation - toItem:view2 - attribute:attr2 - multiplier:multiplier - constant:c]; - // apparently only added in 10.9 - if ([constraint respondsToSelector:@selector(setIdentifier:)]) - [((id) constraint) setIdentifier:desc]; - return constraint; -} - -CGFloat uiDarwinMarginAmount(void *reserved) -{ - return 20.0; -} - -CGFloat uiDarwinPaddingAmount(void *reserved) -{ - return 8.0; -} - -// this is needed for NSSplitView to work properly; see http://stackoverflow.com/questions/34574478/how-can-i-set-the-position-of-a-nssplitview-nowadays-setpositionofdivideratind (stal in irc.freenode.net/#macdev came up with the exact combination) -// turns out it also works on NSTabView and NSBox too, possibly others! -// and for bonus points, it even seems to fix unsatisfiable-constraint-autoresizing-mask issues with NSTabView and NSBox too!!! this is nuts -void jiggleViewLayout(NSView *view) -{ - [view setNeedsLayout:YES]; - [view layoutSubtreeIfNeeded]; -} - -static CGFloat margins(int margined) -{ - if (!margined) - return 0.0; - return uiDarwinMarginAmount(NULL); -} - -void singleChildConstraintsEstablish(struct singleChildConstraints *c, NSView *contentView, NSView *childView, BOOL hugsTrailing, BOOL hugsBottom, int margined, NSString *desc) -{ - CGFloat margin; - - margin = margins(margined); - - c->leadingConstraint = mkConstraint(contentView, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - childView, NSLayoutAttributeLeading, - 1, -margin, - [desc stringByAppendingString:@" leading constraint"]); - [contentView addConstraint:c->leadingConstraint]; - [c->leadingConstraint retain]; - - c->topConstraint = mkConstraint(contentView, NSLayoutAttributeTop, - NSLayoutRelationEqual, - childView, NSLayoutAttributeTop, - 1, -margin, - [desc stringByAppendingString:@" top constraint"]); - [contentView addConstraint:c->topConstraint]; - [c->topConstraint retain]; - - c->trailingConstraintGreater = mkConstraint(contentView, NSLayoutAttributeTrailing, - NSLayoutRelationGreaterThanOrEqual, - childView, NSLayoutAttributeTrailing, - 1, margin, - [desc stringByAppendingString:@" trailing >= constraint"]); - if (hugsTrailing) - [c->trailingConstraintGreater setPriority:NSLayoutPriorityDefaultLow]; - [contentView addConstraint:c->trailingConstraintGreater]; - [c->trailingConstraintGreater retain]; - - c->trailingConstraintEqual = mkConstraint(contentView, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - childView, NSLayoutAttributeTrailing, - 1, margin, - [desc stringByAppendingString:@" trailing == constraint"]); - if (!hugsTrailing) - [c->trailingConstraintEqual setPriority:NSLayoutPriorityDefaultLow]; - [contentView addConstraint:c->trailingConstraintEqual]; - [c->trailingConstraintEqual retain]; - - c->bottomConstraintGreater = mkConstraint(contentView, NSLayoutAttributeBottom, - NSLayoutRelationGreaterThanOrEqual, - childView, NSLayoutAttributeBottom, - 1, margin, - [desc stringByAppendingString:@" bottom >= constraint"]); - if (hugsBottom) - [c->bottomConstraintGreater setPriority:NSLayoutPriorityDefaultLow]; - [contentView addConstraint:c->bottomConstraintGreater]; - [c->bottomConstraintGreater retain]; - - c->bottomConstraintEqual = mkConstraint(contentView, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - childView, NSLayoutAttributeBottom, - 1, margin, - [desc stringByAppendingString:@" bottom == constraint"]); - if (!hugsBottom) - [c->bottomConstraintEqual setPriority:NSLayoutPriorityDefaultLow]; - [contentView addConstraint:c->bottomConstraintEqual]; - [c->bottomConstraintEqual retain]; -} - -void singleChildConstraintsRemove(struct singleChildConstraints *c, NSView *cv) -{ - if (c->leadingConstraint != nil) { - [cv removeConstraint:c->leadingConstraint]; - [c->leadingConstraint release]; - c->leadingConstraint = nil; - } - if (c->topConstraint != nil) { - [cv removeConstraint:c->topConstraint]; - [c->topConstraint release]; - c->topConstraint = nil; - } - if (c->trailingConstraintGreater != nil) { - [cv removeConstraint:c->trailingConstraintGreater]; - [c->trailingConstraintGreater release]; - c->trailingConstraintGreater = nil; - } - if (c->trailingConstraintEqual != nil) { - [cv removeConstraint:c->trailingConstraintEqual]; - [c->trailingConstraintEqual release]; - c->trailingConstraintEqual = nil; - } - if (c->bottomConstraintGreater != nil) { - [cv removeConstraint:c->bottomConstraintGreater]; - [c->bottomConstraintGreater release]; - c->bottomConstraintGreater = nil; - } - if (c->bottomConstraintEqual != nil) { - [cv removeConstraint:c->bottomConstraintEqual]; - [c->bottomConstraintEqual release]; - c->bottomConstraintEqual = nil; - } -} - -void singleChildConstraintsSetMargined(struct singleChildConstraints *c, int margined) -{ - CGFloat margin; - - margin = margins(margined); - if (c->leadingConstraint != nil) - [c->leadingConstraint setConstant:-margin]; - if (c->topConstraint != nil) - [c->topConstraint setConstant:-margin]; - if (c->trailingConstraintGreater != nil) - [c->trailingConstraintGreater setConstant:margin]; - if (c->trailingConstraintEqual != nil) - [c->trailingConstraintEqual setConstant:margin]; - if (c->bottomConstraintGreater != nil) - [c->bottomConstraintGreater setConstant:margin]; - if (c->bottomConstraintEqual != nil) - [c->bottomConstraintEqual setConstant:margin]; -} diff --git a/src/libui_sdl/libui/darwin/box.m b/src/libui_sdl/libui/darwin/box.m deleted file mode 100644 index 18d536d5..00000000 --- a/src/libui_sdl/libui/darwin/box.m +++ /dev/null @@ -1,469 +0,0 @@ -// 15 august 2015 -#import "uipriv_darwin.h" - -// TODO hiding all stretchy controls still hugs trailing edge - -@interface boxChild : NSObject -@property uiControl *c; -@property BOOL stretchy; -@property NSLayoutPriority oldPrimaryHuggingPri; -@property NSLayoutPriority oldSecondaryHuggingPri; -- (NSView *)view; -@end - -@interface boxView : NSView { - uiBox *b; - NSMutableArray *children; - BOOL vertical; - int padded; - - NSLayoutConstraint *first; - NSMutableArray *inBetweens; - NSLayoutConstraint *last; - NSMutableArray *otherConstraints; - - NSLayoutAttribute primaryStart; - NSLayoutAttribute primaryEnd; - NSLayoutAttribute secondaryStart; - NSLayoutAttribute secondaryEnd; - NSLayoutAttribute primarySize; - NSLayoutConstraintOrientation primaryOrientation; - NSLayoutConstraintOrientation secondaryOrientation; -} -- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb; -- (void)onDestroy; -- (void)removeOurConstraints; -- (void)syncEnableStates:(int)enabled; -- (CGFloat)paddingAmount; -- (void)establishOurConstraints; -- (void)append:(uiControl *)c stretchy:(int)stretchy; -- (void)delete:(int)n; -- (int)isPadded; -- (void)setPadded:(int)p; -- (BOOL)hugsTrailing; -- (BOOL)hugsBottom; -- (int)nStretchy; -@end - -struct uiBox { - uiDarwinControl c; - boxView *view; -}; - -@implementation boxChild - -- (NSView *)view -{ - return (NSView *) uiControlHandle(self.c); -} - -@end - -@implementation boxView - -- (id)initWithVertical:(BOOL)vert b:(uiBox *)bb -{ - self = [super initWithFrame:NSZeroRect]; - if (self != nil) { - // the weird names vert and bb are to shut the compiler up about shadowing because implicit this/self is stupid - self->b = bb; - self->vertical = vert; - self->padded = 0; - self->children = [NSMutableArray new]; - - self->inBetweens = [NSMutableArray new]; - self->otherConstraints = [NSMutableArray new]; - - if (self->vertical) { - self->primaryStart = NSLayoutAttributeTop; - self->primaryEnd = NSLayoutAttributeBottom; - self->secondaryStart = NSLayoutAttributeLeading; - self->secondaryEnd = NSLayoutAttributeTrailing; - self->primarySize = NSLayoutAttributeHeight; - self->primaryOrientation = NSLayoutConstraintOrientationVertical; - self->secondaryOrientation = NSLayoutConstraintOrientationHorizontal; - } else { - self->primaryStart = NSLayoutAttributeLeading; - self->primaryEnd = NSLayoutAttributeTrailing; - self->secondaryStart = NSLayoutAttributeTop; - self->secondaryEnd = NSLayoutAttributeBottom; - self->primarySize = NSLayoutAttributeWidth; - self->primaryOrientation = NSLayoutConstraintOrientationHorizontal; - self->secondaryOrientation = NSLayoutConstraintOrientationVertical; - } - } - return self; -} - -- (void)onDestroy -{ - boxChild *bc; - - [self removeOurConstraints]; - [self->inBetweens release]; - [self->otherConstraints release]; - - for (bc in self->children) { - uiControlSetParent(bc.c, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil); - uiControlDestroy(bc.c); - } - [self->children release]; -} - -- (void)removeOurConstraints -{ - if (self->first != nil) { - [self removeConstraint:self->first]; - [self->first release]; - self->first = nil; - } - if ([self->inBetweens count] != 0) { - [self removeConstraints:self->inBetweens]; - [self->inBetweens removeAllObjects]; - } - if (self->last != nil) { - [self removeConstraint:self->last]; - [self->last release]; - self->last = nil; - } - if ([self->otherConstraints count] != 0) { - [self removeConstraints:self->otherConstraints]; - [self->otherConstraints removeAllObjects]; - } -} - -- (void)syncEnableStates:(int)enabled -{ - boxChild *bc; - - for (bc in self->children) - uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), enabled); -} - -- (CGFloat)paddingAmount -{ - if (!self->padded) - return 0.0; - return uiDarwinPaddingAmount(NULL); -} - -- (void)establishOurConstraints -{ - boxChild *bc; - CGFloat padding; - NSView *prev; - NSLayoutConstraint *c; - BOOL (*hugsSecondary)(uiDarwinControl *); - - [self removeOurConstraints]; - if ([self->children count] == 0) - return; - padding = [self paddingAmount]; - - // first arrange in the primary direction - prev = nil; - for (bc in self->children) { - if (!uiControlVisible(bc.c)) - continue; - if (prev == nil) { // first view - self->first = mkConstraint(self, self->primaryStart, - NSLayoutRelationEqual, - [bc view], self->primaryStart, - 1, 0, - @"uiBox first primary constraint"); - [self addConstraint:self->first]; - [self->first retain]; - prev = [bc view]; - continue; - } - // not the first; link it - c = mkConstraint(prev, self->primaryEnd, - NSLayoutRelationEqual, - [bc view], self->primaryStart, - 1, -padding, - @"uiBox in-between primary constraint"); - [self addConstraint:c]; - [self->inBetweens addObject:c]; - prev = [bc view]; - } - if (prev == nil) // no control visible; act as if no controls - return; - self->last = mkConstraint(prev, self->primaryEnd, - NSLayoutRelationEqual, - self, self->primaryEnd, - 1, 0, - @"uiBox last primary constraint"); - [self addConstraint:self->last]; - [self->last retain]; - - // then arrange in the secondary direction - hugsSecondary = uiDarwinControlHugsTrailingEdge; - if (!self->vertical) - hugsSecondary = uiDarwinControlHugsBottom; - for (bc in self->children) { - if (!uiControlVisible(bc.c)) - continue; - c = mkConstraint(self, self->secondaryStart, - NSLayoutRelationEqual, - [bc view], self->secondaryStart, - 1, 0, - @"uiBox secondary start constraint"); - [self addConstraint:c]; - [self->otherConstraints addObject:c]; - c = mkConstraint([bc view], self->secondaryEnd, - NSLayoutRelationLessThanOrEqual, - self, self->secondaryEnd, - 1, 0, - @"uiBox secondary end <= constraint"); - if ((*hugsSecondary)(uiDarwinControl(bc.c))) - [c setPriority:NSLayoutPriorityDefaultLow]; - [self addConstraint:c]; - [self->otherConstraints addObject:c]; - c = mkConstraint([bc view], self->secondaryEnd, - NSLayoutRelationEqual, - self, self->secondaryEnd, - 1, 0, - @"uiBox secondary end == constraint"); - if (!(*hugsSecondary)(uiDarwinControl(bc.c))) - [c setPriority:NSLayoutPriorityDefaultLow]; - [self addConstraint:c]; - [self->otherConstraints addObject:c]; - } - - // and make all stretchy controls the same size - if ([self nStretchy] == 0) - return; - prev = nil; // first stretchy view - for (bc in self->children) { - if (!uiControlVisible(bc.c)) - continue; - if (!bc.stretchy) - continue; - if (prev == nil) { - prev = [bc view]; - continue; - } - c = mkConstraint(prev, self->primarySize, - NSLayoutRelationEqual, - [bc view], self->primarySize, - 1, 0, - @"uiBox stretchy size constraint"); - [self addConstraint:c]; - [self->otherConstraints addObject:c]; - } -} - -- (void)append:(uiControl *)c stretchy:(int)stretchy -{ - boxChild *bc; - NSLayoutPriority priority; - int oldnStretchy; - - bc = [boxChild new]; - bc.c = c; - bc.stretchy = stretchy; - bc.oldPrimaryHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(bc.c), self->primaryOrientation); - bc.oldSecondaryHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(bc.c), self->secondaryOrientation); - - uiControlSetParent(bc.c, uiControl(self->b)); - uiDarwinControlSetSuperview(uiDarwinControl(bc.c), self); - uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), uiControlEnabledToUser(uiControl(self->b))); - - // if a control is stretchy, it should not hug in the primary direction - // otherwise, it should *forcibly* hug - if (bc.stretchy) - priority = NSLayoutPriorityDefaultLow; - else - // LONGTERM will default high work? - priority = NSLayoutPriorityRequired; - uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), priority, self->primaryOrientation); - // make sure controls don't hug their secondary direction so they fill the width of the view - uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), NSLayoutPriorityDefaultLow, self->secondaryOrientation); - - oldnStretchy = [self nStretchy]; - [self->children addObject:bc]; - - [self establishOurConstraints]; - if (bc.stretchy) - if (oldnStretchy == 0) - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->b)); - - [bc release]; // we don't need the initial reference now -} - -- (void)delete:(int)n -{ - boxChild *bc; - int stretchy; - - bc = (boxChild *) [self->children objectAtIndex:n]; - stretchy = bc.stretchy; - - uiControlSetParent(bc.c, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil); - - uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), bc.oldPrimaryHuggingPri, self->primaryOrientation); - uiDarwinControlSetHuggingPriority(uiDarwinControl(bc.c), bc.oldSecondaryHuggingPri, self->secondaryOrientation); - - [self->children removeObjectAtIndex:n]; - - [self establishOurConstraints]; - if (stretchy) - if ([self nStretchy] == 0) - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->b)); -} - -- (int)isPadded -{ - return self->padded; -} - -- (void)setPadded:(int)p -{ - CGFloat padding; - NSLayoutConstraint *c; - - self->padded = p; - padding = [self paddingAmount]; - for (c in self->inBetweens) - [c setConstant:-padding]; -} - -- (BOOL)hugsTrailing -{ - if (self->vertical) // always hug if vertical - return YES; - return [self nStretchy] != 0; -} - -- (BOOL)hugsBottom -{ - if (!self->vertical) // always hug if horizontal - return YES; - return [self nStretchy] != 0; -} - -- (int)nStretchy -{ - boxChild *bc; - int n; - - n = 0; - for (bc in self->children) { - if (!uiControlVisible(bc.c)) - continue; - if (bc.stretchy) - n++; - } - return n; -} - -@end - -static void uiBoxDestroy(uiControl *c) -{ - uiBox *b = uiBox(c); - - [b->view onDestroy]; - [b->view release]; - uiFreeControl(uiControl(b)); -} - -uiDarwinControlDefaultHandle(uiBox, view) -uiDarwinControlDefaultParent(uiBox, view) -uiDarwinControlDefaultSetParent(uiBox, view) -uiDarwinControlDefaultToplevel(uiBox, view) -uiDarwinControlDefaultVisible(uiBox, view) -uiDarwinControlDefaultShow(uiBox, view) -uiDarwinControlDefaultHide(uiBox, view) -uiDarwinControlDefaultEnabled(uiBox, view) -uiDarwinControlDefaultEnable(uiBox, view) -uiDarwinControlDefaultDisable(uiBox, view) - -static void uiBoxSyncEnableState(uiDarwinControl *c, int enabled) -{ - uiBox *b = uiBox(c); - - if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(b), enabled)) - return; - [b->view syncEnableStates:enabled]; -} - -uiDarwinControlDefaultSetSuperview(uiBox, view) - -static BOOL uiBoxHugsTrailingEdge(uiDarwinControl *c) -{ - uiBox *b = uiBox(c); - - return [b->view hugsTrailing]; -} - -static BOOL uiBoxHugsBottom(uiDarwinControl *c) -{ - uiBox *b = uiBox(c); - - return [b->view hugsBottom]; -} - -static void uiBoxChildEdgeHuggingChanged(uiDarwinControl *c) -{ - uiBox *b = uiBox(c); - - [b->view establishOurConstraints]; -} - -uiDarwinControlDefaultHuggingPriority(uiBox, view) -uiDarwinControlDefaultSetHuggingPriority(uiBox, view) - -static void uiBoxChildVisibilityChanged(uiDarwinControl *c) -{ - uiBox *b = uiBox(c); - - [b->view establishOurConstraints]; -} - -void uiBoxAppend(uiBox *b, uiControl *c, int stretchy) -{ - // LONGTERM on other platforms - // or at leat allow this and implicitly turn it into a spacer - if (c == NULL) - userbug("You cannot add NULL to a uiBox."); - [b->view append:c stretchy:stretchy]; -} - -void uiBoxDelete(uiBox *b, int n) -{ - [b->view delete:n]; -} - -int uiBoxPadded(uiBox *b) -{ - return [b->view isPadded]; -} - -void uiBoxSetPadded(uiBox *b, int padded) -{ - [b->view setPadded:padded]; -} - -static uiBox *finishNewBox(BOOL vertical) -{ - uiBox *b; - - uiDarwinNewControl(uiBox, b); - - b->view = [[boxView alloc] initWithVertical:vertical b:b]; - - return b; -} - -uiBox *uiNewHorizontalBox(void) -{ - return finishNewBox(NO); -} - -uiBox *uiNewVerticalBox(void) -{ - return finishNewBox(YES); -} diff --git a/src/libui_sdl/libui/darwin/button.m b/src/libui_sdl/libui/darwin/button.m deleted file mode 100644 index baccabbb..00000000 --- a/src/libui_sdl/libui/darwin/button.m +++ /dev/null @@ -1,113 +0,0 @@ -// 13 august 2015 -#import "uipriv_darwin.h" - -struct uiButton { - uiDarwinControl c; - NSButton *button; - void (*onClicked)(uiButton *, void *); - void *onClickedData; -}; - -@interface buttonDelegateClass : NSObject { - struct mapTable *buttons; -} -- (IBAction)onClicked:(id)sender; -- (void)registerButton:(uiButton *)b; -- (void)unregisterButton:(uiButton *)b; -@end - -@implementation buttonDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->buttons = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->buttons); - [super dealloc]; -} - -- (IBAction)onClicked:(id)sender -{ - uiButton *b; - - b = (uiButton *) mapGet(self->buttons, sender); - (*(b->onClicked))(b, b->onClickedData); -} - -- (void)registerButton:(uiButton *)b -{ - mapSet(self->buttons, b->button, b); - [b->button setTarget:self]; - [b->button setAction:@selector(onClicked:)]; -} - -- (void)unregisterButton:(uiButton *)b -{ - [b->button setTarget:nil]; - mapDelete(self->buttons, b->button); -} - -@end - -static buttonDelegateClass *buttonDelegate = nil; - -uiDarwinControlAllDefaultsExceptDestroy(uiButton, button) - -static void uiButtonDestroy(uiControl *c) -{ - uiButton *b = uiButton(c); - - [buttonDelegate unregisterButton:b]; - [b->button release]; - uiFreeControl(uiControl(b)); -} - -char *uiButtonText(uiButton *b) -{ - return uiDarwinNSStringToText([b->button title]); -} - -void uiButtonSetText(uiButton *b, const char *text) -{ - [b->button setTitle:toNSString(text)]; -} - -void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *, void *), void *data) -{ - b->onClicked = f; - b->onClickedData = data; -} - -static void defaultOnClicked(uiButton *b, void *data) -{ - // do nothing -} - -uiButton *uiNewButton(const char *text) -{ - uiButton *b; - - uiDarwinNewControl(uiButton, b); - - b->button = [[NSButton alloc] initWithFrame:NSZeroRect]; - [b->button setTitle:toNSString(text)]; - [b->button setButtonType:NSMomentaryPushInButton]; - [b->button setBordered:YES]; - [b->button setBezelStyle:NSRoundedBezelStyle]; - uiDarwinSetControlFont(b->button, NSRegularControlSize); - - if (buttonDelegate == nil) { - buttonDelegate = [[buttonDelegateClass new] autorelease]; - [delegates addObject:buttonDelegate]; - } - [buttonDelegate registerButton:b]; - uiButtonOnClicked(b, defaultOnClicked, NULL); - - return b; -} diff --git a/src/libui_sdl/libui/darwin/checkbox.m b/src/libui_sdl/libui/darwin/checkbox.m deleted file mode 100644 index dd1ce093..00000000 --- a/src/libui_sdl/libui/darwin/checkbox.m +++ /dev/null @@ -1,129 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -struct uiCheckbox { - uiDarwinControl c; - NSButton *button; - void (*onToggled)(uiCheckbox *, void *); - void *onToggledData; -}; - -@interface checkboxDelegateClass : NSObject { - struct mapTable *buttons; -} -- (IBAction)onToggled:(id)sender; -- (void)registerCheckbox:(uiCheckbox *)c; -- (void)unregisterCheckbox:(uiCheckbox *)c; -@end - -@implementation checkboxDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->buttons = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->buttons); - [super dealloc]; -} - -- (IBAction)onToggled:(id)sender -{ - uiCheckbox *c; - - c = (uiCheckbox *) mapGet(self->buttons, sender); - (*(c->onToggled))(c, c->onToggledData); -} - -- (void)registerCheckbox:(uiCheckbox *)c -{ - mapSet(self->buttons, c->button, c); - [c->button setTarget:self]; - [c->button setAction:@selector(onToggled:)]; -} - -- (void)unregisterCheckbox:(uiCheckbox *)c -{ - [c->button setTarget:nil]; - mapDelete(self->buttons, c->button); -} - -@end - -static checkboxDelegateClass *checkboxDelegate = nil; - -uiDarwinControlAllDefaultsExceptDestroy(uiCheckbox, button) - -static void uiCheckboxDestroy(uiControl *cc) -{ - uiCheckbox *c = uiCheckbox(cc); - - [checkboxDelegate unregisterCheckbox:c]; - [c->button release]; - uiFreeControl(uiControl(c)); -} - -char *uiCheckboxText(uiCheckbox *c) -{ - return uiDarwinNSStringToText([c->button title]); -} - -void uiCheckboxSetText(uiCheckbox *c, const char *text) -{ - [c->button setTitle:toNSString(text)]; -} - -void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *, void *), void *data) -{ - c->onToggled = f; - c->onToggledData = data; -} - -int uiCheckboxChecked(uiCheckbox *c) -{ - return [c->button state] == NSOnState; -} - -void uiCheckboxSetChecked(uiCheckbox *c, int checked) -{ - NSInteger state; - - state = NSOnState; - if (!checked) - state = NSOffState; - [c->button setState:state]; -} - -static void defaultOnToggled(uiCheckbox *c, void *data) -{ - // do nothing -} - -uiCheckbox *uiNewCheckbox(const char *text) -{ - uiCheckbox *c; - - uiDarwinNewControl(uiCheckbox, c); - - c->button = [[NSButton alloc] initWithFrame:NSZeroRect]; - [c->button setTitle:toNSString(text)]; - [c->button setButtonType:NSSwitchButton]; - // doesn't seem to have an associated bezel style - [c->button setBordered:NO]; - [c->button setTransparent:NO]; - uiDarwinSetControlFont(c->button, NSRegularControlSize); - - if (checkboxDelegate == nil) { - checkboxDelegate = [[checkboxDelegateClass new] autorelease]; - [delegates addObject:checkboxDelegate]; - } - [checkboxDelegate registerCheckbox:c]; - uiCheckboxOnToggled(c, defaultOnToggled, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/darwin/colorbutton.m b/src/libui_sdl/libui/darwin/colorbutton.m deleted file mode 100644 index 83b61571..00000000 --- a/src/libui_sdl/libui/darwin/colorbutton.m +++ /dev/null @@ -1,159 +0,0 @@ -// 15 may 2016 -#import "uipriv_darwin.h" - -// TODO no intrinsic height? - -@interface colorButton : NSColorWell { - uiColorButton *libui_b; - BOOL libui_changing; - BOOL libui_setting; -} -- (id)initWithFrame:(NSRect)frame libuiColorButton:(uiColorButton *)b; -- (void)deactivateOnClose:(NSNotification *)note; -- (void)libuiColor:(double *)r g:(double *)g b:(double *)b a:(double *)a; -- (void)libuiSetColor:(double)r g:(double)g b:(double)b a:(double)a; -@end - -// only one may be active at one time -static colorButton *activeColorButton = nil; - -struct uiColorButton { - uiDarwinControl c; - colorButton *button; - void (*onChanged)(uiColorButton *, void *); - void *onChangedData; -}; - -@implementation colorButton - -- (id)initWithFrame:(NSRect)frame libuiColorButton:(uiColorButton *)b -{ - self = [super initWithFrame:frame]; - if (self) { - // the default color is white; set it to black first (see -setColor: below for why we do it first) - [self libuiSetColor:0.0 g:0.0 b:0.0 a:1.0]; - - self->libui_b = b; - self->libui_changing = NO; - } - return self; -} - -- (void)activate:(BOOL)exclusive -{ - if (activeColorButton != nil) - activeColorButton->libui_changing = YES; - [NSColorPanel setPickerMask:NSColorPanelAllModesMask]; - [[NSColorPanel sharedColorPanel] setShowsAlpha:YES]; - [super activate:YES]; - activeColorButton = self; - // see stddialogs.m for details - [[NSColorPanel sharedColorPanel] setWorksWhenModal:NO]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(deactivateOnClose:) - name:NSWindowWillCloseNotification - object:[NSColorPanel sharedColorPanel]]; -} - -- (void)deactivate -{ - [super deactivate]; - activeColorButton = nil; - if (!self->libui_changing) - [[NSColorPanel sharedColorPanel] orderOut:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSWindowWillCloseNotification - object:[NSColorPanel sharedColorPanel]]; - self->libui_changing = NO; -} - -- (void)deactivateOnClose:(NSNotification *)note -{ - [self deactivate]; -} - -- (void)setColor:(NSColor *)color -{ - uiColorButton *b = self->libui_b; - - [super setColor:color]; - // this is called by NSColorWell's init, so we have to guard - // also don't signal during a programmatic change - if (b != nil && !self->libui_setting) - (*(b->onChanged))(b, b->onChangedData); -} - -- (void)libuiColor:(double *)r g:(double *)g b:(double *)b a:(double *)a -{ - NSColor *rgba; - CGFloat cr, cg, cb, ca; - - // the given color may not be an RGBA color, which will cause the -getRed:green:blue:alpha: call to throw an exception - rgba = [[self color] colorUsingColorSpace:[NSColorSpace sRGBColorSpace]]; - [rgba getRed:&cr green:&cg blue:&cb alpha:&ca]; - *r = cr; - *g = cg; - *b = cb; - *a = ca; - // rgba will be autoreleased since it isn't a new or init call -} - -- (void)libuiSetColor:(double)r g:(double)g b:(double)b a:(double)a -{ - self->libui_setting = YES; - [self setColor:[NSColor colorWithSRGBRed:r green:g blue:b alpha:a]]; - self->libui_setting = NO; -} - -// NSColorWell has no intrinsic size by default; give it the default Interface Builder size. -- (NSSize)intrinsicContentSize -{ - return NSMakeSize(44, 23); -} - -@end - -uiDarwinControlAllDefaults(uiColorButton, button) - -// we do not want color change events to be sent to any controls other than the color buttons -// see main.m for more details -BOOL colorButtonInhibitSendAction(SEL sel, id from, id to) -{ - if (sel != @selector(changeColor:)) - return NO; - return ![to isKindOfClass:[colorButton class]]; -} - -static void defaultOnChanged(uiColorButton *b, void *data) -{ - // do nothing -} - -void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a) -{ - [b->button libuiColor:r g:g b:bl a:a]; -} - -void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a) -{ - [b->button libuiSetColor:r g:g b:bl a:a]; -} - -void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data) -{ - b->onChanged = f; - b->onChangedData = data; -} - -uiColorButton *uiNewColorButton(void) -{ - uiColorButton *b; - - uiDarwinNewControl(uiColorButton, b); - - b->button = [[colorButton alloc] initWithFrame:NSZeroRect libuiColorButton:b]; - - uiColorButtonOnChanged(b, defaultOnChanged, NULL); - - return b; -} diff --git a/src/libui_sdl/libui/darwin/combobox.m b/src/libui_sdl/libui/darwin/combobox.m deleted file mode 100644 index 89a2e28c..00000000 --- a/src/libui_sdl/libui/darwin/combobox.m +++ /dev/null @@ -1,145 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// NSComboBoxes have no intrinsic width; we'll use the default Interface Builder width for them. -// NSPopUpButton is fine. -#define comboboxWidth 96 - -struct uiCombobox { - uiDarwinControl c; - NSPopUpButton *pb; - NSArrayController *pbac; - void (*onSelected)(uiCombobox *, void *); - void *onSelectedData; -}; - -@interface comboboxDelegateClass : NSObject { - struct mapTable *comboboxes; -} -- (IBAction)onSelected:(id)sender; -- (void)registerCombobox:(uiCombobox *)c; -- (void)unregisterCombobox:(uiCombobox *)c; -@end - -@implementation comboboxDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->comboboxes = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->comboboxes); - [super dealloc]; -} - -- (IBAction)onSelected:(id)sender -{ - uiCombobox *c; - - c = uiCombobox(mapGet(self->comboboxes, sender)); - (*(c->onSelected))(c, c->onSelectedData); -} - -- (void)registerCombobox:(uiCombobox *)c -{ - mapSet(self->comboboxes, c->pb, c); - [c->pb setTarget:self]; - [c->pb setAction:@selector(onSelected:)]; -} - -- (void)unregisterCombobox:(uiCombobox *)c -{ - [c->pb setTarget:nil]; - mapDelete(self->comboboxes, c->pb); -} - -@end - -static comboboxDelegateClass *comboboxDelegate = nil; - -uiDarwinControlAllDefaultsExceptDestroy(uiCombobox, pb) - -static void uiComboboxDestroy(uiControl *cc) -{ - uiCombobox *c = uiCombobox(cc); - - [comboboxDelegate unregisterCombobox:c]; - [c->pb unbind:@"contentObjects"]; - [c->pb unbind:@"selectedIndex"]; - [c->pbac release]; - [c->pb release]; - uiFreeControl(uiControl(c)); -} - -void uiComboboxAppend(uiCombobox *c, const char *text) -{ - [c->pbac addObject:toNSString(text)]; -} - -int uiComboboxSelected(uiCombobox *c) -{ - return [c->pb indexOfSelectedItem]; -} - -void uiComboboxSetSelected(uiCombobox *c, int n) -{ - [c->pb selectItemAtIndex:n]; -} - -void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data) -{ - c->onSelected = f; - c->onSelectedData = data; -} - -static void defaultOnSelected(uiCombobox *c, void *data) -{ - // do nothing -} - -uiCombobox *uiNewCombobox(void) -{ - uiCombobox *c; - NSPopUpButtonCell *pbcell; - - uiDarwinNewControl(uiCombobox, c); - - c->pb = [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO]; - [c->pb setPreferredEdge:NSMinYEdge]; - pbcell = (NSPopUpButtonCell *) [c->pb cell]; - [pbcell setArrowPosition:NSPopUpArrowAtBottom]; - // the font defined by Interface Builder is Menu 13, which is lol - // just use the regular control size for consistency - uiDarwinSetControlFont(c->pb, NSRegularControlSize); - - // NSPopUpButton doesn't work like a combobox - // - it automatically selects the first item - // - it doesn't support duplicates - // but we can use a NSArrayController and Cocoa bindings to bypass these restrictions - c->pbac = [NSArrayController new]; - [c->pbac setAvoidsEmptySelection:NO]; - [c->pbac setSelectsInsertedObjects:NO]; - [c->pbac setAutomaticallyRearrangesObjects:NO]; - [c->pb bind:@"contentValues" - toObject:c->pbac - withKeyPath:@"arrangedObjects" - options:nil]; - [c->pb bind:@"selectedIndex" - toObject:c->pbac - withKeyPath:@"selectionIndex" - options:nil]; - - if (comboboxDelegate == nil) { - comboboxDelegate = [[comboboxDelegateClass new] autorelease]; - [delegates addObject:comboboxDelegate]; - } - [comboboxDelegate registerCombobox:c]; - uiComboboxOnSelected(c, defaultOnSelected, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/darwin/control.m b/src/libui_sdl/libui/darwin/control.m deleted file mode 100644 index 9eaf47a2..00000000 --- a/src/libui_sdl/libui/darwin/control.m +++ /dev/null @@ -1,84 +0,0 @@ -// 16 august 2015 -#import "uipriv_darwin.h" - -void uiDarwinControlSyncEnableState(uiDarwinControl *c, int state) -{ - (*(c->SyncEnableState))(c, state); -} - -void uiDarwinControlSetSuperview(uiDarwinControl *c, NSView *superview) -{ - (*(c->SetSuperview))(c, superview); -} - -BOOL uiDarwinControlHugsTrailingEdge(uiDarwinControl *c) -{ - return (*(c->HugsTrailingEdge))(c); -} - -BOOL uiDarwinControlHugsBottom(uiDarwinControl *c) -{ - return (*(c->HugsBottom))(c); -} - -void uiDarwinControlChildEdgeHuggingChanged(uiDarwinControl *c) -{ - (*(c->ChildEdgeHuggingChanged))(c); -} - -NSLayoutPriority uiDarwinControlHuggingPriority(uiDarwinControl *c, NSLayoutConstraintOrientation orientation) -{ - return (*(c->HuggingPriority))(c, orientation); -} - -void uiDarwinControlSetHuggingPriority(uiDarwinControl *c, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation) -{ - (*(c->SetHuggingPriority))(c, priority, orientation); -} - -void uiDarwinControlChildVisibilityChanged(uiDarwinControl *c) -{ - (*(c->ChildVisibilityChanged))(c); -} - -void uiDarwinSetControlFont(NSControl *c, NSControlSize size) -{ - [c setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:size]]]; -} - -#define uiDarwinControlSignature 0x44617277 - -uiDarwinControl *uiDarwinAllocControl(size_t n, uint32_t typesig, const char *typenamestr) -{ - return uiDarwinControl(uiAllocControl(n, uiDarwinControlSignature, typesig, typenamestr)); -} - -BOOL uiDarwinShouldStopSyncEnableState(uiDarwinControl *c, BOOL enabled) -{ - int ce; - - ce = uiControlEnabled(uiControl(c)); - // only stop if we're going from disabled back to enabled; don't stop under any other condition - // (if we stop when going from enabled to disabled then enabled children of a disabled control won't get disabled at the OS level) - if (!ce && enabled) - return YES; - return NO; -} - -void uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl *c) -{ - uiControl *parent; - - parent = uiControlParent(uiControl(c)); - if (parent != NULL) - uiDarwinControlChildEdgeHuggingChanged(uiDarwinControl(parent)); -} - -void uiDarwinNotifyVisibilityChanged(uiDarwinControl *c) -{ - uiControl *parent; - - parent = uiControlParent(uiControl(c)); - if (parent != NULL) - uiDarwinControlChildVisibilityChanged(uiDarwinControl(parent)); -} diff --git a/src/libui_sdl/libui/darwin/datetimepicker.m b/src/libui_sdl/libui/darwin/datetimepicker.m deleted file mode 100644 index 44364d9d..00000000 --- a/src/libui_sdl/libui/darwin/datetimepicker.m +++ /dev/null @@ -1,42 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -struct uiDateTimePicker { - uiDarwinControl c; - NSDatePicker *dp; -}; - -uiDarwinControlAllDefaults(uiDateTimePicker, dp) - -static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elements) -{ - uiDateTimePicker *d; - - uiDarwinNewControl(uiDateTimePicker, d); - - d->dp = [[NSDatePicker alloc] initWithFrame:NSZeroRect]; - [d->dp setBordered:NO]; - [d->dp setBezeled:YES]; - [d->dp setDrawsBackground:YES]; - [d->dp setDatePickerStyle:NSTextFieldAndStepperDatePickerStyle]; - [d->dp setDatePickerElements:elements]; - [d->dp setDatePickerMode:NSSingleDateMode]; - uiDarwinSetControlFont(d->dp, NSRegularControlSize); - - return d; -} - -uiDateTimePicker *uiNewDateTimePicker(void) -{ - return finishNewDateTimePicker(NSYearMonthDayDatePickerElementFlag | NSHourMinuteSecondDatePickerElementFlag); -} - -uiDateTimePicker *uiNewDatePicker(void) -{ - return finishNewDateTimePicker(NSYearMonthDayDatePickerElementFlag); -} - -uiDateTimePicker *uiNewTimePicker(void) -{ - return finishNewDateTimePicker(NSHourMinuteSecondDatePickerElementFlag); -} diff --git a/src/libui_sdl/libui/darwin/debug.m b/src/libui_sdl/libui/darwin/debug.m deleted file mode 100644 index c91c6a73..00000000 --- a/src/libui_sdl/libui/darwin/debug.m +++ /dev/null @@ -1,19 +0,0 @@ -// 13 may 2016 -#import "uipriv_darwin.h" - -// LONGTERM don't halt on release builds - -void realbug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap) -{ - NSMutableString *str; - NSString *formatted; - - str = [NSMutableString new]; - [str appendString:[NSString stringWithFormat:@"[libui] %s:%s:%s() %s", file, line, func, prefix]]; - formatted = [[NSString alloc] initWithFormat:[NSString stringWithUTF8String:format] arguments:ap]; - [str appendString:formatted]; - [formatted release]; - NSLog(@"%@", str); - [str release]; - __builtin_trap(); -} diff --git a/src/libui_sdl/libui/darwin/draw.m b/src/libui_sdl/libui/darwin/draw.m deleted file mode 100644 index 262ad3e2..00000000 --- a/src/libui_sdl/libui/darwin/draw.m +++ /dev/null @@ -1,454 +0,0 @@ -// 6 september 2015 -#import "uipriv_darwin.h" - -struct uiDrawPath { - CGMutablePathRef path; - uiDrawFillMode fillMode; - BOOL ended; -}; - -uiDrawPath *uiDrawNewPath(uiDrawFillMode mode) -{ - uiDrawPath *p; - - p = uiNew(uiDrawPath); - p->path = CGPathCreateMutable(); - p->fillMode = mode; - return p; -} - -void uiDrawFreePath(uiDrawPath *p) -{ - CGPathRelease((CGPathRef) (p->path)); - uiFree(p); -} - -void uiDrawPathNewFigure(uiDrawPath *p, double x, double y) -{ - if (p->ended) - userbug("You cannot call uiDrawPathNewFigure() on a uiDrawPath that has already been ended. (path; %p)", p); - CGPathMoveToPoint(p->path, NULL, x, y); -} - -void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) -{ - double sinStart, cosStart; - double startx, starty; - - if (p->ended) - userbug("You cannot call uiDrawPathNewFigureWithArc() on a uiDrawPath that has already been ended. (path; %p)", p); - sinStart = sin(startAngle); - cosStart = cos(startAngle); - startx = xCenter + radius * cosStart; - starty = yCenter + radius * sinStart; - CGPathMoveToPoint(p->path, NULL, startx, starty); - uiDrawPathArcTo(p, xCenter, yCenter, radius, startAngle, sweep, negative); -} - -void uiDrawPathLineTo(uiDrawPath *p, double x, double y) -{ - // TODO refine this to require being in a path - if (p->ended) - implbug("attempt to add line to ended path in uiDrawPathLineTo()"); - CGPathAddLineToPoint(p->path, NULL, x, y); -} - -void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) -{ - bool cw; - - // TODO likewise - if (p->ended) - implbug("attempt to add arc to ended path in uiDrawPathArcTo()"); - if (sweep > 2 * uiPi) - sweep = 2 * uiPi; - cw = false; - if (negative) - cw = true; - CGPathAddArc(p->path, NULL, - xCenter, yCenter, - radius, - startAngle, startAngle + sweep, - cw); -} - -void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY) -{ - // TODO likewise - if (p->ended) - implbug("attempt to add bezier to ended path in uiDrawPathBezierTo()"); - CGPathAddCurveToPoint(p->path, NULL, - c1x, c1y, - c2x, c2y, - endX, endY); -} - -void uiDrawPathCloseFigure(uiDrawPath *p) -{ - // TODO likewise - if (p->ended) - implbug("attempt to close figure of ended path in uiDrawPathCloseFigure()"); - CGPathCloseSubpath(p->path); -} - -void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height) -{ - if (p->ended) - userbug("You cannot call uiDrawPathAddRectangle() on a uiDrawPath that has already been ended. (path; %p)", p); - CGPathAddRect(p->path, NULL, CGRectMake(x, y, width, height)); -} - -void uiDrawPathEnd(uiDrawPath *p) -{ - p->ended = TRUE; -} - -struct uiDrawContext { - CGContextRef c; - CGFloat height; // needed for text; see below -}; - -uiDrawContext *newContext(CGContextRef ctxt, CGFloat height) -{ - uiDrawContext *c; - - c = uiNew(uiDrawContext); - c->c = ctxt; - c->height = height; - return c; -} - -void freeContext(uiDrawContext *c) -{ - uiFree(c); -} - -// a stroke is identical to a fill of a stroked path -// we need to do this in order to stroke with a gradient; see http://stackoverflow.com/a/25034854/3408572 -// doing this for other brushes works too -void uiDrawStroke(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b, uiDrawStrokeParams *p) -{ - CGLineCap cap; - CGLineJoin join; - CGPathRef dashPath; - CGFloat *dashes; - size_t i; - uiDrawPath p2; - - if (!path->ended) - userbug("You cannot call uiDrawStroke() on a uiDrawPath that has not been ended. (path: %p)", path); - - switch (p->Cap) { - case uiDrawLineCapFlat: - cap = kCGLineCapButt; - break; - case uiDrawLineCapRound: - cap = kCGLineCapRound; - break; - case uiDrawLineCapSquare: - cap = kCGLineCapSquare; - break; - } - switch (p->Join) { - case uiDrawLineJoinMiter: - join = kCGLineJoinMiter; - break; - case uiDrawLineJoinRound: - join = kCGLineJoinRound; - break; - case uiDrawLineJoinBevel: - join = kCGLineJoinBevel; - break; - } - - // create a temporary path identical to the previous one - dashPath = (CGPathRef) path->path; - if (p->NumDashes != 0) { - dashes = (CGFloat *) uiAlloc(p->NumDashes * sizeof (CGFloat), "CGFloat[]"); - for (i = 0; i < p->NumDashes; i++) - dashes[i] = p->Dashes[i]; - dashPath = CGPathCreateCopyByDashingPath(path->path, - NULL, - p->DashPhase, - dashes, - p->NumDashes); - uiFree(dashes); - } - // the documentation is wrong: this produces a path suitable for calling CGPathCreateCopyByStrokingPath(), not for filling directly - // the cast is safe; we never modify the CGPathRef and always cast it back to a CGPathRef anyway - p2.path = (CGMutablePathRef) CGPathCreateCopyByStrokingPath(dashPath, - NULL, - p->Thickness, - cap, - join, - p->MiterLimit); - if (p->NumDashes != 0) - CGPathRelease(dashPath); - - // always draw stroke fills using the winding rule - // otherwise intersecting figures won't draw correctly - p2.fillMode = uiDrawFillModeWinding; - p2.ended = path->ended; - uiDrawFill(c, &p2, b); - // and clean up - CGPathRelease((CGPathRef) (p2.path)); -} - -// for a solid fill, we can merely have Core Graphics fill directly -static void fillSolid(CGContextRef ctxt, uiDrawPath *p, uiDrawBrush *b) -{ - // TODO this uses DeviceRGB; switch to sRGB - CGContextSetRGBFillColor(ctxt, b->R, b->G, b->B, b->A); - switch (p->fillMode) { - case uiDrawFillModeWinding: - CGContextFillPath(ctxt); - break; - case uiDrawFillModeAlternate: - CGContextEOFillPath(ctxt); - break; - } -} - -// for a gradient fill, we need to clip to the path and then draw the gradient -// see http://stackoverflow.com/a/25034854/3408572 -static void fillGradient(CGContextRef ctxt, uiDrawPath *p, uiDrawBrush *b) -{ - CGGradientRef gradient; - CGColorSpaceRef colorspace; - CGFloat *colors; - CGFloat *locations; - size_t i; - - // gradients need a color space - // for consistency with windows, use sRGB - colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - - // make the gradient - colors = uiAlloc(b->NumStops * 4 * sizeof (CGFloat), "CGFloat[]"); - locations = uiAlloc(b->NumStops * sizeof (CGFloat), "CGFloat[]"); - for (i = 0; i < b->NumStops; i++) { - colors[i * 4 + 0] = b->Stops[i].R; - colors[i * 4 + 1] = b->Stops[i].G; - colors[i * 4 + 2] = b->Stops[i].B; - colors[i * 4 + 3] = b->Stops[i].A; - locations[i] = b->Stops[i].Pos; - } - gradient = CGGradientCreateWithColorComponents(colorspace, colors, locations, b->NumStops); - uiFree(locations); - uiFree(colors); - - // because we're mucking with clipping, we need to save the graphics state and restore it later - CGContextSaveGState(ctxt); - - // clip - switch (p->fillMode) { - case uiDrawFillModeWinding: - CGContextClip(ctxt); - break; - case uiDrawFillModeAlternate: - CGContextEOClip(ctxt); - break; - } - - // draw the gradient - switch (b->Type) { - case uiDrawBrushTypeLinearGradient: - CGContextDrawLinearGradient(ctxt, - gradient, - CGPointMake(b->X0, b->Y0), - CGPointMake(b->X1, b->Y1), - kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); - break; - case uiDrawBrushTypeRadialGradient: - CGContextDrawRadialGradient(ctxt, - gradient, - CGPointMake(b->X0, b->Y0), - // make the start circle radius 0 to make it a point - 0, - CGPointMake(b->X1, b->Y1), - b->OuterRadius, - kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); - break; - } - - // and clean up - CGContextRestoreGState(ctxt); - CGGradientRelease(gradient); - CGColorSpaceRelease(colorspace); -} - -void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b) -{ - if (!path->ended) - userbug("You cannot call uiDrawStroke() on a uiDrawPath that has not been ended. (path: %p)", path); - CGContextAddPath(c->c, (CGPathRef) (path->path)); - switch (b->Type) { - case uiDrawBrushTypeSolid: - fillSolid(c->c, path, b); - return; - case uiDrawBrushTypeLinearGradient: - case uiDrawBrushTypeRadialGradient: - fillGradient(c->c, path, b); - return; -// case uiDrawBrushTypeImage: - // TODO - return; - } - userbug("Unknown brush type %d passed to uiDrawFill().", b->Type); -} - -static void m2c(uiDrawMatrix *m, CGAffineTransform *c) -{ - c->a = m->M11; - c->b = m->M12; - c->c = m->M21; - c->d = m->M22; - c->tx = m->M31; - c->ty = m->M32; -} - -static void c2m(CGAffineTransform *c, uiDrawMatrix *m) -{ - m->M11 = c->a; - m->M12 = c->b; - m->M21 = c->c; - m->M22 = c->d; - m->M31 = c->tx; - m->M32 = c->ty; -} - -void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y) -{ - CGAffineTransform c; - - m2c(m, &c); - c = CGAffineTransformTranslate(c, x, y); - c2m(&c, m); -} - -void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) -{ - CGAffineTransform c; - double xt, yt; - - m2c(m, &c); - xt = x; - yt = y; - scaleCenter(xCenter, yCenter, &xt, &yt); - c = CGAffineTransformTranslate(c, xt, yt); - c = CGAffineTransformScale(c, x, y); - c = CGAffineTransformTranslate(c, -xt, -yt); - c2m(&c, m); -} - -void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount) -{ - CGAffineTransform c; - - m2c(m, &c); - c = CGAffineTransformTranslate(c, x, y); - c = CGAffineTransformRotate(c, amount); - c = CGAffineTransformTranslate(c, -x, -y); - c2m(&c, m); -} - -void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount) -{ - fallbackSkew(m, x, y, xamount, yamount); -} - -void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src) -{ - CGAffineTransform c; - CGAffineTransform d; - - m2c(dest, &c); - m2c(src, &d); - c = CGAffineTransformConcat(c, d); - c2m(&c, dest); -} - -// there is no test for invertibility; CGAffineTransformInvert() is merely documented as returning the matrix unchanged if it isn't invertible -// therefore, special care must be taken to catch matrices who are their own inverses -// TODO figure out which matrices these are and do so -int uiDrawMatrixInvertible(uiDrawMatrix *m) -{ - CGAffineTransform c, d; - - m2c(m, &c); - d = CGAffineTransformInvert(c); - return CGAffineTransformEqualToTransform(c, d) == false; -} - -int uiDrawMatrixInvert(uiDrawMatrix *m) -{ - CGAffineTransform c, d; - - m2c(m, &c); - d = CGAffineTransformInvert(c); - if (CGAffineTransformEqualToTransform(c, d)) - return 0; - c2m(&d, m); - return 1; -} - -void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y) -{ - CGAffineTransform c; - CGPoint p; - - m2c(m, &c); - p = CGPointApplyAffineTransform(CGPointMake(*x, *y), c); - *x = p.x; - *y = p.y; -} - -void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y) -{ - CGAffineTransform c; - CGSize s; - - m2c(m, &c); - s = CGSizeApplyAffineTransform(CGSizeMake(*x, *y), c); - *x = s.width; - *y = s.height; -} - -void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m) -{ - CGAffineTransform cm; - - m2c(m, &cm); - CGContextConcatCTM(c->c, cm); -} - -void uiDrawClip(uiDrawContext *c, uiDrawPath *path) -{ - if (!path->ended) - userbug("You cannot call uiDrawCilp() on a uiDrawPath that has not been ended. (path: %p)", path); - CGContextAddPath(c->c, (CGPathRef) (path->path)); - switch (path->fillMode) { - case uiDrawFillModeWinding: - CGContextClip(c->c); - break; - case uiDrawFillModeAlternate: - CGContextEOClip(c->c); - break; - } -} - -// TODO figure out what besides transforms these save/restore on all platforms -void uiDrawSave(uiDrawContext *c) -{ - CGContextSaveGState(c->c); -} - -void uiDrawRestore(uiDrawContext *c) -{ - CGContextRestoreGState(c->c); -} - -void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout) -{ - doDrawText(c->c, c->height, x, y, layout); -} diff --git a/src/libui_sdl/libui/darwin/drawtext.m b/src/libui_sdl/libui/darwin/drawtext.m deleted file mode 100644 index c376536a..00000000 --- a/src/libui_sdl/libui/darwin/drawtext.m +++ /dev/null @@ -1,655 +0,0 @@ -// 6 september 2015 -#import "uipriv_darwin.h" - -// TODO -#define complain(...) implbug(__VA_ARGS__) - -// TODO double-check that we are properly handling allocation failures (or just toll free bridge from cocoa) -struct uiDrawFontFamilies { - CFArrayRef fonts; -}; - -uiDrawFontFamilies *uiDrawListFontFamilies(void) -{ - uiDrawFontFamilies *ff; - - ff = uiNew(uiDrawFontFamilies); - ff->fonts = CTFontManagerCopyAvailableFontFamilyNames(); - if (ff->fonts == NULL) - implbug("error getting available font names (no reason specified) (TODO)"); - return ff; -} - -int uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff) -{ - return CFArrayGetCount(ff->fonts); -} - -char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, int n) -{ - CFStringRef familystr; - char *family; - - familystr = (CFStringRef) CFArrayGetValueAtIndex(ff->fonts, n); - // toll-free bridge - family = uiDarwinNSStringToText((NSString *) familystr); - // Get Rule means we do not free familystr - return family; -} - -void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff) -{ - CFRelease(ff->fonts); - uiFree(ff); -} - -struct uiDrawTextFont { - CTFontRef f; -}; - -uiDrawTextFont *mkTextFont(CTFontRef f, BOOL retain) -{ - uiDrawTextFont *font; - - font = uiNew(uiDrawTextFont); - font->f = f; - if (retain) - CFRetain(font->f); - return font; -} - -uiDrawTextFont *mkTextFontFromNSFont(NSFont *f) -{ - // toll-free bridging; we do retain, though - return mkTextFont((CTFontRef) f, YES); -} - -static CFMutableDictionaryRef newAttrList(void) -{ - CFMutableDictionaryRef attr; - - attr = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (attr == NULL) - complain("error creating attribute dictionary in newAttrList()()"); - return attr; -} - -static void addFontFamilyAttr(CFMutableDictionaryRef attr, const char *family) -{ - CFStringRef cfstr; - - cfstr = CFStringCreateWithCString(NULL, family, kCFStringEncodingUTF8); - if (cfstr == NULL) - complain("error creating font family name CFStringRef in addFontFamilyAttr()"); - CFDictionaryAddValue(attr, kCTFontFamilyNameAttribute, cfstr); - CFRelease(cfstr); // dictionary holds its own reference -} - -static void addFontSizeAttr(CFMutableDictionaryRef attr, double size) -{ - CFNumberRef n; - - n = CFNumberCreate(NULL, kCFNumberDoubleType, &size); - CFDictionaryAddValue(attr, kCTFontSizeAttribute, n); - CFRelease(n); -} - -#if 0 -TODO -// See http://stackoverflow.com/questions/4810409/does-coretext-support-small-caps/4811371#4811371 and https://git.gnome.org/browse/pango/tree/pango/pangocoretext-fontmap.c for what these do -// And fortunately, unlike the traits (see below), unmatched features are simply ignored without affecting the other features :D -static void addFontSmallCapsAttr(CFMutableDictionaryRef attr) -{ - CFMutableArrayRef outerArray; - CFMutableDictionaryRef innerDict; - CFNumberRef numType, numSelector; - int num; - - outerArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - if (outerArray == NULL) - complain("error creating outer CFArray for adding small caps attributes in addFontSmallCapsAttr()"); - - // Apple's headers say these are deprecated, but a few fonts still rely on them - num = kLetterCaseType; - numType = CFNumberCreate(NULL, kCFNumberIntType, &num); - num = kSmallCapsSelector; - numSelector = CFNumberCreate(NULL, kCFNumberIntType, &num); - innerDict = newAttrList(); - CFDictionaryAddValue(innerDict, kCTFontFeatureTypeIdentifierKey, numType); - CFRelease(numType); - CFDictionaryAddValue(innerDict, kCTFontFeatureSelectorIdentifierKey, numSelector); - CFRelease(numSelector); - CFArrayAppendValue(outerArray, innerDict); - CFRelease(innerDict); // and likewise for CFArray - - // these are the non-deprecated versions of the above; some fonts have these instead - num = kLowerCaseType; - numType = CFNumberCreate(NULL, kCFNumberIntType, &num); - num = kLowerCaseSmallCapsSelector; - numSelector = CFNumberCreate(NULL, kCFNumberIntType, &num); - innerDict = newAttrList(); - CFDictionaryAddValue(innerDict, kCTFontFeatureTypeIdentifierKey, numType); - CFRelease(numType); - CFDictionaryAddValue(innerDict, kCTFontFeatureSelectorIdentifierKey, numSelector); - CFRelease(numSelector); - CFArrayAppendValue(outerArray, innerDict); - CFRelease(innerDict); // and likewise for CFArray - - CFDictionaryAddValue(attr, kCTFontFeatureSettingsAttribute, outerArray); - CFRelease(outerArray); -} -#endif - -// Named constants for these were NOT added until 10.11, and even then they were added as external symbols instead of macros, so we can't use them directly :( -// kode54 got these for me before I had access to El Capitan; thanks to him. -#define ourNSFontWeightUltraLight -0.800000 -#define ourNSFontWeightThin -0.600000 -#define ourNSFontWeightLight -0.400000 -#define ourNSFontWeightRegular 0.000000 -#define ourNSFontWeightMedium 0.230000 -#define ourNSFontWeightSemibold 0.300000 -#define ourNSFontWeightBold 0.400000 -#define ourNSFontWeightHeavy 0.560000 -#define ourNSFontWeightBlack 0.620000 -static const CGFloat ctWeights[] = { - // yeah these two have their names swapped; blame Pango - [uiDrawTextWeightThin] = ourNSFontWeightUltraLight, - [uiDrawTextWeightUltraLight] = ourNSFontWeightThin, - [uiDrawTextWeightLight] = ourNSFontWeightLight, - // for this one let's go between Light and Regular - // we're doing nearest so if there happens to be an exact value hopefully it's close enough - [uiDrawTextWeightBook] = ourNSFontWeightLight + ((ourNSFontWeightRegular - ourNSFontWeightLight) / 2), - [uiDrawTextWeightNormal] = ourNSFontWeightRegular, - [uiDrawTextWeightMedium] = ourNSFontWeightMedium, - [uiDrawTextWeightSemiBold] = ourNSFontWeightSemibold, - [uiDrawTextWeightBold] = ourNSFontWeightBold, - // for this one let's go between Bold and Heavy - [uiDrawTextWeightUltraBold] = ourNSFontWeightBold + ((ourNSFontWeightHeavy - ourNSFontWeightBold) / 2), - [uiDrawTextWeightHeavy] = ourNSFontWeightHeavy, - [uiDrawTextWeightUltraHeavy] = ourNSFontWeightBlack, -}; - -// Unfortunately there are still no named constants for these. -// Let's just use normalized widths. -// As far as I can tell (OS X only ships with condensed fonts, not expanded fonts; TODO), regardless of condensed or expanded, negative means condensed and positive means expanded. -// TODO verify this is correct -static const CGFloat ctStretches[] = { - [uiDrawTextStretchUltraCondensed] = -1.0, - [uiDrawTextStretchExtraCondensed] = -0.75, - [uiDrawTextStretchCondensed] = -0.5, - [uiDrawTextStretchSemiCondensed] = -0.25, - [uiDrawTextStretchNormal] = 0.0, - [uiDrawTextStretchSemiExpanded] = 0.25, - [uiDrawTextStretchExpanded] = 0.5, - [uiDrawTextStretchExtraExpanded] = 0.75, - [uiDrawTextStretchUltraExpanded] = 1.0, -}; - -struct closeness { - CFIndex index; - CGFloat weight; - CGFloat italic; - CGFloat stretch; - CGFloat distance; -}; - -// Stupidity: CTFont requires an **exact match for the entire traits dictionary**, otherwise it will **drop ALL the traits**. -// We have to implement the closest match ourselves. -// Also we have to do this before adding the small caps flags, because the matching descriptors won't have those. -CTFontDescriptorRef matchTraits(CTFontDescriptorRef against, uiDrawTextWeight weight, uiDrawTextItalic italic, uiDrawTextStretch stretch) -{ - CGFloat targetWeight; - CGFloat italicCloseness, obliqueCloseness, normalCloseness; - CGFloat targetStretch; - CFArrayRef matching; - CFIndex i, n; - struct closeness *closeness; - CTFontDescriptorRef current; - CTFontDescriptorRef out; - - targetWeight = ctWeights[weight]; - switch (italic) { - case uiDrawTextItalicNormal: - italicCloseness = 1; - obliqueCloseness = 1; - normalCloseness = 0; - break; - case uiDrawTextItalicOblique: - italicCloseness = 0.5; - obliqueCloseness = 0; - normalCloseness = 1; - break; - case uiDrawTextItalicItalic: - italicCloseness = 0; - obliqueCloseness = 0.5; - normalCloseness = 1; - break; - } - targetStretch = ctStretches[stretch]; - - matching = CTFontDescriptorCreateMatchingFontDescriptors(against, NULL); - if (matching == NULL) - // no matches; give the original back and hope for the best - return against; - n = CFArrayGetCount(matching); - if (n == 0) { - // likewise - CFRelease(matching); - return against; - } - - closeness = (struct closeness *) uiAlloc(n * sizeof (struct closeness), "struct closeness[]"); - for (i = 0; i < n; i++) { - CFDictionaryRef traits; - CFNumberRef cfnum; - CTFontSymbolicTraits symbolic; - - closeness[i].index = i; - - current = CFArrayGetValueAtIndex(matching, i); - traits = CTFontDescriptorCopyAttribute(current, kCTFontTraitsAttribute); - if (traits == NULL) { - // couldn't get traits; be safe by ranking it lowest - // LONGTERM figure out what the longest possible distances are - closeness[i].weight = 3; - closeness[i].italic = 2; - closeness[i].stretch = 3; - continue; - } - - symbolic = 0; // assume no symbolic traits if none are listed - cfnum = CFDictionaryGetValue(traits, kCTFontSymbolicTrait); - if (cfnum != NULL) { - SInt32 s; - - if (CFNumberGetValue(cfnum, kCFNumberSInt32Type, &s) == false) - complain("error getting symbolic traits in matchTraits()"); - symbolic = (CTFontSymbolicTraits) s; - // Get rule; do not release cfnum - } - - // now try weight - cfnum = CFDictionaryGetValue(traits, kCTFontWeightTrait); - if (cfnum != NULL) { - CGFloat val; - - // LONGTERM instead of complaining for this and width and possibly also symbolic traits above, should we just fall through to the default? - if (CFNumberGetValue(cfnum, kCFNumberCGFloatType, &val) == false) - complain("error getting weight value in matchTraits()"); - closeness[i].weight = val - targetWeight; - } else - // okay there's no weight key; let's try the literal meaning of the symbolic constant - // LONGTERM is the weight key guaranteed? - if ((symbolic & kCTFontBoldTrait) != 0) - closeness[i].weight = ourNSFontWeightBold - targetWeight; - else - closeness[i].weight = ourNSFontWeightRegular - targetWeight; - - // italics is a bit harder because Core Text doesn't expose a concept of obliqueness - // Pango just does a g_strrstr() (backwards case-sensitive search) for "Oblique" in the font's style name (see https://git.gnome.org/browse/pango/tree/pango/pangocoretext-fontmap.c); let's do that too I guess - if ((symbolic & kCTFontItalicTrait) != 0) - closeness[i].italic = italicCloseness; - else { - CFStringRef styleName; - BOOL isOblique; - - isOblique = NO; // default value - styleName = CTFontDescriptorCopyAttribute(current, kCTFontStyleNameAttribute); - if (styleName != NULL) { - CFRange range; - - // note the use of the toll-free bridge for the string literal, since CFSTR() *can* return NULL - range = CFStringFind(styleName, (CFStringRef) @"Oblique", kCFCompareBackwards); - if (range.location != kCFNotFound) - isOblique = YES; - CFRelease(styleName); - } - if (isOblique) - closeness[i].italic = obliqueCloseness; - else - closeness[i].italic = normalCloseness; - } - - // now try width - // TODO this does not seem to be enough for Skia's extended variants; the width trait is 0 but the Expanded flag is on - // TODO verify the rest of this matrix (what matrix?) - cfnum = CFDictionaryGetValue(traits, kCTFontWidthTrait); - if (cfnum != NULL) { - CGFloat val; - - if (CFNumberGetValue(cfnum, kCFNumberCGFloatType, &val) == false) - complain("error getting width value in matchTraits()"); - closeness[i].stretch = val - targetStretch; - } else - // okay there's no width key; let's try the literal meaning of the symbolic constant - // LONGTERM is the width key guaranteed? - if ((symbolic & kCTFontExpandedTrait) != 0) - closeness[i].stretch = 1.0 - targetStretch; - else if ((symbolic & kCTFontCondensedTrait) != 0) - closeness[i].stretch = -1.0 - targetStretch; - else - closeness[i].stretch = 0.0 - targetStretch; - - CFRelease(traits); - } - - // now figure out the 3-space difference between the three and sort by that - for (i = 0; i < n; i++) { - CGFloat weight, italic, stretch; - - weight = closeness[i].weight; - weight *= weight; - italic = closeness[i].italic; - italic *= italic; - stretch = closeness[i].stretch; - stretch *= stretch; - closeness[i].distance = sqrt(weight + italic + stretch); - } - qsort_b(closeness, n, sizeof (struct closeness), ^(const void *aa, const void *bb) { - const struct closeness *a = (const struct closeness *) aa; - const struct closeness *b = (const struct closeness *) bb; - - // via http://www.gnu.org/software/libc/manual/html_node/Comparison-Functions.html#Comparison-Functions - // LONGTERM is this really the best way? isn't it the same as if (*a < *b) return -1; if (*a > *b) return 1; return 0; ? - return (a->distance > b->distance) - (a->distance < b->distance); - }); - // and the first element of the sorted array is what we want - out = CFArrayGetValueAtIndex(matching, closeness[0].index); - CFRetain(out); // get rule - - // release everything - uiFree(closeness); - CFRelease(matching); - // and release the original descriptor since we no longer need it - CFRelease(against); - - return out; -} - -// Now remember what I said earlier about having to add the small caps traits after calling the above? This gets a dictionary back so we can do so. -CFMutableDictionaryRef extractAttributes(CTFontDescriptorRef desc) -{ - CFDictionaryRef dict; - CFMutableDictionaryRef mdict; - - dict = CTFontDescriptorCopyAttributes(desc); - // this might not be mutable, so make a mutable copy - mdict = CFDictionaryCreateMutableCopy(NULL, 0, dict); - CFRelease(dict); - return mdict; -} - -uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc) -{ - CTFontRef f; - CFMutableDictionaryRef attr; - CTFontDescriptorRef cfdesc; - - attr = newAttrList(); - addFontFamilyAttr(attr, desc->Family); - addFontSizeAttr(attr, desc->Size); - - // now we have to do the traits matching, so create a descriptor, match the traits, and then get the attributes back - cfdesc = CTFontDescriptorCreateWithAttributes(attr); - // TODO release attr? - cfdesc = matchTraits(cfdesc, desc->Weight, desc->Italic, desc->Stretch); - - // specify the initial size again just to be safe - f = CTFontCreateWithFontDescriptor(cfdesc, desc->Size, NULL); - // TODO release cfdesc? - - return mkTextFont(f, NO); // we hold the initial reference; no need to retain again -} - -void uiDrawFreeTextFont(uiDrawTextFont *font) -{ - CFRelease(font->f); - uiFree(font); -} - -uintptr_t uiDrawTextFontHandle(uiDrawTextFont *font) -{ - return (uintptr_t) (font->f); -} - -void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc) -{ - // TODO -} - -// text sizes and user space points are identical: -// - https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/TypoFeatures/TextSystemFeatures.html#//apple_ref/doc/uid/TP40009459-CH6-51627-BBCCHIFF text points are 72 per inch -// - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Transforms/Transforms.html#//apple_ref/doc/uid/TP40003290-CH204-SW5 user space points are 72 per inch -void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics) -{ - metrics->Ascent = CTFontGetAscent(font->f); - metrics->Descent = CTFontGetDescent(font->f); - metrics->Leading = CTFontGetLeading(font->f); - metrics->UnderlinePos = CTFontGetUnderlinePosition(font->f); - metrics->UnderlineThickness = CTFontGetUnderlineThickness(font->f); -} - -struct uiDrawTextLayout { - CFMutableAttributedStringRef mas; - CFRange *charsToRanges; - double width; -}; - -uiDrawTextLayout *uiDrawNewTextLayout(const char *str, uiDrawTextFont *defaultFont, double width) -{ - uiDrawTextLayout *layout; - CFAttributedStringRef immutable; - CFMutableDictionaryRef attr; - CFStringRef backing; - CFIndex i, j, n; - - layout = uiNew(uiDrawTextLayout); - - // TODO docs say we need to use a different set of key callbacks - // TODO see if the font attribute key callbacks need to be the same - attr = newAttrList(); - // this will retain defaultFont->f; no need to worry - CFDictionaryAddValue(attr, kCTFontAttributeName, defaultFont->f); - - immutable = CFAttributedStringCreate(NULL, (CFStringRef) [NSString stringWithUTF8String:str], attr); - if (immutable == NULL) - complain("error creating immutable attributed string in uiDrawNewTextLayout()"); - CFRelease(attr); - - layout->mas = CFAttributedStringCreateMutableCopy(NULL, 0, immutable); - if (layout->mas == NULL) - complain("error creating attributed string in uiDrawNewTextLayout()"); - CFRelease(immutable); - - uiDrawTextLayoutSetWidth(layout, width); - - // unfortunately the CFRanges for attributes expect UTF-16 codepoints - // we want graphemes - // fortunately CFStringGetRangeOfComposedCharactersAtIndex() is here for us - // https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Strings/Articles/stringsClusters.html says that this does work on all multi-codepoint graphemes (despite the name), and that this is the preferred function for this particular job anyway - backing = CFAttributedStringGetString(layout->mas); - n = CFStringGetLength(backing); - // allocate one extra, just to be safe - layout->charsToRanges = (CFRange *) uiAlloc((n + 1) * sizeof (CFRange), "CFRange[]"); - i = 0; - j = 0; - while (i < n) { - CFRange range; - - range = CFStringGetRangeOfComposedCharactersAtIndex(backing, i); - i = range.location + range.length; - layout->charsToRanges[j] = range; - j++; - } - // and set the last one - layout->charsToRanges[j].location = i; - layout->charsToRanges[j].length = 0; - - return layout; -} - -void uiDrawFreeTextLayout(uiDrawTextLayout *layout) -{ - uiFree(layout->charsToRanges); - CFRelease(layout->mas); - uiFree(layout); -} - -void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width) -{ - layout->width = width; -} - -struct framesetter { - CTFramesetterRef fs; - CFMutableDictionaryRef frameAttrib; - CGSize extents; -}; - -// TODO CTFrameProgression for RTL/LTR -// TODO kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierMinimumLineSpacing, kCTParagraphStyleSpecifierLineSpacingAdjustment for line spacing -static void mkFramesetter(uiDrawTextLayout *layout, struct framesetter *fs) -{ - CFRange fitRange; - CGFloat width; - - fs->fs = CTFramesetterCreateWithAttributedString(layout->mas); - if (fs->fs == NULL) - complain("error creating CTFramesetter object in mkFramesetter()"); - - // TODO kCTFramePathWidthAttributeName? - fs->frameAttrib = NULL; - - width = layout->width; - if (layout->width < 0) - width = CGFLOAT_MAX; - // TODO these seem to be floor()'d or truncated? - fs->extents = CTFramesetterSuggestFrameSizeWithConstraints(fs->fs, - CFRangeMake(0, 0), - fs->frameAttrib, - CGSizeMake(width, CGFLOAT_MAX), - &fitRange); // not documented as accepting NULL -} - -static void freeFramesetter(struct framesetter *fs) -{ - if (fs->frameAttrib != NULL) - CFRelease(fs->frameAttrib); - CFRelease(fs->fs); -} - -// LONGTERM allow line separation and leading to be factored into a wrapping text layout - -// TODO reconcile differences in character wrapping on platforms -void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height) -{ - struct framesetter fs; - - mkFramesetter(layout, &fs); - *width = fs.extents.width; - *height = fs.extents.height; - freeFramesetter(&fs); -} - -// Core Text doesn't draw onto a flipped view correctly; we have to do this -// see the iOS bits of the first example at https://developer.apple.com/library/mac/documentation/StringsTextFonts/Conceptual/CoreText_Programming/LayoutOperations/LayoutOperations.html#//apple_ref/doc/uid/TP40005533-CH12-SW1 (iOS is naturally flipped) -// TODO how is this affected by the CTM? -static void prepareContextForText(CGContextRef c, CGFloat cheight, double *y) -{ - CGContextSaveGState(c); - CGContextTranslateCTM(c, 0, cheight); - CGContextScaleCTM(c, 1.0, -1.0); - CGContextSetTextMatrix(c, CGAffineTransformIdentity); - - // wait, that's not enough; we need to offset y values to account for our new flipping - *y = cheight - *y; -} - -// TODO placement is incorrect for Helvetica -void doDrawText(CGContextRef c, CGFloat cheight, double x, double y, uiDrawTextLayout *layout) -{ - struct framesetter fs; - CGRect rect; - CGPathRef path; - CTFrameRef frame; - - prepareContextForText(c, cheight, &y); - mkFramesetter(layout, &fs); - - // oh, and since we're flipped, y is the bottom-left coordinate of the rectangle, not the top-left - // since we are flipped, we subtract - y -= fs.extents.height; - - rect.origin = CGPointMake(x, y); - rect.size = fs.extents; - path = CGPathCreateWithRect(rect, NULL); - - frame = CTFramesetterCreateFrame(fs.fs, - CFRangeMake(0, 0), - path, - fs.frameAttrib); - if (frame == NULL) - complain("error creating CTFrame object in doDrawText()"); - CTFrameDraw(frame, c); - CFRelease(frame); - - CFRelease(path); - - freeFramesetter(&fs); - CGContextRestoreGState(c); -} - -// LONGTERM provide an equivalent to CTLineGetTypographicBounds() on uiDrawTextLayout? - -// LONGTERM keep this for later features and documentation purposes -#if 0 - w = CTLineGetTypographicBounds(line, &ascent, &descent, NULL); - // though CTLineGetTypographicBounds() returns 0 on error, it also returns 0 on an empty string, so we can't reasonably check for error - CFRelease(line); - - // LONGTERM provide a way to get the image bounds as a separate function later - bounds = CTLineGetImageBounds(line, c); - // though CTLineGetImageBounds() returns CGRectNull on error, it also returns CGRectNull on an empty string, so we can't reasonably check for error - - // CGContextSetTextPosition() positions at the baseline in the case of CTLineDraw(); we need the top-left corner instead - CTLineGetTypographicBounds(line, &yoff, NULL, NULL); - // remember that we're flipped, so we subtract - y -= yoff; - CGContextSetTextPosition(c, x, y); -#endif - -static CFRange charsToRange(uiDrawTextLayout *layout, int startChar, int endChar) -{ - CFRange start, end; - CFRange out; - - start = layout->charsToRanges[startChar]; - end = layout->charsToRanges[endChar]; - out.location = start.location; - out.length = end.location - start.location; - return out; -} - -#define rangeToCFRange() charsToRange(layout, startChar, endChar) - -void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar, int endChar, double r, double g, double b, double a) -{ - CGColorSpaceRef colorspace; - CGFloat components[4]; - CGColorRef color; - - // for consistency with windows, use sRGB - colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - components[0] = r; - components[1] = g; - components[2] = b; - components[3] = a; - color = CGColorCreate(colorspace, components); - CGColorSpaceRelease(colorspace); - - CFAttributedStringSetAttribute(layout->mas, - rangeToCFRange(), - kCTForegroundColorAttributeName, - color); - CGColorRelease(color); // TODO safe? -} diff --git a/src/libui_sdl/libui/darwin/editablecombo.m b/src/libui_sdl/libui/darwin/editablecombo.m deleted file mode 100644 index 434add70..00000000 --- a/src/libui_sdl/libui/darwin/editablecombo.m +++ /dev/null @@ -1,185 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// So why did I split uiCombobox into uiCombobox and uiEditableCombobox? Here's (90% of the; the other 10% is GTK+ events) answer: -// When you type a value into a NSComboBox that just happens to be in the list, it will autoselect that item! -// I can't seem to find a workaround. -// Fortunately, there's other weird behaviors that made this split worth it. -// And besides, selected items make little sense with editable comboboxes... you either separate or combine them with the text entry :V - -// NSComboBoxes have no intrinsic width; we'll use the default Interface Builder width for them. -#define comboboxWidth 96 - -@interface libui_intrinsicWidthNSComboBox : NSComboBox -@end - -@implementation libui_intrinsicWidthNSComboBox - -- (NSSize)intrinsicContentSize -{ - NSSize s; - - s = [super intrinsicContentSize]; - s.width = comboboxWidth; - return s; -} - -@end - -struct uiEditableCombobox { - uiDarwinControl c; - NSComboBox *cb; - void (*onChanged)(uiEditableCombobox *, void *); - void *onChangedData; -}; - -@interface editableComboboxDelegateClass : NSObject { - struct mapTable *comboboxes; -} -- (void)controlTextDidChange:(NSNotification *)note; -- (void)comboBoxSelectionDidChange:(NSNotification *)note; -- (void)registerCombobox:(uiEditableCombobox *)c; -- (void)unregisterCombobox:(uiEditableCombobox *)c; -@end - -@implementation editableComboboxDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->comboboxes = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->comboboxes); - [super dealloc]; -} - -- (void)controlTextDidChange:(NSNotification *)note -{ - uiEditableCombobox *c; - - c = uiEditableCombobox(mapGet(self->comboboxes, [note object])); - (*(c->onChanged))(c, c->onChangedData); -} - -// the above doesn't handle when an item is selected; this will -- (void)comboBoxSelectionDidChange:(NSNotification *)note -{ - // except this is sent BEFORE the entry is changed, and that doesn't send the above, so - // this is via http://stackoverflow.com/a/21059819/3408572 - it avoids the need to manage selected items - // this still isn't perfect — I get residual changes to the same value while navigating the list — but it's good enough - [self performSelector:@selector(controlTextDidChange:) - withObject:note - afterDelay:0]; -} - -- (void)registerCombobox:(uiEditableCombobox *)c -{ - mapSet(self->comboboxes, c->cb, c); - [c->cb setDelegate:self]; -} - -- (void)unregisterCombobox:(uiEditableCombobox *)c -{ - [c->cb setDelegate:nil]; - mapDelete(self->comboboxes, c->cb); -} - -@end - -static editableComboboxDelegateClass *comboboxDelegate = nil; - -uiDarwinControlAllDefaultsExceptDestroy(uiEditableCombobox, cb) - -static void uiEditableComboboxDestroy(uiControl *cc) -{ - uiEditableCombobox *c = uiEditableCombobox(cc); - - [comboboxDelegate unregisterCombobox:c]; - [c->cb release]; - uiFreeControl(uiControl(c)); -} - -void uiEditableComboboxAppend(uiEditableCombobox *c, const char *text) -{ - [c->cb addItemWithObjectValue:toNSString(text)]; -} - -char *uiEditableComboboxText(uiEditableCombobox *c) -{ - return uiDarwinNSStringToText([c->cb stringValue]); -} - -void uiEditableComboboxSetText(uiEditableCombobox *c, const char *text) -{ - NSString *t; - - t = toNSString(text); - [c->cb setStringValue:t]; - // yes, let's imitate the behavior that caused uiEditableCombobox to be separate in the first place! - // just to avoid confusion when users see an option in the list in the text field but not selected in the list - [c->cb selectItemWithObjectValue:t]; -} - -#if 0 -// LONGTERM -void uiEditableComboboxSetSelected(uiEditableCombobox *c, int n) -{ - if (c->editable) { - // see https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ComboBox/Tasks/SettingComboBoxValue.html#//apple_ref/doc/uid/20000256 - id delegate; - - // this triggers the delegate; turn it off for now - delegate = [c->cb delegate]; - [c->cb setDelegate:nil]; - - // this seems to work fine for -1 too - [c->cb selectItemAtIndex:n]; - if (n == -1) - [c->cb setObjectValue:@""]; - else - [c->cb setObjectValue:[c->cb objectValueOfSelectedItem]]; - - [c->cb setDelegate:delegate]; - return; - } - [c->pb selectItemAtIndex:n]; -} -#endif - -void uiEditableComboboxOnChanged(uiEditableCombobox *c, void (*f)(uiEditableCombobox *c, void *data), void *data) -{ - c->onChanged = f; - c->onChangedData = data; -} - -static void defaultOnChanged(uiEditableCombobox *c, void *data) -{ - // do nothing -} - -uiEditableCombobox *uiNewEditableCombobox(void) -{ - uiEditableCombobox *c; - - uiDarwinNewControl(uiEditableCombobox, c); - - c->cb = [[libui_intrinsicWidthNSComboBox alloc] initWithFrame:NSZeroRect]; - [c->cb setUsesDataSource:NO]; - [c->cb setButtonBordered:YES]; - [c->cb setCompletes:NO]; - uiDarwinSetControlFont(c->cb, NSRegularControlSize); - - if (comboboxDelegate == nil) { - comboboxDelegate = [[editableComboboxDelegateClass new] autorelease]; - [delegates addObject:comboboxDelegate]; - } - [comboboxDelegate registerCombobox:c]; - uiEditableComboboxOnChanged(c, defaultOnChanged, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/darwin/entry.m b/src/libui_sdl/libui/darwin/entry.m deleted file mode 100644 index 219d0805..00000000 --- a/src/libui_sdl/libui/darwin/entry.m +++ /dev/null @@ -1,251 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// Text fields for entering text have no intrinsic width; we'll use the default Interface Builder width for them. -#define textfieldWidth 96 - -@interface libui_intrinsicWidthNSTextField : NSTextField -@end - -@implementation libui_intrinsicWidthNSTextField - -- (NSSize)intrinsicContentSize -{ - NSSize s; - - s = [super intrinsicContentSize]; - s.width = textfieldWidth; - return s; -} - -@end - -// TODO does this have one on its own? -@interface libui_intrinsicWidthNSSecureTextField : NSSecureTextField -@end - -@implementation libui_intrinsicWidthNSSecureTextField - -- (NSSize)intrinsicContentSize -{ - NSSize s; - - s = [super intrinsicContentSize]; - s.width = textfieldWidth; - return s; -} - -@end - -// TODO does this have one on its own? -@interface libui_intrinsicWidthNSSearchField : NSSearchField -@end - -@implementation libui_intrinsicWidthNSSearchField - -- (NSSize)intrinsicContentSize -{ - NSSize s; - - s = [super intrinsicContentSize]; - s.width = textfieldWidth; - return s; -} - -@end - -struct uiEntry { - uiDarwinControl c; - NSTextField *textfield; - void (*onChanged)(uiEntry *, void *); - void *onChangedData; -}; - -static BOOL isSearchField(NSTextField *tf) -{ - return [tf isKindOfClass:[NSSearchField class]]; -} - -@interface entryDelegateClass : NSObject { - struct mapTable *entries; -} -- (void)controlTextDidChange:(NSNotification *)note; -- (IBAction)onSearch:(id)sender; -- (void)registerEntry:(uiEntry *)e; -- (void)unregisterEntry:(uiEntry *)e; -@end - -@implementation entryDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->entries = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->entries); - [super dealloc]; -} - -- (void)controlTextDidChange:(NSNotification *)note -{ - [self onSearch:[note object]]; -} - -- (IBAction)onSearch:(id)sender -{ - uiEntry *e; - - e = (uiEntry *) mapGet(self->entries, sender); - (*(e->onChanged))(e, e->onChangedData); -} - -- (void)registerEntry:(uiEntry *)e -{ - mapSet(self->entries, e->textfield, e); - if (isSearchField(e->textfield)) { - [e->textfield setTarget:self]; - [e->textfield setAction:@selector(onSearch:)]; - } else - [e->textfield setDelegate:self]; -} - -- (void)unregisterEntry:(uiEntry *)e -{ - if (isSearchField(e->textfield)) - [e->textfield setTarget:nil]; - else - [e->textfield setDelegate:nil]; - mapDelete(self->entries, e->textfield); -} - -@end - -static entryDelegateClass *entryDelegate = nil; - -uiDarwinControlAllDefaultsExceptDestroy(uiEntry, textfield) - -static void uiEntryDestroy(uiControl *c) -{ - uiEntry *e = uiEntry(c); - - [entryDelegate unregisterEntry:e]; - [e->textfield release]; - uiFreeControl(uiControl(e)); -} - -char *uiEntryText(uiEntry *e) -{ - return uiDarwinNSStringToText([e->textfield stringValue]); -} - -void uiEntrySetText(uiEntry *e, const char *text) -{ - [e->textfield setStringValue:toNSString(text)]; - // don't queue the control for resize; entry sizes are independent of their contents -} - -void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) -{ - e->onChanged = f; - e->onChangedData = data; -} - -int uiEntryReadOnly(uiEntry *e) -{ - return [e->textfield isEditable] == NO; -} - -void uiEntrySetReadOnly(uiEntry *e, int readonly) -{ - BOOL editable; - - editable = YES; - if (readonly) - editable = NO; - [e->textfield setEditable:editable]; -} - -static void defaultOnChanged(uiEntry *e, void *data) -{ - // do nothing -} - -// these are based on interface builder defaults; my comments in the old code weren't very good so I don't really know what talked about what, sorry :/ -void finishNewTextField(NSTextField *t, BOOL isEntry) -{ - uiDarwinSetControlFont(t, NSRegularControlSize); - - // THE ORDER OF THESE CALLS IS IMPORTANT; CHANGE IT AND THE BORDERS WILL DISAPPEAR - [t setBordered:NO]; - [t setBezelStyle:NSTextFieldSquareBezel]; - [t setBezeled:isEntry]; - - // we don't need to worry about substitutions/autocorrect here; see window_darwin.m for details - - [[t cell] setLineBreakMode:NSLineBreakByClipping]; - [[t cell] setScrollable:YES]; -} - -static NSTextField *realNewEditableTextField(Class class) -{ - NSTextField *tf; - - tf = [[class alloc] initWithFrame:NSZeroRect]; - [tf setSelectable:YES]; // otherwise the setting is masked by the editable default of YES - finishNewTextField(tf, YES); - return tf; -} - -NSTextField *newEditableTextField(void) -{ - return realNewEditableTextField([libui_intrinsicWidthNSTextField class]); -} - -static uiEntry *finishNewEntry(Class class) -{ - uiEntry *e; - - uiDarwinNewControl(uiEntry, e); - - e->textfield = realNewEditableTextField(class); - - if (entryDelegate == nil) { - entryDelegate = [[entryDelegateClass new] autorelease]; - [delegates addObject:entryDelegate]; - } - [entryDelegate registerEntry:e]; - uiEntryOnChanged(e, defaultOnChanged, NULL); - - return e; -} - -uiEntry *uiNewEntry(void) -{ - return finishNewEntry([libui_intrinsicWidthNSTextField class]); -} - -uiEntry *uiNewPasswordEntry(void) -{ - return finishNewEntry([libui_intrinsicWidthNSSecureTextField class]); -} - -uiEntry *uiNewSearchEntry(void) -{ - uiEntry *e; - NSSearchField *s; - - e = finishNewEntry([libui_intrinsicWidthNSSearchField class]); - s = (NSSearchField *) (e->textfield); - // TODO these are only on 10.10 -// [s setSendsSearchStringImmediately:NO]; -// [s setSendsWholeSearchString:NO]; - [s setBordered:NO]; - [s setBezelStyle:NSTextFieldRoundedBezel]; - [s setBezeled:YES]; - return e; -} diff --git a/src/libui_sdl/libui/darwin/fontbutton.m b/src/libui_sdl/libui/darwin/fontbutton.m deleted file mode 100644 index 22bc6465..00000000 --- a/src/libui_sdl/libui/darwin/fontbutton.m +++ /dev/null @@ -1,218 +0,0 @@ -// 14 april 2016 -#import "uipriv_darwin.h" - -@interface fontButton : NSButton { - uiFontButton *libui_b; - NSFont *libui_font; -} -- (id)initWithFrame:(NSRect)frame libuiFontButton:(uiFontButton *)b; -- (void)updateFontButtonLabel; -- (IBAction)fontButtonClicked:(id)sender; -- (void)activateFontButton; -- (void)deactivateFontButton:(BOOL)activatingAnother; -- (void)deactivateOnClose:(NSNotification *)note; -- (uiDrawTextFont *)libuiFont; -@end - -// only one may be active at one time -static fontButton *activeFontButton = nil; - -struct uiFontButton { - uiDarwinControl c; - fontButton *button; - void (*onChanged)(uiFontButton *, void *); - void *onChangedData; -}; - -@implementation fontButton - -- (id)initWithFrame:(NSRect)frame libuiFontButton:(uiFontButton *)b -{ - self = [super initWithFrame:frame]; - if (self) { - self->libui_b = b; - - // imitate a NSColorWell in appearance - [self setButtonType:NSPushOnPushOffButton]; - [self setBordered:YES]; - [self setBezelStyle:NSShadowlessSquareBezelStyle]; - - // default font values according to the CTFontDescriptor reference - // this is autoreleased (thanks swillits in irc.freenode.net/#macdev) - self->libui_font = [[NSFont fontWithName:@"Helvetica" size:12.0] retain]; - [self updateFontButtonLabel]; - - // for when clicked - [self setTarget:self]; - [self setAction:@selector(fontButtonClicked:)]; - } - return self; -} - -- (void)dealloc -{ - // clean up notifications - if (activeFontButton == self) - [self deactivateFontButton:NO]; - [self->libui_font release]; - [super dealloc]; -} - -- (void)updateFontButtonLabel -{ - NSString *title; - - title = [NSString stringWithFormat:@"%@ %g", - [self->libui_font displayName], - [self->libui_font pointSize]]; - [self setTitle:title]; -} - -- (IBAction)fontButtonClicked:(id)sender -{ - if ([self state] == NSOnState) - [self activateFontButton]; - else - [self deactivateFontButton:NO]; -} - -- (void)activateFontButton -{ - NSFontManager *sfm; - - sfm = [NSFontManager sharedFontManager]; - if (activeFontButton != nil) - [activeFontButton deactivateFontButton:YES]; - [sfm setTarget:self]; - [sfm setSelectedFont:self->libui_font isMultiple:NO]; - [sfm orderFrontFontPanel:self]; - activeFontButton = self; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(deactivateOnClose:) - name:NSWindowWillCloseNotification - object:[NSFontPanel sharedFontPanel]]; - [self setState:NSOnState]; -} - -- (void)deactivateFontButton:(BOOL)activatingAnother -{ - NSFontManager *sfm; - - sfm = [NSFontManager sharedFontManager]; - [sfm setTarget:nil]; - if (!activatingAnother) - [[NSFontPanel sharedFontPanel] orderOut:self]; - activeFontButton = nil; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSWindowWillCloseNotification - object:[NSFontPanel sharedFontPanel]]; - [self setState:NSOffState]; -} - -- (void)deactivateOnClose:(NSNotification *)note -{ - [self deactivateFontButton:NO]; -} - -- (void)changeFont:(id)sender -{ - NSFontManager *fm; - NSFont *old; - uiFontButton *b = self->libui_b; - - fm = (NSFontManager *) sender; - old = self->libui_font; - self->libui_font = [sender convertFont:self->libui_font]; - // do this even if it returns the same; we don't own anything that isn't from a new or alloc/init - [self->libui_font retain]; - // do this second just in case - [old release]; - [self updateFontButtonLabel]; - (*(b->onChanged))(b, b->onChangedData); -} - -- (NSUInteger)validModesForFontPanel:(NSFontPanel *)panel -{ - return NSFontPanelFaceModeMask | - NSFontPanelSizeModeMask | - NSFontPanelCollectionModeMask; -} - -- (uiDrawTextFont *)libuiFont -{ - return mkTextFontFromNSFont(self->libui_font); -} - -@end - -uiDarwinControlAllDefaults(uiFontButton, button) - -// we do not want font change events to be sent to any controls other than the font buttons -// see main.m for more details -BOOL fontButtonInhibitSendAction(SEL sel, id from, id to) -{ - if (sel != @selector(changeFont:)) - return NO; - return ![to isKindOfClass:[fontButton class]]; -} - -// we do not want NSFontPanelValidation messages to be sent to any controls other than the font buttons when a font button is active -// see main.m for more details -BOOL fontButtonOverrideTargetForAction(SEL sel, id from, id to, id *override) -{ - if (activeFontButton == nil) - return NO; - if (sel != @selector(validModesForFontPanel:)) - return NO; - *override = activeFontButton; - return YES; -} - -// we also don't want the panel to be usable when there's a dialog running; see stddialogs.m for more details on that -// unfortunately the panel seems to ignore -setWorksWhenModal: so we'll have to do things ourselves -@interface nonModalFontPanel : NSFontPanel -@end - -@implementation nonModalFontPanel - -- (BOOL)worksWhenModal -{ - return NO; -} - -@end - -void setupFontPanel(void) -{ - [NSFontManager setFontPanelFactory:[nonModalFontPanel class]]; -} - -static void defaultOnChanged(uiFontButton *b, void *data) -{ - // do nothing -} - -uiDrawTextFont *uiFontButtonFont(uiFontButton *b) -{ - return [b->button libuiFont]; -} - -void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data) -{ - b->onChanged = f; - b->onChangedData = data; -} - -uiFontButton *uiNewFontButton(void) -{ - uiFontButton *b; - - uiDarwinNewControl(uiFontButton, b); - - b->button = [[fontButton alloc] initWithFrame:NSZeroRect libuiFontButton:b]; - uiDarwinSetControlFont(b->button, NSRegularControlSize); - - uiFontButtonOnChanged(b, defaultOnChanged, NULL); - - return b; -} diff --git a/src/libui_sdl/libui/darwin/form.m b/src/libui_sdl/libui/darwin/form.m deleted file mode 100644 index 7cdb965a..00000000 --- a/src/libui_sdl/libui/darwin/form.m +++ /dev/null @@ -1,561 +0,0 @@ -// 7 june 2016 -#import "uipriv_darwin.h" - -// TODO in the test program, sometimes one of the radio buttons can disappear (try when spaced) - -@interface formChild : NSView -@property uiControl *c; -@property (strong) NSTextField *label; -@property BOOL stretchy; -@property NSLayoutPriority oldHorzHuggingPri; -@property NSLayoutPriority oldVertHuggingPri; -@property (strong) NSLayoutConstraint *baseline; -@property (strong) NSLayoutConstraint *leading; -@property (strong) NSLayoutConstraint *top; -@property (strong) NSLayoutConstraint *trailing; -@property (strong) NSLayoutConstraint *bottom; -- (id)initWithLabel:(NSTextField *)l; -- (void)onDestroy; -- (NSView *)view; -@end - -@interface formView : NSView { - uiForm *f; - NSMutableArray *children; - int padded; - - NSLayoutConstraint *first; - NSMutableArray *inBetweens; - NSLayoutConstraint *last; - NSMutableArray *widths; - NSMutableArray *leadings; - NSMutableArray *middles; - NSMutableArray *trailings; -} -- (id)initWithF:(uiForm *)ff; -- (void)onDestroy; -- (void)removeOurConstraints; -- (void)syncEnableStates:(int)enabled; -- (CGFloat)paddingAmount; -- (void)establishOurConstraints; -- (void)append:(NSString *)label c:(uiControl *)c stretchy:(int)stretchy; -- (void)delete:(int)n; -- (int)isPadded; -- (void)setPadded:(int)p; -- (BOOL)hugsTrailing; -- (BOOL)hugsBottom; -- (int)nStretchy; -@end - -struct uiForm { - uiDarwinControl c; - formView *view; -}; - -@implementation formChild - -- (id)initWithLabel:(NSTextField *)l -{ - self = [super initWithFrame:NSZeroRect]; - if (self) { - self.label = l; - [self.label setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self.label setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; - [self.label setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationVertical]; - [self.label setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal]; - [self.label setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationVertical]; - [self addSubview:self.label]; - - self.leading = mkConstraint(self.label, NSLayoutAttributeLeading, - NSLayoutRelationGreaterThanOrEqual, - self, NSLayoutAttributeLeading, - 1, 0, - @"uiForm label leading"); - [self addConstraint:self.leading]; - self.top = mkConstraint(self.label, NSLayoutAttributeTop, - NSLayoutRelationEqual, - self, NSLayoutAttributeTop, - 1, 0, - @"uiForm label top"); - [self addConstraint:self.top]; - self.trailing = mkConstraint(self.label, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - self, NSLayoutAttributeTrailing, - 1, 0, - @"uiForm label trailing"); - [self addConstraint:self.trailing]; - self.bottom = mkConstraint(self.label, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - self, NSLayoutAttributeBottom, - 1, 0, - @"uiForm label bottom"); - [self addConstraint:self.bottom]; - } - return self; -} - -- (void)onDestroy -{ - [self removeConstraint:self.trailing]; - self.trailing = nil; - [self removeConstraint:self.top]; - self.top = nil; - [self removeConstraint:self.bottom]; - self.bottom = nil; - - [self.label removeFromSuperview]; - self.label = nil; -} - -- (NSView *)view -{ - return (NSView *) uiControlHandle(self.c); -} - -@end - -@implementation formView - -- (id)initWithF:(uiForm *)ff -{ - self = [super initWithFrame:NSZeroRect]; - if (self != nil) { - self->f = ff; - self->padded = 0; - self->children = [NSMutableArray new]; - - self->inBetweens = [NSMutableArray new]; - self->widths = [NSMutableArray new]; - self->leadings = [NSMutableArray new]; - self->middles = [NSMutableArray new]; - self->trailings = [NSMutableArray new]; - } - return self; -} - -- (void)onDestroy -{ - formChild *fc; - - [self removeOurConstraints]; - [self->inBetweens release]; - [self->widths release]; - [self->leadings release]; - [self->middles release]; - [self->trailings release]; - - for (fc in self->children) { - [self removeConstraint:fc.baseline]; - fc.baseline = nil; - uiControlSetParent(fc.c, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(fc.c), nil); - uiControlDestroy(fc.c); - [fc onDestroy]; - [fc removeFromSuperview]; - } - [self->children release]; -} - -- (void)removeOurConstraints -{ - if (self->first != nil) { - [self removeConstraint:self->first]; - [self->first release]; - self->first = nil; - } - if ([self->inBetweens count] != 0) { - [self removeConstraints:self->inBetweens]; - [self->inBetweens removeAllObjects]; - } - if (self->last != nil) { - [self removeConstraint:self->last]; - [self->last release]; - self->last = nil; - } - if ([self->widths count] != 0) { - [self removeConstraints:self->widths]; - [self->widths removeAllObjects]; - } - if ([self->leadings count] != 0) { - [self removeConstraints:self->leadings]; - [self->leadings removeAllObjects]; - } - if ([self->middles count] != 0) { - [self removeConstraints:self->middles]; - [self->middles removeAllObjects]; - } - if ([self->trailings count] != 0) { - [self removeConstraints:self->trailings]; - [self->trailings removeAllObjects]; - } -} - -- (void)syncEnableStates:(int)enabled -{ - formChild *fc; - - for (fc in self->children) - uiDarwinControlSyncEnableState(uiDarwinControl(fc.c), enabled); -} - -- (CGFloat)paddingAmount -{ - if (!self->padded) - return 0.0; - return uiDarwinPaddingAmount(NULL); -} - -- (void)establishOurConstraints -{ - formChild *fc; - CGFloat padding; - NSView *prev, *prevlabel; - NSLayoutConstraint *c; - - [self removeOurConstraints]; - if ([self->children count] == 0) - return; - padding = [self paddingAmount]; - - // first arrange the children vertically and make them the same width - prev = nil; - for (fc in self->children) { - [fc setHidden:!uiControlVisible(fc.c)]; - if (!uiControlVisible(fc.c)) - continue; - if (prev == nil) { // first view - self->first = mkConstraint(self, NSLayoutAttributeTop, - NSLayoutRelationEqual, - [fc view], NSLayoutAttributeTop, - 1, 0, - @"uiForm first vertical constraint"); - [self addConstraint:self->first]; - [self->first retain]; - prev = [fc view]; - prevlabel = fc; - continue; - } - // not the first; link it - c = mkConstraint(prev, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - [fc view], NSLayoutAttributeTop, - 1, -padding, - @"uiForm in-between vertical constraint"); - [self addConstraint:c]; - [self->inBetweens addObject:c]; - // and make the same width - c = mkConstraint(prev, NSLayoutAttributeWidth, - NSLayoutRelationEqual, - [fc view], NSLayoutAttributeWidth, - 1, 0, - @"uiForm control width constraint"); - [self addConstraint:c]; - [self->widths addObject:c]; - c = mkConstraint(prevlabel, NSLayoutAttributeWidth, - NSLayoutRelationEqual, - fc, NSLayoutAttributeWidth, - 1, 0, - @"uiForm label lwidth constraint"); - [self addConstraint:c]; - [self->widths addObject:c]; - prev = [fc view]; - prevlabel = fc; - } - if (prev == nil) // all hidden; act as if nothing there - return; - self->last = mkConstraint(prev, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - self, NSLayoutAttributeBottom, - 1, 0, - @"uiForm last vertical constraint"); - [self addConstraint:self->last]; - [self->last retain]; - - // now arrange the controls horizontally - for (fc in self->children) { - if (!uiControlVisible(fc.c)) - continue; - c = mkConstraint(self, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - fc, NSLayoutAttributeLeading, - 1, 0, - @"uiForm leading constraint"); - [self addConstraint:c]; - [self->leadings addObject:c]; - // coerce the control to be as wide as possible - // see http://stackoverflow.com/questions/37710892/in-auto-layout-i-set-up-labels-that-shouldnt-grow-horizontally-and-controls-th - c = mkConstraint(self, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - [fc view], NSLayoutAttributeLeading, - 1, 0, - @"uiForm leading constraint"); - [c setPriority:NSLayoutPriorityDefaultHigh]; - [self addConstraint:c]; - [self->leadings addObject:c]; - c = mkConstraint(fc, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - [fc view], NSLayoutAttributeLeading, - 1, -padding, - @"uiForm middle constraint"); - [self addConstraint:c]; - [self->middles addObject:c]; - c = mkConstraint([fc view], NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - self, NSLayoutAttributeTrailing, - 1, 0, - @"uiForm trailing constraint"); - [self addConstraint:c]; - [self->trailings addObject:c]; - // TODO - c = mkConstraint(fc, NSLayoutAttributeBottom, - NSLayoutRelationLessThanOrEqual, - self, NSLayoutAttributeBottom, - 1, 0, - @"TODO"); - [self addConstraint:c]; - [self->trailings addObject:c]; - } - - // and make all stretchy controls have the same height - prev = nil; - for (fc in self->children) { - if (!uiControlVisible(fc.c)) - continue; - if (!fc.stretchy) - continue; - if (prev == nil) { - prev = [fc view]; - continue; - } - c = mkConstraint([fc view], NSLayoutAttributeHeight, - NSLayoutRelationEqual, - prev, NSLayoutAttributeHeight, - 1, 0, - @"uiForm stretchy constraint"); - [self addConstraint:c]; - // TODO make a dedicated array for this - [self->leadings addObject:c]; - } - - // we don't arrange the labels vertically; that's done when we add the control since those constraints don't need to change (they just need to be at their baseline) -} - -- (void)append:(NSString *)label c:(uiControl *)c stretchy:(int)stretchy -{ - formChild *fc; - NSLayoutPriority priority; - NSLayoutAttribute attribute; - int oldnStretchy; - - fc = [[formChild alloc] initWithLabel:newLabel(label)]; - fc.c = c; - fc.stretchy = stretchy; - fc.oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(fc.c), NSLayoutConstraintOrientationHorizontal); - fc.oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(fc.c), NSLayoutConstraintOrientationVertical); - [fc setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self addSubview:fc]; - - uiControlSetParent(fc.c, uiControl(self->f)); - uiDarwinControlSetSuperview(uiDarwinControl(fc.c), self); - uiDarwinControlSyncEnableState(uiDarwinControl(fc.c), uiControlEnabledToUser(uiControl(self->f))); - - // if a control is stretchy, it should not hug vertically - // otherwise, it should *forcibly* hug - if (fc.stretchy) - priority = NSLayoutPriorityDefaultLow; - else - // LONGTERM will default high work? - priority = NSLayoutPriorityRequired; - uiDarwinControlSetHuggingPriority(uiDarwinControl(fc.c), priority, NSLayoutConstraintOrientationVertical); - // make sure controls don't hug their horizontal direction so they fill the width of the view - uiDarwinControlSetHuggingPriority(uiDarwinControl(fc.c), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationHorizontal); - - // and constrain the baselines to position the label vertically - // if the view is a scroll view, align tops, not baselines - // this is what Interface Builder does - attribute = NSLayoutAttributeBaseline; - if ([[fc view] isKindOfClass:[NSScrollView class]]) - attribute = NSLayoutAttributeTop; - fc.baseline = mkConstraint(fc.label, attribute, - NSLayoutRelationEqual, - [fc view], attribute, - 1, 0, - @"uiForm baseline constraint"); - [self addConstraint:fc.baseline]; - - oldnStretchy = [self nStretchy]; - [self->children addObject:fc]; - - [self establishOurConstraints]; - if (fc.stretchy) - if (oldnStretchy == 0) - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->f)); - - [fc release]; // we don't need the initial reference now -} - -- (void)delete:(int)n -{ - formChild *fc; - int stretchy; - - fc = (formChild *) [self->children objectAtIndex:n]; - stretchy = fc.stretchy; - - uiControlSetParent(fc.c, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(fc.c), nil); - - uiDarwinControlSetHuggingPriority(uiDarwinControl(fc.c), fc.oldHorzHuggingPri, NSLayoutConstraintOrientationHorizontal); - uiDarwinControlSetHuggingPriority(uiDarwinControl(fc.c), fc.oldVertHuggingPri, NSLayoutConstraintOrientationVertical); - - [fc onDestroy]; - [self->children removeObjectAtIndex:n]; - - [self establishOurConstraints]; - if (stretchy) - if ([self nStretchy] == 0) - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->f)); -} - -- (int)isPadded -{ - return self->padded; -} - -- (void)setPadded:(int)p -{ - CGFloat padding; - NSLayoutConstraint *c; - - self->padded = p; - padding = [self paddingAmount]; - for (c in self->inBetweens) - [c setConstant:-padding]; - for (c in self->middles) - [c setConstant:-padding]; -} - -- (BOOL)hugsTrailing -{ - return YES; // always hug trailing -} - -- (BOOL)hugsBottom -{ - // only hug if we have stretchy - return [self nStretchy] != 0; -} - -- (int)nStretchy -{ - formChild *fc; - int n; - - n = 0; - for (fc in self->children) { - if (!uiControlVisible(fc.c)) - continue; - if (fc.stretchy) - n++; - } - return n; -} - -@end - -static void uiFormDestroy(uiControl *c) -{ - uiForm *f = uiForm(c); - - [f->view onDestroy]; - [f->view release]; - uiFreeControl(uiControl(f)); -} - -uiDarwinControlDefaultHandle(uiForm, view) -uiDarwinControlDefaultParent(uiForm, view) -uiDarwinControlDefaultSetParent(uiForm, view) -uiDarwinControlDefaultToplevel(uiForm, view) -uiDarwinControlDefaultVisible(uiForm, view) -uiDarwinControlDefaultShow(uiForm, view) -uiDarwinControlDefaultHide(uiForm, view) -uiDarwinControlDefaultEnabled(uiForm, view) -uiDarwinControlDefaultEnable(uiForm, view) -uiDarwinControlDefaultDisable(uiForm, view) - -static void uiFormSyncEnableState(uiDarwinControl *c, int enabled) -{ - uiForm *f = uiForm(c); - - if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(f), enabled)) - return; - [f->view syncEnableStates:enabled]; -} - -uiDarwinControlDefaultSetSuperview(uiForm, view) - -static BOOL uiFormHugsTrailingEdge(uiDarwinControl *c) -{ - uiForm *f = uiForm(c); - - return [f->view hugsTrailing]; -} - -static BOOL uiFormHugsBottom(uiDarwinControl *c) -{ - uiForm *f = uiForm(c); - - return [f->view hugsBottom]; -} - -static void uiFormChildEdgeHuggingChanged(uiDarwinControl *c) -{ - uiForm *f = uiForm(c); - - [f->view establishOurConstraints]; -} - -uiDarwinControlDefaultHuggingPriority(uiForm, view) -uiDarwinControlDefaultSetHuggingPriority(uiForm, view) - -static void uiFormChildVisibilityChanged(uiDarwinControl *c) -{ - uiForm *f = uiForm(c); - - [f->view establishOurConstraints]; -} - -void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy) -{ - // LONGTERM on other platforms - // or at leat allow this and implicitly turn it into a spacer - if (c == NULL) - userbug("You cannot add NULL to a uiForm."); - [f->view append:toNSString(label) c:c stretchy:stretchy]; -} - -void uiFormDelete(uiForm *f, int n) -{ - [f->view delete:n]; -} - -int uiFormPadded(uiForm *f) -{ - return [f->view isPadded]; -} - -void uiFormSetPadded(uiForm *f, int padded) -{ - [f->view setPadded:padded]; -} - -uiForm *uiNewForm(void) -{ - uiForm *f; - - uiDarwinNewControl(uiForm, f); - - f->view = [[formView alloc] initWithF:f]; - - return f; -} diff --git a/src/libui_sdl/libui/darwin/grid.m b/src/libui_sdl/libui/darwin/grid.m deleted file mode 100644 index d5c5fb1e..00000000 --- a/src/libui_sdl/libui/darwin/grid.m +++ /dev/null @@ -1,800 +0,0 @@ -// 11 june 2016 -#import "uipriv_darwin.h" - -// TODO the assorted test doesn't work right at all - -@interface gridChild : NSView -@property uiControl *c; -@property int left; -@property int top; -@property int xspan; -@property int yspan; -@property int hexpand; -@property uiAlign halign; -@property int vexpand; -@property uiAlign valign; - -@property (strong) NSLayoutConstraint *leadingc; -@property (strong) NSLayoutConstraint *topc; -@property (strong) NSLayoutConstraint *trailingc; -@property (strong) NSLayoutConstraint *bottomc; -@property (strong) NSLayoutConstraint *xcenterc; -@property (strong) NSLayoutConstraint *ycenterc; - -@property NSLayoutPriority oldHorzHuggingPri; -@property NSLayoutPriority oldVertHuggingPri; -- (void)setC:(uiControl *)c grid:(uiGrid *)g; -- (void)onDestroy; -- (NSView *)view; -@end - -@interface gridView : NSView { - uiGrid *g; - NSMutableArray *children; - int padded; - - NSMutableArray *edges; - NSMutableArray *inBetweens; - - NSMutableArray *emptyCellViews; -} -- (id)initWithG:(uiGrid *)gg; -- (void)onDestroy; -- (void)removeOurConstraints; -- (void)syncEnableStates:(int)enabled; -- (CGFloat)paddingAmount; -- (void)establishOurConstraints; -- (void)append:(gridChild *)gc; -- (void)insert:(gridChild *)gc after:(uiControl *)c at:(uiAt)at; -- (int)isPadded; -- (void)setPadded:(int)p; -- (BOOL)hugsTrailing; -- (BOOL)hugsBottom; -- (int)nhexpand; -- (int)nvexpand; -@end - -struct uiGrid { - uiDarwinControl c; - gridView *view; -}; - -@implementation gridChild - -- (void)setC:(uiControl *)c grid:(uiGrid *)g -{ - self.c = c; - self.oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(self.c), NSLayoutConstraintOrientationHorizontal); - self.oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(self.c), NSLayoutConstraintOrientationVertical); - - uiControlSetParent(self.c, uiControl(g)); - uiDarwinControlSetSuperview(uiDarwinControl(self.c), self); - uiDarwinControlSyncEnableState(uiDarwinControl(self.c), uiControlEnabledToUser(uiControl(g))); - - if (self.halign == uiAlignStart || self.halign == uiAlignFill) { - self.leadingc = mkConstraint(self, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - [self view], NSLayoutAttributeLeading, - 1, 0, - @"uiGrid child horizontal alignment start constraint"); - [self addConstraint:self.leadingc]; - } - if (self.halign == uiAlignCenter) { - self.xcenterc = mkConstraint(self, NSLayoutAttributeCenterX, - NSLayoutRelationEqual, - [self view], NSLayoutAttributeCenterX, - 1, 0, - @"uiGrid child horizontal alignment center constraint"); - [self addConstraint:self.xcenterc]; - } - if (self.halign == uiAlignEnd || self.halign == uiAlignFill) { - self.trailingc = mkConstraint(self, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - [self view], NSLayoutAttributeTrailing, - 1, 0, - @"uiGrid child horizontal alignment end constraint"); - [self addConstraint:self.trailingc]; - } - - if (self.valign == uiAlignStart || self.valign == uiAlignFill) { - self.topc = mkConstraint(self, NSLayoutAttributeTop, - NSLayoutRelationEqual, - [self view], NSLayoutAttributeTop, - 1, 0, - @"uiGrid child vertical alignment start constraint"); - [self addConstraint:self.topc]; - } - if (self.valign == uiAlignCenter) { - self.ycenterc = mkConstraint(self, NSLayoutAttributeCenterY, - NSLayoutRelationEqual, - [self view], NSLayoutAttributeCenterY, - 1, 0, - @"uiGrid child vertical alignment center constraint"); - [self addConstraint:self.ycenterc]; - } - if (self.valign == uiAlignEnd || self.valign == uiAlignFill) { - self.bottomc = mkConstraint(self, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - [self view], NSLayoutAttributeBottom, - 1, 0, - @"uiGrid child vertical alignment end constraint"); - [self addConstraint:self.bottomc]; - } -} - -- (void)onDestroy -{ - if (self.leadingc != nil) { - [self removeConstraint:self.leadingc]; - self.leadingc = nil; - } - if (self.topc != nil) { - [self removeConstraint:self.topc]; - self.topc = nil; - } - if (self.trailingc != nil) { - [self removeConstraint:self.trailingc]; - self.trailingc = nil; - } - if (self.bottomc != nil) { - [self removeConstraint:self.bottomc]; - self.bottomc = nil; - } - if (self.xcenterc != nil) { - [self removeConstraint:self.xcenterc]; - self.xcenterc = nil; - } - if (self.ycenterc != nil) { - [self removeConstraint:self.ycenterc]; - self.ycenterc = nil; - } - - uiControlSetParent(self.c, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(self.c), nil); - uiDarwinControlSetHuggingPriority(uiDarwinControl(self.c), self.oldHorzHuggingPri, NSLayoutConstraintOrientationHorizontal); - uiDarwinControlSetHuggingPriority(uiDarwinControl(self.c), self.oldVertHuggingPri, NSLayoutConstraintOrientationVertical); -} - -- (NSView *)view -{ - return (NSView *) uiControlHandle(self.c); -} - -@end - -@implementation gridView - -- (id)initWithG:(uiGrid *)gg -{ - self = [super initWithFrame:NSZeroRect]; - if (self != nil) { - self->g = gg; - self->padded = 0; - self->children = [NSMutableArray new]; - - self->edges = [NSMutableArray new]; - self->inBetweens = [NSMutableArray new]; - - self->emptyCellViews = [NSMutableArray new]; - } - return self; -} - -- (void)onDestroy -{ - gridChild *gc; - - [self removeOurConstraints]; - [self->edges release]; - [self->inBetweens release]; - - [self->emptyCellViews release]; - - for (gc in self->children) { - [gc onDestroy]; - uiControlDestroy(gc.c); - [gc removeFromSuperview]; - } - [self->children release]; -} - -- (void)removeOurConstraints -{ - NSView *v; - - if ([self->edges count] != 0) { - [self removeConstraints:self->edges]; - [self->edges removeAllObjects]; - } - if ([self->inBetweens count] != 0) { - [self removeConstraints:self->inBetweens]; - [self->inBetweens removeAllObjects]; - } - - for (v in self->emptyCellViews) - [v removeFromSuperview]; - [self->emptyCellViews removeAllObjects]; -} - -- (void)syncEnableStates:(int)enabled -{ - gridChild *gc; - - for (gc in self->children) - uiDarwinControlSyncEnableState(uiDarwinControl(gc.c), enabled); -} - -- (CGFloat)paddingAmount -{ - if (!self->padded) - return 0.0; - return uiDarwinPaddingAmount(NULL); -} - -// LONGTERM stop early if all controls are hidden -- (void)establishOurConstraints -{ - gridChild *gc; - CGFloat padding; - int xmin, ymin; - int xmax, ymax; - int xcount, ycount; - BOOL first; - int **gg; - NSView ***gv; - BOOL **gspan; - int x, y; - int i; - NSLayoutConstraint *c; - int firstx, firsty; - BOOL *hexpand, *vexpand; - BOOL doit; - BOOL onlyEmptyAndSpanning; - - [self removeOurConstraints]; - if ([self->children count] == 0) - return; - padding = [self paddingAmount]; - - // first, figure out the minimum and maximum row and column numbers - // ignore hidden controls - first = YES; - for (gc in self->children) { - // this bit is important: it ensures row ymin and column xmin have at least one cell to draw, so the onlyEmptyAndSpanning logic below will never run on those rows - if (!uiControlVisible(gc.c)) - continue; - if (first) { - xmin = gc.left; - ymin = gc.top; - xmax = gc.left + gc.xspan; - ymax = gc.top + gc.yspan; - first = NO; - continue; - } - if (xmin > gc.left) - xmin = gc.left; - if (ymin > gc.top) - ymin = gc.top; - if (xmax < (gc.left + gc.xspan)) - xmax = gc.left + gc.xspan; - if (ymax < (gc.top + gc.yspan)) - ymax = gc.top + gc.yspan; - } - if (first != NO) // the entire grid is hidden; do nothing - return; - xcount = xmax - xmin; - ycount = ymax - ymin; - - // now build a topological map of the grid gg[y][x] - // also figure out which cells contain spanned views so they can be ignored later - // treat hidden controls by keeping the indices -1 - gg = (int **) uiAlloc(ycount * sizeof (int *), "int[][]"); - gspan = (BOOL **) uiAlloc(ycount * sizeof (BOOL *), "BOOL[][]"); - for (y = 0; y < ycount; y++) { - gg[y] = (int *) uiAlloc(xcount * sizeof (int), "int[]"); - gspan[y] = (BOOL *) uiAlloc(xcount * sizeof (BOOL), "BOOL[]"); - for (x = 0; x < xcount; x++) - gg[y][x] = -1; // empty - } - for (i = 0; i < [self->children count]; i++) { - gc = (gridChild *) [self->children objectAtIndex:i]; - if (!uiControlVisible(gc.c)) - continue; - for (y = gc.top; y < gc.top + gc.yspan; y++) - for (x = gc.left; x < gc.left + gc.xspan; x++) { - gg[y - ymin][x - xmin] = i; - if (x != gc.left || y != gc.top) - gspan[y - ymin][x - xmin] = YES; - } - } - - // if a row or column only contains emptys and spanning cells of a opposite-direction spannings, remove it by duplicating the previous row or column - for (y = 0; y < ycount; y++) { - onlyEmptyAndSpanning = YES; - for (x = 0; x < xcount; x++) - if (gg[y][x] != -1) { - gc = (gridChild *) [self->children objectAtIndex:gg[y][x]]; - if (gc.yspan == 1 || gc.top - ymin == y) { - onlyEmptyAndSpanning = NO; - break; - } - } - if (onlyEmptyAndSpanning) - for (x = 0; x < xcount; x++) { - gg[y][x] = gg[y - 1][x]; - gspan[y][x] = YES; - } - } - for (x = 0; x < xcount; x++) { - onlyEmptyAndSpanning = YES; - for (y = 0; y < ycount; y++) - if (gg[y][x] != -1) { - gc = (gridChild *) [self->children objectAtIndex:gg[y][x]]; - if (gc.xspan == 1 || gc.left - xmin == x) { - onlyEmptyAndSpanning = NO; - break; - } - } - if (onlyEmptyAndSpanning) - for (y = 0; y < ycount; y++) { - gg[y][x] = gg[y][x - 1]; - gspan[y][x] = YES; - } - } - - // now build a topological map of the grid's views gv[y][x] - // for any empty cell, create a dummy view - gv = (NSView ***) uiAlloc(ycount * sizeof (NSView **), "NSView *[][]"); - for (y = 0; y < ycount; y++) { - gv[y] = (NSView **) uiAlloc(xcount * sizeof (NSView *), "NSView *[]"); - for (x = 0; x < xcount; x++) - if (gg[y][x] == -1) { - gv[y][x] = [[NSView alloc] initWithFrame:NSZeroRect]; - [gv[y][x] setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self addSubview:gv[y][x]]; - [self->emptyCellViews addObject:gv[y][x]]; - } else { - gc = (gridChild *) [self->children objectAtIndex:gg[y][x]]; - gv[y][x] = gc; - } - } - - // now figure out which rows and columns really expand - hexpand = (BOOL *) uiAlloc(xcount * sizeof (BOOL), "BOOL[]"); - vexpand = (BOOL *) uiAlloc(ycount * sizeof (BOOL), "BOOL[]"); - // first, which don't span - for (gc in self->children) { - if (!uiControlVisible(gc.c)) - continue; - if (gc.hexpand && gc.xspan == 1) - hexpand[gc.left - xmin] = YES; - if (gc.vexpand && gc.yspan == 1) - vexpand[gc.top - ymin] = YES; - } - // second, which do span - // the way we handle this is simple: if none of the spanned rows/columns expand, make all rows/columns expand - for (gc in self->children) { - if (!uiControlVisible(gc.c)) - continue; - if (gc.hexpand && gc.xspan != 1) { - doit = YES; - for (x = gc.left; x < gc.left + gc.xspan; x++) - if (hexpand[x - xmin]) { - doit = NO; - break; - } - if (doit) - for (x = gc.left; x < gc.left + gc.xspan; x++) - hexpand[x - xmin] = YES; - } - if (gc.vexpand && gc.yspan != 1) { - doit = YES; - for (y = gc.top; y < gc.top + gc.yspan; y++) - if (vexpand[y - ymin]) { - doit = NO; - break; - } - if (doit) - for (y = gc.top; y < gc.top + gc.yspan; y++) - vexpand[y - ymin] = YES; - } - } - - // now establish all the edge constraints - // leading and trailing edges - for (y = 0; y < ycount; y++) { - c = mkConstraint(self, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - gv[y][0], NSLayoutAttributeLeading, - 1, 0, - @"uiGrid leading edge constraint"); - [self addConstraint:c]; - [self->edges addObject:c]; - c = mkConstraint(self, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - gv[y][xcount - 1], NSLayoutAttributeTrailing, - 1, 0, - @"uiGrid trailing edge constraint"); - [self addConstraint:c]; - [self->edges addObject:c]; - } - // top and bottom edges - for (x = 0; x < xcount; x++) { - c = mkConstraint(self, NSLayoutAttributeTop, - NSLayoutRelationEqual, - gv[0][x], NSLayoutAttributeTop, - 1, 0, - @"uiGrid top edge constraint"); - [self addConstraint:c]; - [self->edges addObject:c]; - c = mkConstraint(self, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - gv[ycount - 1][x], NSLayoutAttributeBottom, - 1, 0, - @"uiGrid bottom edge constraint"); - [self addConstraint:c]; - [self->edges addObject:c]; - } - - // now align leading and top edges - // do NOT align spanning cells! - for (x = 0; x < xcount; x++) { - for (y = 0; y < ycount; y++) - if (!gspan[y][x]) - break; - firsty = y; - for (y++; y < ycount; y++) { - if (gspan[y][x]) - continue; - c = mkConstraint(gv[firsty][x], NSLayoutAttributeLeading, - NSLayoutRelationEqual, - gv[y][x], NSLayoutAttributeLeading, - 1, 0, - @"uiGrid column leading constraint"); - [self addConstraint:c]; - [self->edges addObject:c]; - } - } - for (y = 0; y < ycount; y++) { - for (x = 0; x < xcount; x++) - if (!gspan[y][x]) - break; - firstx = x; - for (x++; x < xcount; x++) { - if (gspan[y][x]) - continue; - c = mkConstraint(gv[y][firstx], NSLayoutAttributeTop, - NSLayoutRelationEqual, - gv[y][x], NSLayoutAttributeTop, - 1, 0, - @"uiGrid row top constraint"); - [self addConstraint:c]; - [self->edges addObject:c]; - } - } - - // now string adjacent views together - for (y = 0; y < ycount; y++) - for (x = 1; x < xcount; x++) - if (gv[y][x - 1] != gv[y][x]) { - c = mkConstraint(gv[y][x - 1], NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - gv[y][x], NSLayoutAttributeLeading, - 1, -padding, - @"uiGrid internal horizontal constraint"); - [self addConstraint:c]; - [self->inBetweens addObject:c]; - } - for (x = 0; x < xcount; x++) - for (y = 1; y < ycount; y++) - if (gv[y - 1][x] != gv[y][x]) { - c = mkConstraint(gv[y - 1][x], NSLayoutAttributeBottom, - NSLayoutRelationEqual, - gv[y][x], NSLayoutAttributeTop, - 1, -padding, - @"uiGrid internal vertical constraint"); - [self addConstraint:c]; - [self->inBetweens addObject:c]; - } - - // now set priorities for all widgets that expand or not - // if a cell is in an expanding row, OR If it spans, then it must be willing to stretch - // otherwise, it tries not to - // note we don't use NSLayoutPriorityRequired as that will cause things to squish when they shouldn't - for (gc in self->children) { - NSLayoutPriority priority; - - if (!uiControlVisible(gc.c)) - continue; - if (hexpand[gc.left - xmin] || gc.xspan != 1) - priority = NSLayoutPriorityDefaultLow; - else - priority = NSLayoutPriorityDefaultHigh; - uiDarwinControlSetHuggingPriority(uiDarwinControl(gc.c), priority, NSLayoutConstraintOrientationHorizontal); - // same for vertical direction - if (vexpand[gc.top - ymin] || gc.yspan != 1) - priority = NSLayoutPriorityDefaultLow; - else - priority = NSLayoutPriorityDefaultHigh; - uiDarwinControlSetHuggingPriority(uiDarwinControl(gc.c), priority, NSLayoutConstraintOrientationVertical); - } - - // TODO make all expanding rows/columns the same height/width - - // and finally clean up - uiFree(hexpand); - uiFree(vexpand); - for (y = 0; y < ycount; y++) { - uiFree(gg[y]); - uiFree(gv[y]); - uiFree(gspan[y]); - } - uiFree(gg); - uiFree(gv); - uiFree(gspan); -} - -- (void)append:(gridChild *)gc -{ - BOOL update; - int oldnh, oldnv; - - [gc setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self addSubview:gc]; - - // no need to set priority here; that's done in establishOurConstraints - - oldnh = [self nhexpand]; - oldnv = [self nvexpand]; - [self->children addObject:gc]; - - [self establishOurConstraints]; - update = NO; - if (gc.hexpand) - if (oldnh == 0) - update = YES; - if (gc.vexpand) - if (oldnv == 0) - update = YES; - if (update) - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->g)); - - [gc release]; // we don't need the initial reference now -} - -- (void)insert:(gridChild *)gc after:(uiControl *)c at:(uiAt)at -{ - gridChild *other; - BOOL found; - - found = NO; - for (other in self->children) - if (other.c == c) { - found = YES; - break; - } - if (!found) - userbug("Existing control %p is not in grid %p; you cannot add other controls next to it", c, self->g); - - switch (at) { - case uiAtLeading: - gc.left = other.left - gc.xspan; - gc.top = other.top; - break; - case uiAtTop: - gc.left = other.left; - gc.top = other.top - gc.yspan; - break; - case uiAtTrailing: - gc.left = other.left + other.xspan; - gc.top = other.top; - break; - case uiAtBottom: - gc.left = other.left; - gc.top = other.top + other.yspan; - break; - // TODO add error checks to ALL enums - } - - [self append:gc]; -} - -- (int)isPadded -{ - return self->padded; -} - -- (void)setPadded:(int)p -{ - CGFloat padding; - NSLayoutConstraint *c; - -#if 0 /* TODO */ -dispatch_after( -dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), -dispatch_get_main_queue(), -^{ [[self window] visualizeConstraints:[self constraints]]; } -); -#endif - self->padded = p; - padding = [self paddingAmount]; - for (c in self->inBetweens) - switch ([c firstAttribute]) { - case NSLayoutAttributeLeading: - case NSLayoutAttributeTop: - [c setConstant:padding]; - break; - case NSLayoutAttributeTrailing: - case NSLayoutAttributeBottom: - [c setConstant:-padding]; - break; - } -} - -- (BOOL)hugsTrailing -{ - // only hug if we have horizontally expanding - return [self nhexpand] != 0; -} - -- (BOOL)hugsBottom -{ - // only hug if we have vertically expanding - return [self nvexpand] != 0; -} - -- (int)nhexpand -{ - gridChild *gc; - int n; - - n = 0; - for (gc in self->children) { - if (!uiControlVisible(gc.c)) - continue; - if (gc.hexpand) - n++; - } - return n; -} - -- (int)nvexpand -{ - gridChild *gc; - int n; - - n = 0; - for (gc in self->children) { - if (!uiControlVisible(gc.c)) - continue; - if (gc.vexpand) - n++; - } - return n; -} - -@end - -static void uiGridDestroy(uiControl *c) -{ - uiGrid *g = uiGrid(c); - - [g->view onDestroy]; - [g->view release]; - uiFreeControl(uiControl(g)); -} - -uiDarwinControlDefaultHandle(uiGrid, view) -uiDarwinControlDefaultParent(uiGrid, view) -uiDarwinControlDefaultSetParent(uiGrid, view) -uiDarwinControlDefaultToplevel(uiGrid, view) -uiDarwinControlDefaultVisible(uiGrid, view) -uiDarwinControlDefaultShow(uiGrid, view) -uiDarwinControlDefaultHide(uiGrid, view) -uiDarwinControlDefaultEnabled(uiGrid, view) -uiDarwinControlDefaultEnable(uiGrid, view) -uiDarwinControlDefaultDisable(uiGrid, view) - -static void uiGridSyncEnableState(uiDarwinControl *c, int enabled) -{ - uiGrid *g = uiGrid(c); - - if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(g), enabled)) - return; - [g->view syncEnableStates:enabled]; -} - -uiDarwinControlDefaultSetSuperview(uiGrid, view) - -static BOOL uiGridHugsTrailingEdge(uiDarwinControl *c) -{ - uiGrid *g = uiGrid(c); - - return [g->view hugsTrailing]; -} - -static BOOL uiGridHugsBottom(uiDarwinControl *c) -{ - uiGrid *g = uiGrid(c); - - return [g->view hugsBottom]; -} - -static void uiGridChildEdgeHuggingChanged(uiDarwinControl *c) -{ - uiGrid *g = uiGrid(c); - - [g->view establishOurConstraints]; -} - -uiDarwinControlDefaultHuggingPriority(uiGrid, view) -uiDarwinControlDefaultSetHuggingPriority(uiGrid, view) - -static void uiGridChildVisibilityChanged(uiDarwinControl *c) -{ - uiGrid *g = uiGrid(c); - - [g->view establishOurConstraints]; -} - -static gridChild *toChild(uiControl *c, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign, uiGrid *g) -{ - gridChild *gc; - - if (xspan < 0) - userbug("You cannot have a negative xspan in a uiGrid cell."); - if (yspan < 0) - userbug("You cannot have a negative yspan in a uiGrid cell."); - gc = [gridChild new]; - gc.xspan = xspan; - gc.yspan = yspan; - gc.hexpand = hexpand; - gc.halign = halign; - gc.vexpand = vexpand; - gc.valign = valign; - [gc setC:c grid:g]; - return gc; -} - -void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - gridChild *gc; - - // LONGTERM on other platforms - // or at leat allow this and implicitly turn it into a spacer - if (c == NULL) - userbug("You cannot add NULL to a uiGrid."); - gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign, g); - gc.left = left; - gc.top = top; - [g->view append:gc]; -} - -void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - gridChild *gc; - - gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign, g); - [g->view insert:gc after:existing at:at]; -} - -int uiGridPadded(uiGrid *g) -{ - return [g->view isPadded]; -} - -void uiGridSetPadded(uiGrid *g, int padded) -{ - [g->view setPadded:padded]; -} - -uiGrid *uiNewGrid(void) -{ - uiGrid *g; - - uiDarwinNewControl(uiGrid, g); - - g->view = [[gridView alloc] initWithG:g]; - - return g; -} diff --git a/src/libui_sdl/libui/darwin/group.m b/src/libui_sdl/libui/darwin/group.m deleted file mode 100644 index 0050bbdd..00000000 --- a/src/libui_sdl/libui/darwin/group.m +++ /dev/null @@ -1,194 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -struct uiGroup { - uiDarwinControl c; - NSBox *box; - uiControl *child; - NSLayoutPriority oldHorzHuggingPri; - NSLayoutPriority oldVertHuggingPri; - int margined; - struct singleChildConstraints constraints; - NSLayoutPriority horzHuggingPri; - NSLayoutPriority vertHuggingPri; -}; - -static void removeConstraints(uiGroup *g) -{ - // set to contentView instead of to the box itself, otherwise we get clipping underneath the label - singleChildConstraintsRemove(&(g->constraints), [g->box contentView]); -} - -static void uiGroupDestroy(uiControl *c) -{ - uiGroup *g = uiGroup(c); - - removeConstraints(g); - if (g->child != NULL) { - uiControlSetParent(g->child, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(g->child), nil); - uiControlDestroy(g->child); - } - [g->box release]; - uiFreeControl(uiControl(g)); -} - -uiDarwinControlDefaultHandle(uiGroup, box) -uiDarwinControlDefaultParent(uiGroup, box) -uiDarwinControlDefaultSetParent(uiGroup, box) -uiDarwinControlDefaultToplevel(uiGroup, box) -uiDarwinControlDefaultVisible(uiGroup, box) -uiDarwinControlDefaultShow(uiGroup, box) -uiDarwinControlDefaultHide(uiGroup, box) -uiDarwinControlDefaultEnabled(uiGroup, box) -uiDarwinControlDefaultEnable(uiGroup, box) -uiDarwinControlDefaultDisable(uiGroup, box) - -static void uiGroupSyncEnableState(uiDarwinControl *c, int enabled) -{ - uiGroup *g = uiGroup(c); - - if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(g), enabled)) - return; - if (g->child != NULL) - uiDarwinControlSyncEnableState(uiDarwinControl(g->child), enabled); -} - -uiDarwinControlDefaultSetSuperview(uiGroup, box) - -static void groupRelayout(uiGroup *g) -{ - NSView *childView; - - removeConstraints(g); - if (g->child == NULL) - return; - childView = (NSView *) uiControlHandle(g->child); - singleChildConstraintsEstablish(&(g->constraints), - [g->box contentView], childView, - uiDarwinControlHugsTrailingEdge(uiDarwinControl(g->child)), - uiDarwinControlHugsBottom(uiDarwinControl(g->child)), - g->margined, - @"uiGroup"); - // needed for some very rare drawing errors... - jiggleViewLayout(g->box); -} - -// TODO rename these since I'm starting to get confused by what they mean by hugging -BOOL uiGroupHugsTrailingEdge(uiDarwinControl *c) -{ - uiGroup *g = uiGroup(c); - - // TODO make a function? - return g->horzHuggingPri < NSLayoutPriorityWindowSizeStayPut; -} - -BOOL uiGroupHugsBottom(uiDarwinControl *c) -{ - uiGroup *g = uiGroup(c); - - return g->vertHuggingPri < NSLayoutPriorityWindowSizeStayPut; -} - -static void uiGroupChildEdgeHuggingChanged(uiDarwinControl *c) -{ - uiGroup *g = uiGroup(c); - - groupRelayout(g); -} - -static NSLayoutPriority uiGroupHuggingPriority(uiDarwinControl *c, NSLayoutConstraintOrientation orientation) -{ - uiGroup *g = uiGroup(c); - - if (orientation == NSLayoutConstraintOrientationHorizontal) - return g->horzHuggingPri; - return g->vertHuggingPri; -} - -static void uiGroupSetHuggingPriority(uiDarwinControl *c, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation) -{ - uiGroup *g = uiGroup(c); - - if (orientation == NSLayoutConstraintOrientationHorizontal) - g->horzHuggingPri = priority; - else - g->vertHuggingPri = priority; - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(g)); -} - -static void uiGroupChildVisibilityChanged(uiDarwinControl *c) -{ - uiGroup *g = uiGroup(c); - - groupRelayout(g); -} - -char *uiGroupTitle(uiGroup *g) -{ - return uiDarwinNSStringToText([g->box title]); -} - -void uiGroupSetTitle(uiGroup *g, const char *title) -{ - [g->box setTitle:toNSString(title)]; -} - -void uiGroupSetChild(uiGroup *g, uiControl *child) -{ - NSView *childView; - - if (g->child != NULL) { - removeConstraints(g); - uiDarwinControlSetHuggingPriority(uiDarwinControl(g->child), g->oldHorzHuggingPri, NSLayoutConstraintOrientationHorizontal); - uiDarwinControlSetHuggingPriority(uiDarwinControl(g->child), g->oldVertHuggingPri, NSLayoutConstraintOrientationVertical); - uiControlSetParent(g->child, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(g->child), nil); - } - g->child = child; - if (g->child != NULL) { - childView = (NSView *) uiControlHandle(g->child); - uiControlSetParent(g->child, uiControl(g)); - uiDarwinControlSetSuperview(uiDarwinControl(g->child), [g->box contentView]); - uiDarwinControlSyncEnableState(uiDarwinControl(g->child), uiControlEnabledToUser(uiControl(g))); - // don't hug, just in case we're a stretchy group - g->oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(g->child), NSLayoutConstraintOrientationHorizontal); - g->oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(g->child), NSLayoutConstraintOrientationVertical); - uiDarwinControlSetHuggingPriority(uiDarwinControl(g->child), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationHorizontal); - uiDarwinControlSetHuggingPriority(uiDarwinControl(g->child), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationVertical); - } - groupRelayout(g); -} - -int uiGroupMargined(uiGroup *g) -{ - return g->margined; -} - -void uiGroupSetMargined(uiGroup *g, int margined) -{ - g->margined = margined; - singleChildConstraintsSetMargined(&(g->constraints), g->margined); -} - -uiGroup *uiNewGroup(const char *title) -{ - uiGroup *g; - - uiDarwinNewControl(uiGroup, g); - - g->box = [[NSBox alloc] initWithFrame:NSZeroRect]; - [g->box setTitle:toNSString(title)]; - [g->box setBoxType:NSBoxPrimary]; - [g->box setBorderType:NSLineBorder]; - [g->box setTransparent:NO]; - [g->box setTitlePosition:NSAtTop]; - // we can't use uiDarwinSetControlFont() because the selector is different - [g->box setTitleFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; - - // default to low hugging to not hug edges - g->horzHuggingPri = NSLayoutPriorityDefaultLow; - g->vertHuggingPri = NSLayoutPriorityDefaultLow; - - return g; -} diff --git a/src/libui_sdl/libui/darwin/image.m b/src/libui_sdl/libui/darwin/image.m deleted file mode 100644 index b62de31d..00000000 --- a/src/libui_sdl/libui/darwin/image.m +++ /dev/null @@ -1,82 +0,0 @@ -// 25 june 2016 -#import "uipriv_darwin.h" - -struct uiImage { - NSImage *i; - NSSize size; - NSMutableArray *swizzled; -}; - -uiImage *uiNewImage(double width, double height) -{ - uiImage *i; - - i = uiNew(uiImage); - i->size = NSMakeSize(width, height); - i->i = [[NSImage alloc] initWithSize:i->size]; - i->swizzled = [NSMutableArray new]; - return i; -} - -void uiFreeImage(uiImage *i) -{ - NSValue *v; - - [i->i release]; - // to be safe, do this after releasing the image - for (v in i->swizzled) - uiFree([v pointerValue]); - [i->swizzled release]; - uiFree(i); -} - -void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, int pixelStride) -{ - NSBitmapImageRep *repCalibrated, *repsRGB; - uint8_t *swizzled, *bp, *sp; - int x, y; - unsigned char *pix[1]; - - // OS X demands that R and B are in the opposite order from what we expect - // we must swizzle :( - // LONGTERM test on a big-endian system - swizzled = (uint8_t *) uiAlloc((pixelStride * pixelHeight * 4) * sizeof (uint8_t), "uint8_t[]"); - bp = (uint8_t *) pixels; - sp = swizzled; - for (y = 0; y < pixelHeight * pixelStride; y += pixelStride) - for (x = 0; x < pixelStride; x++) { - sp[0] = bp[2]; - sp[1] = bp[1]; - sp[2] = bp[0]; - sp[3] = bp[3]; - sp += 4; - bp += 4; - } - - pix[0] = (unsigned char *) swizzled; - repCalibrated = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:pix - pixelsWide:pixelWidth - pixelsHigh:pixelHeight - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bitmapFormat:0 - bytesPerRow:pixelStride - bitsPerPixel:32]; - repsRGB = [repCalibrated bitmapImageRepByRetaggingWithColorSpace:[NSColorSpace sRGBColorSpace]]; - [repCalibrated release]; - - [i->i addRepresentation:repsRGB]; - [repsRGB setSize:i->size]; - [repsRGB release]; - - // we need to keep swizzled alive for NSBitmapImageRep - [i->swizzled addObject:[NSValue valueWithPointer:swizzled]]; -} - -NSImage *imageImage(uiImage *i) -{ - return i->i; -} diff --git a/src/libui_sdl/libui/darwin/label.m b/src/libui_sdl/libui/darwin/label.m deleted file mode 100644 index 897bc3ff..00000000 --- a/src/libui_sdl/libui/darwin/label.m +++ /dev/null @@ -1,43 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -struct uiLabel { - uiDarwinControl c; - NSTextField *textfield; -}; - -uiDarwinControlAllDefaults(uiLabel, textfield) - -char *uiLabelText(uiLabel *l) -{ - return uiDarwinNSStringToText([l->textfield stringValue]); -} - -void uiLabelSetText(uiLabel *l, const char *text) -{ - [l->textfield setStringValue:toNSString(text)]; -} - -NSTextField *newLabel(NSString *str) -{ - NSTextField *tf; - - tf = [[NSTextField alloc] initWithFrame:NSZeroRect]; - [tf setStringValue:str]; - [tf setEditable:NO]; - [tf setSelectable:NO]; - [tf setDrawsBackground:NO]; - finishNewTextField(tf, NO); - return tf; -} - -uiLabel *uiNewLabel(const char *text) -{ - uiLabel *l; - - uiDarwinNewControl(uiLabel, l); - - l->textfield = newLabel(toNSString(text)); - - return l; -} diff --git a/src/libui_sdl/libui/darwin/main.m b/src/libui_sdl/libui/darwin/main.m deleted file mode 100644 index 59a8683b..00000000 --- a/src/libui_sdl/libui/darwin/main.m +++ /dev/null @@ -1,239 +0,0 @@ -// 6 april 2015 -#import "uipriv_darwin.h" - -static BOOL canQuit = NO; -static NSAutoreleasePool *globalPool; -static applicationClass *app; -static appDelegate *delegate; - -static BOOL (^isRunning)(void); -static BOOL stepsIsRunning; - -@implementation applicationClass - -- (void)sendEvent:(NSEvent *)e -{ - if (sendAreaEvents(e) != 0) - return; - [super sendEvent:e]; -} - -// NSColorPanel always sends changeColor: to the first responder regardless of whether there's a target set on it -// we can override it here (see colorbutton.m) -// thanks to mikeash in irc.freenode.net/#macdev for informing me this is how the first responder chain is initiated -// it turns out NSFontManager also sends changeFont: through this; let's inhibit that here too (see fontbutton.m) -- (BOOL)sendAction:(SEL)sel to:(id)to from:(id)from -{ - if (colorButtonInhibitSendAction(sel, from, to)) - return NO; - if (fontButtonInhibitSendAction(sel, from, to)) - return NO; - return [super sendAction:sel to:to from:from]; -} - -// likewise, NSFontManager also sends NSFontPanelValidation messages to the first responder, however it does NOT use sendAction:from:to:! -// instead, it uses this one (thanks swillits in irc.freenode.net/#macdev) -// we also need to override it (see fontbutton.m) -- (id)targetForAction:(SEL)sel to:(id)to from:(id)from -{ - id override; - - if (fontButtonOverrideTargetForAction(sel, from, to, &override)) - return override; - return [super targetForAction:sel to:to from:from]; -} - -// hey look! we're overriding terminate:! -// we're going to make sure we can go back to main() whether Cocoa likes it or not! -// and just how are we going to do that, hm? -// (note: this is called after applicationShouldTerminate:) -- (void)terminate:(id)sender -{ - // yes that's right folks: DO ABSOLUTELY NOTHING. - // the magic is [NSApp run] will just... stop. - - // well let's not do nothing; let's actually quit our graceful way - NSEvent *e; - - if (!canQuit) - implbug("call to [NSApp terminate:] when not ready to terminate; definitely contact andlabs"); - - [realNSApp() stop:realNSApp()]; - // stop: won't register until another event has passed; let's synthesize one - e = [NSEvent otherEventWithType:NSApplicationDefined - location:NSZeroPoint - modifierFlags:0 - timestamp:[[NSProcessInfo processInfo] systemUptime] - windowNumber:0 - context:[NSGraphicsContext currentContext] - subtype:0 - data1:0 - data2:0]; - [realNSApp() postEvent:e atStart:NO]; // let pending events take priority (this is what PostQuitMessage() on Windows does so we have to do it here too for parity; thanks to mikeash in irc.freenode.net/#macdev for confirming that this parameter should indeed be NO) - - // and in case uiMainSteps() was called - stepsIsRunning = NO; -} - -@end - -@implementation appDelegate - -- (void)dealloc -{ - // Apple docs: "Don't Use Accessor Methods in Initializer Methods and dealloc" - [_menuManager release]; - [super dealloc]; -} - -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app -{ - // for debugging - NSLog(@"in applicationShouldTerminate:"); - if (shouldQuit()) { - canQuit = YES; - // this will call terminate:, which is the same as uiQuit() - return NSTerminateNow; - } - return NSTerminateCancel; -} - -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app -{ - return NO; -} - -@end - -uiInitOptions options; - -const char *uiInit(uiInitOptions *o) -{ - @autoreleasepool { - options = *o; - app = [[applicationClass sharedApplication] retain]; - // don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy! - // see https://github.com/andlabs/ui/issues/6 - [realNSApp() setActivationPolicy:NSApplicationActivationPolicyRegular]; - delegate = [appDelegate new]; - [realNSApp() setDelegate:delegate]; - - initAlloc(); - - // always do this so we always have an application menu - appDelegate().menuManager = [[menuManager new] autorelease]; - [realNSApp() setMainMenu:[appDelegate().menuManager makeMenubar]]; - - setupFontPanel(); - } - - globalPool = [[NSAutoreleasePool alloc] init]; - - return NULL; -} - -void uiUninit(void) -{ - if (!globalPool) { - userbug("You must call uiInit() first!"); - } - [globalPool release]; - - @autoreleasepool { - [delegate release]; - [realNSApp() setDelegate:nil]; - [app release]; - uninitAlloc(); - } -} - -void uiFreeInitError(const char *err) -{ -} - -void uiMain(void) -{ - isRunning = ^{ - return [realNSApp() isRunning]; - }; - [realNSApp() run]; -} - -void uiMainSteps(void) -{ - // SDL does this and it seems to be necessary for the menubar to work (see #182) - [realNSApp() finishLaunching]; - isRunning = ^{ - return stepsIsRunning; - }; - stepsIsRunning = YES; -} - -int uiMainStep(int wait) -{ - struct nextEventArgs nea; - - nea.mask = NSAnyEventMask; - - // ProPuke did this in his original PR requesting this - // I'm not sure if this will work, but I assume it will... - nea.duration = [NSDate distantPast]; - if (wait) // but this is normal so it will work - nea.duration = [NSDate distantFuture]; - - nea.mode = NSDefaultRunLoopMode; - nea.dequeue = YES; - - return mainStep(&nea, ^(NSEvent *e) { - return NO; - }); -} - -// see also: -// - http://www.cocoawithlove.com/2009/01/demystifying-nsapplication-by.html -// - https://github.com/gnustep/gui/blob/master/Source/NSApplication.m -int mainStep(struct nextEventArgs *nea, BOOL (^interceptEvent)(NSEvent *e)) -{ - NSDate *expire; - NSEvent *e; - NSEventType type; - - @autoreleasepool { - if (!isRunning()) - return 0; - - e = [realNSApp() nextEventMatchingMask:nea->mask - untilDate:nea->duration - inMode:nea->mode - dequeue:nea->dequeue]; - if (e == nil) - return 1; - - type = [e type]; - if (!interceptEvent(e)) - [realNSApp() sendEvent:e]; - [realNSApp() updateWindows]; - - // GNUstep does this - // it also updates the Services menu but there doesn't seem to be a public API for that so - if (type != NSPeriodic && type != NSMouseMoved) - [[realNSApp() mainMenu] update]; - - return 1; - } -} - -void uiQuit(void) -{ - canQuit = YES; - [realNSApp() terminate:realNSApp()]; -} - -// thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this -// LONGTERM will dispatch_get_main_queue() break after _CFRunLoopSetCurrent()? -void uiQueueMain(void (*f)(void *data), void *data) -{ - // dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently - // the signature of f matches dispatch_function_t - dispatch_async_f(dispatch_get_main_queue(), data, f); -} diff --git a/src/libui_sdl/libui/darwin/map.m b/src/libui_sdl/libui/darwin/map.m deleted file mode 100644 index 46a7b8d2..00000000 --- a/src/libui_sdl/libui/darwin/map.m +++ /dev/null @@ -1,59 +0,0 @@ -// 17 august 2015 -#import "uipriv_darwin.h" - -// unfortunately NSMutableDictionary copies its keys, meaning we can't use it for pointers -// hence, this file -// we could expose a NSMapTable directly, but let's treat all pointers as opaque and hide the implementation, just to be safe and prevent even more rewrites later -struct mapTable { - NSMapTable *m; -}; - -struct mapTable *newMap(void) -{ - struct mapTable *m; - - m = uiNew(struct mapTable); - m->m = [[NSMapTable alloc] initWithKeyOptions:(NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality) - valueOptions:(NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality) - capacity:0]; - return m; -} - -void mapDestroy(struct mapTable *m) -{ - if ([m->m count] != 0) - implbug("attempt to destroy map with items inside"); - [m->m release]; - uiFree(m); -} - -void *mapGet(struct mapTable *m, void *key) -{ - return NSMapGet(m->m, key); -} - -void mapSet(struct mapTable *m, void *key, void *value) -{ - NSMapInsert(m->m, key, value); -} - -void mapDelete(struct mapTable *m, void *key) -{ - NSMapRemove(m->m, key); -} - -void mapWalk(struct mapTable *m, void (*f)(void *key, void *value)) -{ - NSMapEnumerator e = NSEnumerateMapTable(m->m); - void *k = NULL; - void *v = NULL; - while (NSNextMapEnumeratorPair(&e, &k, &v)) { - f(k, v); - } - NSEndMapTableEnumeration(&e); -} - -void mapReset(struct mapTable *m) -{ - NSResetMapTable(m->m); -} diff --git a/src/libui_sdl/libui/darwin/menu.m b/src/libui_sdl/libui/darwin/menu.m deleted file mode 100644 index 735cac50..00000000 --- a/src/libui_sdl/libui/darwin/menu.m +++ /dev/null @@ -1,368 +0,0 @@ -// 28 april 2015 -#import "uipriv_darwin.h" - -static NSMutableArray *menus = nil; -static BOOL menusFinalized = NO; - -struct uiMenu { - NSMenu *menu; - NSMenuItem *item; - NSMutableArray *items; -}; - -struct uiMenuItem { - NSMenuItem *item; - int type; - BOOL disabled; - void (*onClicked)(uiMenuItem *, uiWindow *, void *); - void *onClickedData; -}; - -enum { - typeRegular, - typeCheckbox, - typeQuit, - typePreferences, - typeAbout, - typeSeparator, -}; - -static void mapItemReleaser(void *key, void *value) -{ - uiMenuItem *item; - - item = (uiMenuItem *)value; - [item->item release]; -} - -@implementation menuManager - -- (id)init -{ - self = [super init]; - if (self) { - self->items = newMap(); - self->hasQuit = NO; - self->hasPreferences = NO; - self->hasAbout = NO; - } - return self; -} - -- (void)dealloc -{ - mapWalk(self->items, mapItemReleaser); - mapReset(self->items); - mapDestroy(self->items); - uninitMenus(); - [super dealloc]; -} - -- (IBAction)onClicked:(id)sender -{ - uiMenuItem *item; - - item = (uiMenuItem *) mapGet(self->items, sender); - if (item->type == typeCheckbox) - uiMenuItemSetChecked(item, !uiMenuItemChecked(item)); - // use the key window as the source of the menu event; it's the active window - (*(item->onClicked))(item, windowFromNSWindow([realNSApp() keyWindow]), item->onClickedData); -} - -- (IBAction)onQuitClicked:(id)sender -{ - if (shouldQuit()) - uiQuit(); -} - -- (void)register:(NSMenuItem *)item to:(uiMenuItem *)smi -{ - switch (smi->type) { - case typeQuit: - if (self->hasQuit) - userbug("You can't have multiple Quit menu items in one program."); - self->hasQuit = YES; - break; - case typePreferences: - if (self->hasPreferences) - userbug("You can't have multiple Preferences menu items in one program."); - self->hasPreferences = YES; - break; - case typeAbout: - if (self->hasAbout) - userbug("You can't have multiple About menu items in one program."); - self->hasAbout = YES; - break; - } - mapSet(self->items, item, smi); -} - -// on OS X there are two ways to handle menu items being enabled or disabled: automatically and manually -// unfortunately, the application menu requires automatic menu handling for the Hide, Hide Others, and Show All items to work correctly -// therefore, we have to handle enabling of the other options ourselves -- (BOOL)validateMenuItem:(NSMenuItem *)item -{ - uiMenuItem *smi; - - // disable the special items if they aren't present - if (item == self.quitItem && !self->hasQuit) - return NO; - if (item == self.preferencesItem && !self->hasPreferences) - return NO; - if (item == self.aboutItem && !self->hasAbout) - return NO; - // then poll the item's enabled/disabled state - smi = (uiMenuItem *) mapGet(self->items, item); - return !smi->disabled; -} - -// Cocoa constructs the default application menu by hand for each program; that's what MainMenu.[nx]ib does -- (void)buildApplicationMenu:(NSMenu *)menubar -{ - NSString *appName; - NSMenuItem *appMenuItem; - NSMenu *appMenu; - NSMenuItem *item; - NSString *title; - NSMenu *servicesMenu; - - // note: no need to call setAppleMenu: on this anymore; see https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKitOlderNotes/#X10_6Notes - appName = [[NSProcessInfo processInfo] processName]; - appMenuItem = [[[NSMenuItem alloc] initWithTitle:appName action:NULL keyEquivalent:@""] autorelease]; - appMenu = [[[NSMenu alloc] initWithTitle:appName] autorelease]; - [appMenuItem setSubmenu:appMenu]; - [menubar addItem:appMenuItem]; - - // first is About - title = [@"About " stringByAppendingString:appName]; - item = [[[NSMenuItem alloc] initWithTitle:title action:@selector(onClicked:) keyEquivalent:@""] autorelease]; - [item setTarget:self]; - [appMenu addItem:item]; - self.aboutItem = item; - - [appMenu addItem:[NSMenuItem separatorItem]]; - - // next is Preferences - item = [[[NSMenuItem alloc] initWithTitle:@"Preferences…" action:@selector(onClicked:) keyEquivalent:@","] autorelease]; - [item setTarget:self]; - [appMenu addItem:item]; - self.preferencesItem = item; - - [appMenu addItem:[NSMenuItem separatorItem]]; - - // next is Services - item = [[[NSMenuItem alloc] initWithTitle:@"Services" action:NULL keyEquivalent:@""] autorelease]; - servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease]; - [item setSubmenu:servicesMenu]; - [realNSApp() setServicesMenu:servicesMenu]; - [appMenu addItem:item]; - - [appMenu addItem:[NSMenuItem separatorItem]]; - - // next are the three hiding options - title = [@"Hide " stringByAppendingString:appName]; - item = [[[NSMenuItem alloc] initWithTitle:title action:@selector(hide:) keyEquivalent:@"h"] autorelease]; - // the .xib file says they go to -1 ("First Responder", which sounds wrong...) - // to do that, we simply leave the target as nil - [appMenu addItem:item]; - item = [[[NSMenuItem alloc] initWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"] autorelease]; - [item setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)]; - [appMenu addItem:item]; - item = [[[NSMenuItem alloc] initWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""] autorelease]; - [appMenu addItem:item]; - - [appMenu addItem:[NSMenuItem separatorItem]]; - - // and finally Quit - // DON'T use @selector(terminate:) as the action; we handle termination ourselves - title = [@"Quit " stringByAppendingString:appName]; - item = [[[NSMenuItem alloc] initWithTitle:title action:@selector(onQuitClicked:) keyEquivalent:@"q"] autorelease]; - [item setTarget:self]; - [appMenu addItem:item]; - self.quitItem = item; -} - -- (NSMenu *)makeMenubar -{ - NSMenu *menubar; - - menubar = [[[NSMenu alloc] initWithTitle:@""] autorelease]; - [self buildApplicationMenu:menubar]; - return menubar; -} - -@end - -static void defaultOnClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - // do nothing -} - -void uiMenuItemEnable(uiMenuItem *item) -{ - item->disabled = NO; - // we don't need to explicitly update the menus here; they'll be updated the next time they're opened (thanks mikeash in irc.freenode.net/#macdev) -} - -void uiMenuItemDisable(uiMenuItem *item) -{ - item->disabled = YES; -} - -void uiMenuItemOnClicked(uiMenuItem *item, void (*f)(uiMenuItem *, uiWindow *, void *), void *data) -{ - if (item->type == typeQuit) - userbug("You can't call uiMenuItemOnClicked() on a Quit item; use uiOnShouldQuit() instead."); - item->onClicked = f; - item->onClickedData = data; -} - -int uiMenuItemChecked(uiMenuItem *item) -{ - return [item->item state] != NSOffState; -} - -void uiMenuItemSetChecked(uiMenuItem *item, int checked) -{ - NSInteger state; - - state = NSOffState; - if ([item->item state] == NSOffState) - state = NSOnState; - [item->item setState:state]; -} - -static uiMenuItem *newItem(uiMenu *m, int type, const char *name) -{ - @autoreleasepool { - - uiMenuItem *item; - - if (menusFinalized) - userbug("You can't create a new menu item after menus have been finalized."); - - item = uiNew(uiMenuItem); - - item->type = type; - switch (item->type) { - case typeQuit: - item->item = [appDelegate().menuManager.quitItem retain]; - break; - case typePreferences: - item->item = [appDelegate().menuManager.preferencesItem retain]; - break; - case typeAbout: - item->item = [appDelegate().menuManager.aboutItem retain]; - break; - case typeSeparator: - item->item = [[NSMenuItem separatorItem] retain]; - [m->menu addItem:item->item]; - break; - default: - item->item = [[NSMenuItem alloc] initWithTitle:toNSString(name) action:@selector(onClicked:) keyEquivalent:@""]; - [item->item setTarget:appDelegate().menuManager]; - [m->menu addItem:item->item]; - break; - } - - [appDelegate().menuManager register:item->item to:item]; - item->onClicked = defaultOnClicked; - - [m->items addObject:[NSValue valueWithPointer:item]]; - - return item; - - } // @autoreleasepool -} - -uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name) -{ - return newItem(m, typeRegular, name); -} - -uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name) -{ - return newItem(m, typeCheckbox, name); -} - -uiMenuItem *uiMenuAppendQuitItem(uiMenu *m) -{ - // duplicate check is in the register:to: selector - return newItem(m, typeQuit, NULL); -} - -uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m) -{ - // duplicate check is in the register:to: selector - return newItem(m, typePreferences, NULL); -} - -uiMenuItem *uiMenuAppendAboutItem(uiMenu *m) -{ - // duplicate check is in the register:to: selector - return newItem(m, typeAbout, NULL); -} - -void uiMenuAppendSeparator(uiMenu *m) -{ - newItem(m, typeSeparator, NULL); -} - -uiMenu *uiNewMenu(const char *name) -{ - @autoreleasepool { - - uiMenu *m; - - if (menusFinalized) - userbug("You can't create a new menu after menus have been finalized."); - if (menus == nil) - menus = [NSMutableArray new]; - - m = uiNew(uiMenu); - - m->menu = [[NSMenu alloc] initWithTitle:toNSString(name)]; - // use automatic menu item enabling for all menus for consistency's sake - - m->item = [[NSMenuItem alloc] initWithTitle:toNSString(name) action:NULL keyEquivalent:@""]; - [m->item setSubmenu:m->menu]; - - m->items = [NSMutableArray new]; - - [[realNSApp() mainMenu] addItem:m->item]; - - [menus addObject:[NSValue valueWithPointer:m]]; - - return m; - - } // @autoreleasepool -} - -void finalizeMenus(void) -{ - menusFinalized = YES; -} - -void uninitMenus(void) -{ - if (menus == NULL) - return; - [menus enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) { - NSValue *v; - uiMenu *m; - - v = (NSValue *) obj; - m = (uiMenu *) [v pointerValue]; - [m->items enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) { - NSValue *v; - uiMenuItem *mi; - - v = (NSValue *) obj; - mi = (uiMenuItem *) [v pointerValue]; - uiFree(mi); - }]; - [m->items release]; - uiFree(m); - }]; - [menus release]; -} diff --git a/src/libui_sdl/libui/darwin/multilineentry.m b/src/libui_sdl/libui/darwin/multilineentry.m deleted file mode 100644 index 605e9004..00000000 --- a/src/libui_sdl/libui/darwin/multilineentry.m +++ /dev/null @@ -1,233 +0,0 @@ -// 8 december 2015 -#import "uipriv_darwin.h" - -// NSTextView has no intrinsic content size by default, which wreaks havoc on a pure-Auto Layout system -// we'll have to take over to get it to work -// see also http://stackoverflow.com/questions/24210153/nstextview-not-properly-resizing-with-auto-layout and http://stackoverflow.com/questions/11237622/using-autolayout-with-expanding-nstextviews -@interface intrinsicSizeTextView : NSTextView { - uiMultilineEntry *libui_e; -} -- (id)initWithFrame:(NSRect)r e:(uiMultilineEntry *)e; -@end - -struct uiMultilineEntry { - uiDarwinControl c; - NSScrollView *sv; - intrinsicSizeTextView *tv; - struct scrollViewData *d; - void (*onChanged)(uiMultilineEntry *, void *); - void *onChangedData; - BOOL changing; -}; - -@implementation intrinsicSizeTextView - -- (id)initWithFrame:(NSRect)r e:(uiMultilineEntry *)e -{ - self = [super initWithFrame:r]; - if (self) - self->libui_e = e; - return self; -} - -- (NSSize)intrinsicContentSize -{ - NSTextContainer *textContainer; - NSLayoutManager *layoutManager; - NSRect rect; - - textContainer = [self textContainer]; - layoutManager = [self layoutManager]; - [layoutManager ensureLayoutForTextContainer:textContainer]; - rect = [layoutManager usedRectForTextContainer:textContainer]; - return rect.size; -} - -- (void)didChangeText -{ - [super didChangeText]; - [self invalidateIntrinsicContentSize]; - if (!self->libui_e->changing) - (*(self->libui_e->onChanged))(self->libui_e, self->libui_e->onChangedData); -} - -@end - -uiDarwinControlAllDefaultsExceptDestroy(uiMultilineEntry, sv) - -static void uiMultilineEntryDestroy(uiControl *c) -{ - uiMultilineEntry *e = uiMultilineEntry(c); - - scrollViewFreeData(e->sv, e->d); - [e->tv release]; - [e->sv release]; - uiFreeControl(uiControl(e)); -} - -static void defaultOnChanged(uiMultilineEntry *e, void *data) -{ - // do nothing -} - -char *uiMultilineEntryText(uiMultilineEntry *e) -{ - return uiDarwinNSStringToText([e->tv string]); -} - -void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text) -{ - [[e->tv textStorage] replaceCharactersInRange:NSMakeRange(0, [[e->tv string] length]) - withString:toNSString(text)]; - // must be called explicitly according to the documentation of shouldChangeTextInRange:replacementString: - e->changing = YES; - [e->tv didChangeText]; - e->changing = NO; -} - -// TODO scroll to end? -void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text) -{ - [[e->tv textStorage] replaceCharactersInRange:NSMakeRange([[e->tv string] length], 0) - withString:toNSString(text)]; - e->changing = YES; - [e->tv didChangeText]; - e->changing = NO; -} - -void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *e, void *data), void *data) -{ - e->onChanged = f; - e->onChangedData = data; -} - -int uiMultilineEntryReadOnly(uiMultilineEntry *e) -{ - return [e->tv isEditable] == NO; -} - -void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly) -{ - BOOL editable; - - editable = YES; - if (readonly) - editable = NO; - [e->tv setEditable:editable]; -} - -static uiMultilineEntry *finishMultilineEntry(BOOL hscroll) -{ - uiMultilineEntry *e; - NSFont *font; - struct scrollViewCreateParams p; - - uiDarwinNewControl(uiMultilineEntry, e); - - e->tv = [[intrinsicSizeTextView alloc] initWithFrame:NSZeroRect e:e]; - - // verified against Interface Builder for a sufficiently customized text view - - // NSText properties: - // this is what Interface Builder sets the background color to - [e->tv setBackgroundColor:[NSColor colorWithCalibratedWhite:1.0 alpha:1.0]]; - [e->tv setDrawsBackground:YES]; - [e->tv setEditable:YES]; - [e->tv setSelectable:YES]; - [e->tv setFieldEditor:NO]; - [e->tv setRichText:NO]; - [e->tv setImportsGraphics:NO]; - [e->tv setUsesFontPanel:NO]; - [e->tv setRulerVisible:NO]; - // we'll handle font last - // while setAlignment: has been around since 10.0, the named constant "NSTextAlignmentNatural" seems to have only been introduced in 10.11 -#define ourNSTextAlignmentNatural 4 - [e->tv setAlignment:ourNSTextAlignmentNatural]; - // textColor is set to nil, just keep the dfault - [e->tv setBaseWritingDirection:NSWritingDirectionNatural]; - [e->tv setHorizontallyResizable:NO]; - [e->tv setVerticallyResizable:YES]; - - // NSTextView properties: - [e->tv setAllowsDocumentBackgroundColorChange:NO]; - [e->tv setAllowsUndo:YES]; - // default paragraph style is nil; keep default - [e->tv setAllowsImageEditing:NO]; - [e->tv setAutomaticQuoteSubstitutionEnabled:NO]; - [e->tv setAutomaticLinkDetectionEnabled:NO]; - [e->tv setDisplaysLinkToolTips:YES]; - [e->tv setUsesRuler:NO]; - [e->tv setUsesInspectorBar:NO]; - [e->tv setSelectionGranularity:NSSelectByCharacter]; - // there is a dedicated named insertion point color but oh well - [e->tv setInsertionPointColor:[NSColor controlTextColor]]; - // typing attributes is nil; keep default (we change it below for fonts though) - [e->tv setSmartInsertDeleteEnabled:NO]; - [e->tv setContinuousSpellCheckingEnabled:NO]; - [e->tv setGrammarCheckingEnabled:NO]; - [e->tv setUsesFindPanel:YES]; - [e->tv setEnabledTextCheckingTypes:0]; - [e->tv setAutomaticDashSubstitutionEnabled:NO]; - [e->tv setAutomaticDataDetectionEnabled:NO]; - [e->tv setAutomaticSpellingCorrectionEnabled:NO]; - [e->tv setAutomaticTextReplacementEnabled:NO]; - [e->tv setUsesFindBar:NO]; - [e->tv setIncrementalSearchingEnabled:NO]; - - // NSTextContainer properties: - [[e->tv textContainer] setWidthTracksTextView:YES]; - [[e->tv textContainer] setHeightTracksTextView:NO]; - - // NSLayoutManager properties: - [[e->tv layoutManager] setAllowsNonContiguousLayout:YES]; - - // now just to be safe; this will do some of the above but whatever - disableAutocorrect(e->tv); - - // see https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html - // notice we don't use the Auto Layout code; see scrollview.m for more details - [e->tv setMaxSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)]; - [e->tv setVerticallyResizable:YES]; - [e->tv setHorizontallyResizable:hscroll]; - if (hscroll) { - [e->tv setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; - [[e->tv textContainer] setWidthTracksTextView:NO]; - } else { - [e->tv setAutoresizingMask:NSViewWidthSizable]; - [[e->tv textContainer] setWidthTracksTextView:YES]; - } - [[e->tv textContainer] setContainerSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)]; - - // don't use uiDarwinSetControlFont() directly; we have to do a little extra work to set the font - font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; - [e->tv setTypingAttributes:[NSDictionary - dictionaryWithObject:font - forKey:NSFontAttributeName]]; - // e->tv font from Interface Builder is nil, but setFont:nil throws an exception - // let's just set it to the standard control font anyway, just to be safe - [e->tv setFont:font]; - - memset(&p, 0, sizeof (struct scrollViewCreateParams)); - p.DocumentView = e->tv; - // this is what Interface Builder sets it to - p.BackgroundColor = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0]; - p.DrawsBackground = YES; - p.Bordered = YES; - p.HScroll = hscroll; - p.VScroll = YES; - e->sv = mkScrollView(&p, &(e->d)); - - uiMultilineEntryOnChanged(e, defaultOnChanged, NULL); - - return e; -} - -uiMultilineEntry *uiNewMultilineEntry(void) -{ - return finishMultilineEntry(NO); -} - -uiMultilineEntry *uiNewNonWrappingMultilineEntry(void) -{ - return finishMultilineEntry(YES); -} diff --git a/src/libui_sdl/libui/darwin/progressbar.m b/src/libui_sdl/libui/darwin/progressbar.m deleted file mode 100644 index b5382281..00000000 --- a/src/libui_sdl/libui/darwin/progressbar.m +++ /dev/null @@ -1,78 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// NSProgressIndicator has no intrinsic width by default; use the default width in Interface Builder -#define progressIndicatorWidth 100 - -@interface intrinsicWidthNSProgressIndicator : NSProgressIndicator -@end - -@implementation intrinsicWidthNSProgressIndicator - -- (NSSize)intrinsicContentSize -{ - NSSize s; - - s = [super intrinsicContentSize]; - s.width = progressIndicatorWidth; - return s; -} - -@end - -struct uiProgressBar { - uiDarwinControl c; - NSProgressIndicator *pi; -}; - -uiDarwinControlAllDefaults(uiProgressBar, pi) - -int uiProgressBarValue(uiProgressBar *p) -{ - if ([p->pi isIndeterminate]) - return -1; - return [p->pi doubleValue]; -} - -void uiProgressBarSetValue(uiProgressBar *p, int value) -{ - if (value == -1) { - [p->pi setIndeterminate:YES]; - [p->pi startAnimation:p->pi]; - return; - } - - if ([p->pi isIndeterminate]) { - [p->pi setIndeterminate:NO]; - [p->pi stopAnimation:p->pi]; - } - - if (value < 0 || value > 100) - userbug("Value %d out of range for a uiProgressBar.", value); - - // on 10.8 there's an animation when the progress bar increases, just like with Aero - if (value == 100) { - [p->pi setMaxValue:101]; - [p->pi setDoubleValue:101]; - [p->pi setDoubleValue:100]; - [p->pi setMaxValue:100]; - return; - } - [p->pi setDoubleValue:((double) (value + 1))]; - [p->pi setDoubleValue:((double) value)]; -} - -uiProgressBar *uiNewProgressBar(void) -{ - uiProgressBar *p; - - uiDarwinNewControl(uiProgressBar, p); - - p->pi = [[intrinsicWidthNSProgressIndicator alloc] initWithFrame:NSZeroRect]; - [p->pi setControlSize:NSRegularControlSize]; - [p->pi setBezeled:YES]; - [p->pi setStyle:NSProgressIndicatorBarStyle]; - [p->pi setIndeterminate:NO]; - - return p; -} diff --git a/src/libui_sdl/libui/darwin/radiobuttons.m b/src/libui_sdl/libui/darwin/radiobuttons.m deleted file mode 100644 index 25d773c9..00000000 --- a/src/libui_sdl/libui/darwin/radiobuttons.m +++ /dev/null @@ -1,207 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// TODO resizing the controlgallery vertically causes the third button to still resize :| - -// In the old days you would use a NSMatrix for this; as of OS X 10.8 this was deprecated and now you need just a bunch of NSButtons with the same superview AND same action method. -// This is documented on the NSMatrix page, but the rest of the OS X documentation says to still use NSMatrix. -// NSMatrix has weird quirks anyway... - -// LONGTERM 6 units of spacing between buttons, as suggested by Interface Builder? - -@interface radioButtonsDelegate : NSObject { - uiRadioButtons *libui_r; -} -- (id)initWithR:(uiRadioButtons *)r; -- (IBAction)onClicked:(id)sender; -@end - -struct uiRadioButtons { - uiDarwinControl c; - NSView *view; - NSMutableArray *buttons; - NSMutableArray *constraints; - NSLayoutConstraint *lastv; - radioButtonsDelegate *delegate; - void (*onSelected)(uiRadioButtons *, void *); - void *onSelectedData; -}; - -@implementation radioButtonsDelegate - -- (id)initWithR:(uiRadioButtons *)r -{ - self = [super init]; - if (self) - self->libui_r = r; - return self; -} - -- (IBAction)onClicked:(id)sender -{ - uiRadioButtons *r = self->libui_r; - - (*(r->onSelected))(r, r->onSelectedData); -} - -@end - -uiDarwinControlAllDefaultsExceptDestroy(uiRadioButtons, view) - -static void defaultOnSelected(uiRadioButtons *r, void *data) -{ - // do nothing -} - -static void uiRadioButtonsDestroy(uiControl *c) -{ - uiRadioButtons *r = uiRadioButtons(c); - NSButton *b; - - // drop the constraints - [r->view removeConstraints:r->constraints]; - [r->constraints release]; - if (r->lastv != nil) - [r->lastv release]; - // destroy the buttons - for (b in r->buttons) { - [b setTarget:nil]; - [b removeFromSuperview]; - } - [r->buttons release]; - // destroy the delegate - [r->delegate release]; - // and destroy ourselves - [r->view release]; - uiFreeControl(uiControl(r)); -} - -static NSButton *buttonAt(uiRadioButtons *r, int n) -{ - return (NSButton *) [r->buttons objectAtIndex:n]; -} - -void uiRadioButtonsAppend(uiRadioButtons *r, const char *text) -{ - NSButton *b, *b2; - NSLayoutConstraint *constraint; - - b = [[NSButton alloc] initWithFrame:NSZeroRect]; - [b setTitle:toNSString(text)]; - [b setButtonType:NSRadioButton]; - // doesn't seem to have an associated bezel style - [b setBordered:NO]; - [b setTransparent:NO]; - uiDarwinSetControlFont(b, NSRegularControlSize); - [b setTranslatesAutoresizingMaskIntoConstraints:NO]; - - [b setTarget:r->delegate]; - [b setAction:@selector(onClicked:)]; - - [r->buttons addObject:b]; - [r->view addSubview:b]; - - // pin horizontally to the edges of the superview - constraint = mkConstraint(b, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - r->view, NSLayoutAttributeLeading, - 1, 0, - @"uiRadioButtons button leading constraint"); - [r->view addConstraint:constraint]; - [r->constraints addObject:constraint]; - constraint = mkConstraint(b, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - r->view, NSLayoutAttributeTrailing, - 1, 0, - @"uiRadioButtons button trailing constraint"); - [r->view addConstraint:constraint]; - [r->constraints addObject:constraint]; - - // if this is the first view, pin it to the top - // otherwise pin to the bottom of the last - if ([r->buttons count] == 1) - constraint = mkConstraint(b, NSLayoutAttributeTop, - NSLayoutRelationEqual, - r->view, NSLayoutAttributeTop, - 1, 0, - @"uiRadioButtons first button top constraint"); - else { - b2 = buttonAt(r, [r->buttons count] - 2); - constraint = mkConstraint(b, NSLayoutAttributeTop, - NSLayoutRelationEqual, - b2, NSLayoutAttributeBottom, - 1, 0, - @"uiRadioButtons non-first button top constraint"); - } - [r->view addConstraint:constraint]; - [r->constraints addObject:constraint]; - - // if there is a previous bottom constraint, remove it - if (r->lastv != nil) { - [r->view removeConstraint:r->lastv]; - [r->constraints removeObject:r->lastv]; - [r->lastv release]; - } - - // and make the new bottom constraint - r->lastv = mkConstraint(b, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - r->view, NSLayoutAttributeBottom, - 1, 0, - @"uiRadioButtons last button bottom constraint"); - [r->view addConstraint:r->lastv]; - [r->constraints addObject:r->lastv]; - [r->lastv retain]; -} - -int uiRadioButtonsSelected(uiRadioButtons *r) -{ - NSButton *b; - NSUInteger i; - - for (i = 0; i < [r->buttons count]; i++) { - b = (NSButton *) [r->buttons objectAtIndex:i]; - if ([b state] == NSOnState) - return i; - } - return -1; -} - -void uiRadioButtonsSetSelected(uiRadioButtons *r, int n) -{ - NSButton *b; - NSInteger state; - - state = NSOnState; - if (n == -1) { - n = uiRadioButtonsSelected(r); - if (n == -1) // from nothing to nothing; do nothing - return; - state = NSOffState; - } - b = (NSButton *) [r->buttons objectAtIndex:n]; - [b setState:state]; -} - -void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data) -{ - r->onSelected = f; - r->onSelectedData = data; -} - -uiRadioButtons *uiNewRadioButtons(void) -{ - uiRadioButtons *r; - - uiDarwinNewControl(uiRadioButtons, r); - - r->view = [[NSView alloc] initWithFrame:NSZeroRect]; - r->buttons = [NSMutableArray new]; - r->constraints = [NSMutableArray new]; - - r->delegate = [[radioButtonsDelegate alloc] initWithR:r]; - - uiRadioButtonsOnSelected(r, defaultOnSelected, NULL); - - return r; -} diff --git a/src/libui_sdl/libui/darwin/scrollview.m b/src/libui_sdl/libui/darwin/scrollview.m deleted file mode 100644 index b0b4040c..00000000 --- a/src/libui_sdl/libui/darwin/scrollview.m +++ /dev/null @@ -1,61 +0,0 @@ -// 27 may 2016 -#include "uipriv_darwin.h" - -// see http://stackoverflow.com/questions/37979445/how-do-i-properly-set-up-a-scrolling-nstableview-using-auto-layout-what-ive-tr for why we don't use auto layout -// TODO do the same with uiGroup and uiTab? - -struct scrollViewData { - BOOL hscroll; - BOOL vscroll; -}; - -NSScrollView *mkScrollView(struct scrollViewCreateParams *p, struct scrollViewData **dout) -{ - NSScrollView *sv; - NSBorderType border; - struct scrollViewData *d; - - sv = [[NSScrollView alloc] initWithFrame:NSZeroRect]; - if (p->BackgroundColor != nil) - [sv setBackgroundColor:p->BackgroundColor]; - [sv setDrawsBackground:p->DrawsBackground]; - border = NSNoBorder; - if (p->Bordered) - border = NSBezelBorder; - // document view seems to set the cursor properly - [sv setBorderType:border]; - [sv setAutohidesScrollers:YES]; - [sv setHasHorizontalRuler:NO]; - [sv setHasVerticalRuler:NO]; - [sv setRulersVisible:NO]; - [sv setScrollerKnobStyle:NSScrollerKnobStyleDefault]; - // the scroller style is documented as being set by default for us - // LONGTERM verify line and page for programmatically created NSTableView - [sv setScrollsDynamically:YES]; - [sv setFindBarPosition:NSScrollViewFindBarPositionAboveContent]; - [sv setUsesPredominantAxisScrolling:NO]; - [sv setHorizontalScrollElasticity:NSScrollElasticityAutomatic]; - [sv setVerticalScrollElasticity:NSScrollElasticityAutomatic]; - [sv setAllowsMagnification:NO]; - - [sv setDocumentView:p->DocumentView]; - d = uiNew(struct scrollViewData); - scrollViewSetScrolling(sv, d, p->HScroll, p->VScroll); - - *dout = d; - return sv; -} - -// based on http://blog.bjhomer.com/2014/08/nsscrollview-and-autolayout.html because (as pointed out there) Apple's official guide is really only for iOS -void scrollViewSetScrolling(NSScrollView *sv, struct scrollViewData *d, BOOL hscroll, BOOL vscroll) -{ - d->hscroll = hscroll; - [sv setHasHorizontalScroller:d->hscroll]; - d->vscroll = vscroll; - [sv setHasVerticalScroller:d->vscroll]; -} - -void scrollViewFreeData(NSScrollView *sv, struct scrollViewData *d) -{ - uiFree(d); -} diff --git a/src/libui_sdl/libui/darwin/separator.m b/src/libui_sdl/libui/darwin/separator.m deleted file mode 100644 index a37a376e..00000000 --- a/src/libui_sdl/libui/darwin/separator.m +++ /dev/null @@ -1,45 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// TODO make this intrinsic -#define separatorWidth 96 -#define separatorHeight 96 - -struct uiSeparator { - uiDarwinControl c; - NSBox *box; -}; - -uiDarwinControlAllDefaults(uiSeparator, box) - -uiSeparator *uiNewHorizontalSeparator(void) -{ - uiSeparator *s; - - uiDarwinNewControl(uiSeparator, s); - - // make the initial width >= initial height to force horizontal - s->box = [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, 100, 1)]; - [s->box setBoxType:NSBoxSeparator]; - [s->box setBorderType:NSGrooveBorder]; - [s->box setTransparent:NO]; - [s->box setTitlePosition:NSNoTitle]; - - return s; -} - -uiSeparator *uiNewVerticalSeparator(void) -{ - uiSeparator *s; - - uiDarwinNewControl(uiSeparator, s); - - // make the initial height >= initial width to force vertical - s->box = [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, 1, 100)]; - [s->box setBoxType:NSBoxSeparator]; - [s->box setBorderType:NSGrooveBorder]; - [s->box setTransparent:NO]; - [s->box setTitlePosition:NSNoTitle]; - - return s; -} diff --git a/src/libui_sdl/libui/darwin/slider.m b/src/libui_sdl/libui/darwin/slider.m deleted file mode 100644 index f00da50f..00000000 --- a/src/libui_sdl/libui/darwin/slider.m +++ /dev/null @@ -1,147 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -// Horizontal sliders have no intrinsic width; we'll use the default Interface Builder width for them. -// This will also be used for the initial frame size, to ensure the slider is always horizontal (see below). -#define sliderWidth 92 - -@interface libui_intrinsicWidthNSSlider : NSSlider -@end - -@implementation libui_intrinsicWidthNSSlider - -- (NSSize)intrinsicContentSize -{ - NSSize s; - - s = [super intrinsicContentSize]; - s.width = sliderWidth; - return s; -} - -@end - -struct uiSlider { - uiDarwinControl c; - NSSlider *slider; - void (*onChanged)(uiSlider *, void *); - void *onChangedData; -}; - -@interface sliderDelegateClass : NSObject { - struct mapTable *sliders; -} -- (IBAction)onChanged:(id)sender; -- (void)registerSlider:(uiSlider *)b; -- (void)unregisterSlider:(uiSlider *)b; -@end - -@implementation sliderDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->sliders = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->sliders); - [super dealloc]; -} - -- (IBAction)onChanged:(id)sender -{ - uiSlider *s; - - s = (uiSlider *) mapGet(self->sliders, sender); - (*(s->onChanged))(s, s->onChangedData); -} - -- (void)registerSlider:(uiSlider *)s -{ - mapSet(self->sliders, s->slider, s); - [s->slider setTarget:self]; - [s->slider setAction:@selector(onChanged:)]; -} - -- (void)unregisterSlider:(uiSlider *)s -{ - [s->slider setTarget:nil]; - mapDelete(self->sliders, s->slider); -} - -@end - -static sliderDelegateClass *sliderDelegate = nil; - -uiDarwinControlAllDefaultsExceptDestroy(uiSlider, slider) - -static void uiSliderDestroy(uiControl *c) -{ - uiSlider *s = uiSlider(c); - - [sliderDelegate unregisterSlider:s]; - [s->slider release]; - uiFreeControl(uiControl(s)); -} - -int uiSliderValue(uiSlider *s) -{ - return [s->slider integerValue]; -} - -void uiSliderSetValue(uiSlider *s, int value) -{ - [s->slider setIntegerValue:value]; -} - -void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *, void *), void *data) -{ - s->onChanged = f; - s->onChangedData = data; -} - -static void defaultOnChanged(uiSlider *s, void *data) -{ - // do nothing -} - -uiSlider *uiNewSlider(int min, int max) -{ - uiSlider *s; - NSSliderCell *cell; - int temp; - - if (min >= max) { - temp = min; - min = max; - max = temp; - } - - uiDarwinNewControl(uiSlider, s); - - // a horizontal slider is defined as one where the width > height, not by a flag - // to be safe, don't use NSZeroRect, but make it horizontal from the get-go - s->slider = [[libui_intrinsicWidthNSSlider alloc] - initWithFrame:NSMakeRect(0, 0, sliderWidth, 2)]; - [s->slider setMinValue:min]; - [s->slider setMaxValue:max]; - [s->slider setAllowsTickMarkValuesOnly:NO]; - [s->slider setNumberOfTickMarks:0]; - [s->slider setTickMarkPosition:NSTickMarkAbove]; - - cell = (NSSliderCell *) [s->slider cell]; - [cell setSliderType:NSLinearSlider]; - - if (sliderDelegate == nil) { - sliderDelegate = [[sliderDelegateClass new] autorelease]; - [delegates addObject:sliderDelegate]; - } - [sliderDelegate registerSlider:s]; - uiSliderOnChanged(s, defaultOnChanged, NULL); - - return s; -} diff --git a/src/libui_sdl/libui/darwin/spinbox.m b/src/libui_sdl/libui/darwin/spinbox.m deleted file mode 100644 index 73474d04..00000000 --- a/src/libui_sdl/libui/darwin/spinbox.m +++ /dev/null @@ -1,214 +0,0 @@ -// 14 august 2015 -#import "uipriv_darwin.h" - -@interface libui_spinbox : NSView { - NSTextField *tf; - NSNumberFormatter *formatter; - NSStepper *stepper; - - NSInteger value; - NSInteger minimum; - NSInteger maximum; - - uiSpinbox *spinbox; -} -- (id)initWithFrame:(NSRect)r spinbox:(uiSpinbox *)sb; -// see https://github.com/andlabs/ui/issues/82 -- (NSInteger)libui_value; -- (void)libui_setValue:(NSInteger)val; -- (void)setMinimum:(NSInteger)min; -- (void)setMaximum:(NSInteger)max; -- (IBAction)stepperClicked:(id)sender; -- (void)controlTextDidChange:(NSNotification *)note; -@end - -struct uiSpinbox { - uiDarwinControl c; - libui_spinbox *spinbox; - void (*onChanged)(uiSpinbox *, void *); - void *onChangedData; -}; - -// yes folks, this varies by operating system! woo! -// 10.10 started drawing the NSStepper one point too low, so we have to fix it up conditionally -// TODO test this; we'll probably have to substitute 10_9 -static CGFloat stepperYDelta(void) -{ - // via https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKit/ - if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9) - return 0; - return -1; -} - -@implementation libui_spinbox - -- (id)initWithFrame:(NSRect)r spinbox:(uiSpinbox *)sb -{ - self = [super initWithFrame:r]; - if (self) { - self->tf = newEditableTextField(); - [self->tf setTranslatesAutoresizingMaskIntoConstraints:NO]; - - self->formatter = [NSNumberFormatter new]; - [self->formatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; - [self->formatter setLocalizesFormat:NO]; - [self->formatter setUsesGroupingSeparator:NO]; - [self->formatter setHasThousandSeparators:NO]; - [self->formatter setAllowsFloats:NO]; - [self->tf setFormatter:self->formatter]; - - self->stepper = [[NSStepper alloc] initWithFrame:NSZeroRect]; - [self->stepper setIncrement:1]; - [self->stepper setValueWraps:NO]; - [self->stepper setAutorepeat:YES]; // hold mouse button to step repeatedly - [self->stepper setTranslatesAutoresizingMaskIntoConstraints:NO]; - - [self->tf setDelegate:self]; - [self->stepper setTarget:self]; - [self->stepper setAction:@selector(stepperClicked:)]; - - [self addSubview:self->tf]; - [self addSubview:self->stepper]; - - [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeLeading, - NSLayoutRelationEqual, - self, NSLayoutAttributeLeading, - 1, 0, - @"uiSpinbox left edge")]; - [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - self, NSLayoutAttributeTrailing, - 1, 0, - @"uiSpinbox right edge")]; - [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeTop, - NSLayoutRelationEqual, - self, NSLayoutAttributeTop, - 1, 0, - @"uiSpinbox top edge text field")]; - [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - self, NSLayoutAttributeBottom, - 1, 0, - @"uiSpinbox bottom edge text field")]; - [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeTop, - NSLayoutRelationEqual, - self, NSLayoutAttributeTop, - 1, stepperYDelta(), - @"uiSpinbox top edge stepper")]; - [self addConstraint:mkConstraint(self->stepper, NSLayoutAttributeBottom, - NSLayoutRelationEqual, - self, NSLayoutAttributeBottom, - 1, stepperYDelta(), - @"uiSpinbox bottom edge stepper")]; - [self addConstraint:mkConstraint(self->tf, NSLayoutAttributeTrailing, - NSLayoutRelationEqual, - self->stepper, NSLayoutAttributeLeading, - 1, -3, // arbitrary amount; good enough visually (and it seems to match NSDatePicker too, at least on 10.11, which is even better) - @"uiSpinbox space between text field and stepper")]; - - self->spinbox = sb; - } - return self; -} - -- (void)dealloc -{ - [self->tf setDelegate:nil]; - [self->tf removeFromSuperview]; - [self->tf release]; - [self->formatter release]; - [self->stepper setTarget:nil]; - [self->stepper removeFromSuperview]; - [self->stepper release]; - [super dealloc]; -} - -- (NSInteger)libui_value -{ - return self->value; -} - -- (void)libui_setValue:(NSInteger)val -{ - self->value = val; - if (self->value < self->minimum) - self->value = self->minimum; - if (self->value > self->maximum) - self->value = self->maximum; - [self->tf setIntegerValue:self->value]; - [self->stepper setIntegerValue:self->value]; -} - -- (void)setMinimum:(NSInteger)min -{ - self->minimum = min; - [self->formatter setMinimum:[NSNumber numberWithInteger:self->minimum]]; - [self->stepper setMinValue:((double) (self->minimum))]; -} - -- (void)setMaximum:(NSInteger)max -{ - self->maximum = max; - [self->formatter setMaximum:[NSNumber numberWithInteger:self->maximum]]; - [self->stepper setMaxValue:((double) (self->maximum))]; -} - -- (IBAction)stepperClicked:(id)sender -{ - [self libui_setValue:[self->stepper integerValue]]; - (*(self->spinbox->onChanged))(self->spinbox, self->spinbox->onChangedData); -} - -- (void)controlTextDidChange:(NSNotification *)note -{ - [self libui_setValue:[self->tf integerValue]]; - (*(self->spinbox->onChanged))(self->spinbox, self->spinbox->onChangedData); -} - -@end - -uiDarwinControlAllDefaults(uiSpinbox, spinbox) - -int uiSpinboxValue(uiSpinbox *s) -{ - return [s->spinbox libui_value]; -} - -void uiSpinboxSetValue(uiSpinbox *s, int value) -{ - [s->spinbox libui_setValue:value]; -} - -void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *, void *), void *data) -{ - s->onChanged = f; - s->onChangedData = data; -} - -static void defaultOnChanged(uiSpinbox *s, void *data) -{ - // do nothing -} - -uiSpinbox *uiNewSpinbox(int min, int max) -{ - uiSpinbox *s; - int temp; - - if (min >= max) { - temp = min; - min = max; - max = temp; - } - - uiDarwinNewControl(uiSpinbox, s); - - s->spinbox = [[libui_spinbox alloc] initWithFrame:NSZeroRect spinbox:s]; - [s->spinbox setMinimum:min]; - [s->spinbox setMaximum:max]; - [s->spinbox libui_setValue:min]; - - uiSpinboxOnChanged(s, defaultOnChanged, NULL); - - return s; -} diff --git a/src/libui_sdl/libui/darwin/stddialogs.m b/src/libui_sdl/libui/darwin/stddialogs.m deleted file mode 100644 index c8260351..00000000 --- a/src/libui_sdl/libui/darwin/stddialogs.m +++ /dev/null @@ -1,123 +0,0 @@ -// 26 june 2015 -#import "uipriv_darwin.h" - -// LONGTERM restructure this whole file -// LONGTERM explicitly document this works as we want -// LONGTERM note that font and color buttons also do this - -#define windowWindow(w) ((NSWindow *) uiControlHandle(uiControl(w))) - -// source of code modal logic: http://stackoverflow.com/questions/604768/wait-for-nsalert-beginsheetmodalforwindow - -// note: whether extensions are actually shown depends on a user setting in Finder; we can't control it here -static void setupSavePanel(NSSavePanel *s) -{ - [s setCanCreateDirectories:YES]; - [s setShowsHiddenFiles:YES]; - [s setExtensionHidden:NO]; - [s setCanSelectHiddenExtension:NO]; - [s setTreatsFilePackagesAsDirectories:YES]; -} - -static char *runSavePanel(NSWindow *parent, NSSavePanel *s) -{ - char *filename; - - [s beginSheetModalForWindow:parent completionHandler:^(NSInteger result) { - [realNSApp() stopModalWithCode:result]; - }]; - if ([realNSApp() runModalForWindow:s] != NSFileHandlingPanelOKButton) - return NULL; - filename = uiDarwinNSStringToText([[s URL] path]); - return filename; -} - -char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath) -{ - NSOpenPanel *o; - - o = [NSOpenPanel openPanel]; - [o setCanChooseFiles:YES]; - [o setCanChooseDirectories:NO]; - [o setResolvesAliases:NO]; - [o setAllowsMultipleSelection:NO]; - setupSavePanel(o); - // panel is autoreleased - return runSavePanel(windowWindow(parent), o); -} - -char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath) -{ - NSSavePanel *s; - - s = [NSSavePanel savePanel]; - setupSavePanel(s); - // panel is autoreleased - return runSavePanel(windowWindow(parent), s); -} - -// I would use a completion handler for NSAlert as well, but alas NSAlert's are 10.9 and higher only -@interface libuiCodeModalAlertPanel : NSObject { - NSAlert *panel; - NSWindow *parent; -} -- (id)initWithPanel:(NSAlert *)p parent:(NSWindow *)w; -- (NSInteger)run; -- (void)panelEnded:(NSAlert *)panel result:(NSInteger)result data:(void *)data; -@end - -@implementation libuiCodeModalAlertPanel - -- (id)initWithPanel:(NSAlert *)p parent:(NSWindow *)w -{ - self = [super init]; - if (self) { - self->panel = p; - self->parent = w; - } - return self; -} - -- (NSInteger)run -{ - [self->panel beginSheetModalForWindow:self->parent - modalDelegate:self - didEndSelector:@selector(panelEnded:result:data:) - contextInfo:NULL]; - return [realNSApp() runModalForWindow:[self->panel window]]; -} - -- (void)panelEnded:(NSAlert *)panel result:(NSInteger)result data:(void *)data -{ - [realNSApp() stopModalWithCode:result]; -} - -@end - -static void msgbox(NSWindow *parent, const char *title, const char *description, NSAlertStyle style) -{ - NSAlert *a; - libuiCodeModalAlertPanel *cm; - - a = [NSAlert new]; - [a setAlertStyle:style]; - [a setShowsHelp:NO]; - [a setShowsSuppressionButton:NO]; - [a setMessageText:toNSString(title)]; - [a setInformativeText:toNSString(description)]; - [a addButtonWithTitle:@"OK"]; - cm = [[libuiCodeModalAlertPanel alloc] initWithPanel:a parent:parent]; - [cm run]; - [cm release]; - [a release]; -} - -void uiMsgBox(uiWindow *parent, const char *title, const char *description) -{ - msgbox(windowWindow(parent), title, description, NSInformationalAlertStyle); -} - -void uiMsgBoxError(uiWindow *parent, const char *title, const char *description) -{ - msgbox(windowWindow(parent), title, description, NSCriticalAlertStyle); -} diff --git a/src/libui_sdl/libui/darwin/tab.m b/src/libui_sdl/libui/darwin/tab.m deleted file mode 100644 index 3d2ca9f0..00000000 --- a/src/libui_sdl/libui/darwin/tab.m +++ /dev/null @@ -1,292 +0,0 @@ -// 15 august 2015 -#import "uipriv_darwin.h" - -// TODO need to jiggle on tab change too (second page disabled tab label initially ambiguous) - -@interface tabPage : NSObject { - struct singleChildConstraints constraints; - int margined; - NSView *view; // the NSTabViewItem view itself - NSObject *pageID; -} -@property uiControl *c; -@property NSLayoutPriority oldHorzHuggingPri; -@property NSLayoutPriority oldVertHuggingPri; -- (id)initWithView:(NSView *)v pageID:(NSObject *)o; -- (NSView *)childView; -- (void)establishChildConstraints; -- (void)removeChildConstraints; -- (int)isMargined; -- (void)setMargined:(int)m; -@end - -struct uiTab { - uiDarwinControl c; - NSTabView *tabview; - NSMutableArray *pages; - NSLayoutPriority horzHuggingPri; - NSLayoutPriority vertHuggingPri; -}; - -@implementation tabPage - -- (id)initWithView:(NSView *)v pageID:(NSObject *)o -{ - self = [super init]; - if (self != nil) { - self->view = [v retain]; - self->pageID = [o retain]; - } - return self; -} - -- (void)dealloc -{ - [self removeChildConstraints]; - [self->view release]; - [self->pageID release]; - [super dealloc]; -} - -- (NSView *)childView -{ - return (NSView *) uiControlHandle(self.c); -} - -- (void)establishChildConstraints -{ - [self removeChildConstraints]; - if (self.c == NULL) - return; - singleChildConstraintsEstablish(&(self->constraints), - self->view, [self childView], - uiDarwinControlHugsTrailingEdge(uiDarwinControl(self.c)), - uiDarwinControlHugsBottom(uiDarwinControl(self.c)), - self->margined, - @"uiTab page"); -} - -- (void)removeChildConstraints -{ - singleChildConstraintsRemove(&(self->constraints), self->view); -} - -- (int)isMargined -{ - return self->margined; -} - -- (void)setMargined:(int)m -{ - self->margined = m; - singleChildConstraintsSetMargined(&(self->constraints), self->margined); -} - -@end - -static void uiTabDestroy(uiControl *c) -{ - uiTab *t = uiTab(c); - tabPage *page; - - // first remove all tab pages so we can destroy all the children - while ([t->tabview numberOfTabViewItems] != 0) - [t->tabview removeTabViewItem:[t->tabview tabViewItemAtIndex:0]]; - // then destroy all the children - for (page in t->pages) { - [page removeChildConstraints]; - uiControlSetParent(page.c, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(page.c), nil); - uiControlDestroy(page.c); - } - // and finally destroy ourselves - [t->pages release]; - [t->tabview release]; - uiFreeControl(uiControl(t)); -} - -uiDarwinControlDefaultHandle(uiTab, tabview) -uiDarwinControlDefaultParent(uiTab, tabview) -uiDarwinControlDefaultSetParent(uiTab, tabview) -uiDarwinControlDefaultToplevel(uiTab, tabview) -uiDarwinControlDefaultVisible(uiTab, tabview) -uiDarwinControlDefaultShow(uiTab, tabview) -uiDarwinControlDefaultHide(uiTab, tabview) -uiDarwinControlDefaultEnabled(uiTab, tabview) -uiDarwinControlDefaultEnable(uiTab, tabview) -uiDarwinControlDefaultDisable(uiTab, tabview) - -static void uiTabSyncEnableState(uiDarwinControl *c, int enabled) -{ - uiTab *t = uiTab(c); - tabPage *page; - - if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(t), enabled)) - return; - for (page in t->pages) - uiDarwinControlSyncEnableState(uiDarwinControl(page.c), enabled); -} - -uiDarwinControlDefaultSetSuperview(uiTab, tabview) - -static void tabRelayout(uiTab *t) -{ - tabPage *page; - - for (page in t->pages) - [page establishChildConstraints]; - // and this gets rid of some weird issues with regards to box alignment - jiggleViewLayout(t->tabview); -} - -BOOL uiTabHugsTrailingEdge(uiDarwinControl *c) -{ - uiTab *t = uiTab(c); - - return t->horzHuggingPri < NSLayoutPriorityWindowSizeStayPut; -} - -BOOL uiTabHugsBottom(uiDarwinControl *c) -{ - uiTab *t = uiTab(c); - - return t->vertHuggingPri < NSLayoutPriorityWindowSizeStayPut; -} - -static void uiTabChildEdgeHuggingChanged(uiDarwinControl *c) -{ - uiTab *t = uiTab(c); - - tabRelayout(t); -} - -static NSLayoutPriority uiTabHuggingPriority(uiDarwinControl *c, NSLayoutConstraintOrientation orientation) -{ - uiTab *t = uiTab(c); - - if (orientation == NSLayoutConstraintOrientationHorizontal) - return t->horzHuggingPri; - return t->vertHuggingPri; -} - -static void uiTabSetHuggingPriority(uiDarwinControl *c, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation) -{ - uiTab *t = uiTab(c); - - if (orientation == NSLayoutConstraintOrientationHorizontal) - t->horzHuggingPri = priority; - else - t->vertHuggingPri = priority; - uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(t)); -} - -static void uiTabChildVisibilityChanged(uiDarwinControl *c) -{ - uiTab *t = uiTab(c); - - tabRelayout(t); -} - -void uiTabAppend(uiTab *t, const char *name, uiControl *child) -{ - uiTabInsertAt(t, name, [t->pages count], child); -} - -void uiTabInsertAt(uiTab *t, const char *name, int n, uiControl *child) -{ - tabPage *page; - NSView *view; - NSTabViewItem *i; - NSObject *pageID; - - uiControlSetParent(child, uiControl(t)); - - view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease]; - // note: if we turn off the autoresizing mask, nothing shows up - uiDarwinControlSetSuperview(uiDarwinControl(child), view); - uiDarwinControlSyncEnableState(uiDarwinControl(child), uiControlEnabledToUser(uiControl(t))); - - // the documentation says these can be nil but the headers say these must not be; let's be safe and make them non-nil anyway - pageID = [NSObject new]; - page = [[[tabPage alloc] initWithView:view pageID:pageID] autorelease]; - page.c = child; - - // don't hug, just in case we're a stretchy tab - page.oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(page.c), NSLayoutConstraintOrientationHorizontal); - page.oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(page.c), NSLayoutConstraintOrientationVertical); - uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationHorizontal); - uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationVertical); - - [t->pages insertObject:page atIndex:n]; - - i = [[[NSTabViewItem alloc] initWithIdentifier:pageID] autorelease]; - [i setLabel:toNSString(name)]; - [i setView:view]; - [t->tabview insertTabViewItem:i atIndex:n]; - - tabRelayout(t); -} - -void uiTabDelete(uiTab *t, int n) -{ - tabPage *page; - uiControl *child; - NSTabViewItem *i; - - page = (tabPage *) [t->pages objectAtIndex:n]; - - uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), page.oldHorzHuggingPri, NSLayoutConstraintOrientationHorizontal); - uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), page.oldVertHuggingPri, NSLayoutConstraintOrientationVertical); - - child = page.c; - [page removeChildConstraints]; - [t->pages removeObjectAtIndex:n]; - - uiControlSetParent(child, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(child), nil); - - i = [t->tabview tabViewItemAtIndex:n]; - [t->tabview removeTabViewItem:i]; - - tabRelayout(t); -} - -int uiTabNumPages(uiTab *t) -{ - return [t->pages count]; -} - -int uiTabMargined(uiTab *t, int n) -{ - tabPage *page; - - page = (tabPage *) [t->pages objectAtIndex:n]; - return [page isMargined]; -} - -void uiTabSetMargined(uiTab *t, int n, int margined) -{ - tabPage *page; - - page = (tabPage *) [t->pages objectAtIndex:n]; - [page setMargined:margined]; -} - -uiTab *uiNewTab(void) -{ - uiTab *t; - - uiDarwinNewControl(uiTab, t); - - t->tabview = [[NSTabView alloc] initWithFrame:NSZeroRect]; - // also good for NSTabView (same selector and everything) - uiDarwinSetControlFont((NSControl *) (t->tabview), NSRegularControlSize); - - t->pages = [NSMutableArray new]; - - // default to low hugging to not hug edges - t->horzHuggingPri = NSLayoutPriorityDefaultLow; - t->vertHuggingPri = NSLayoutPriorityDefaultLow; - - return t; -} diff --git a/src/libui_sdl/libui/darwin/text.m b/src/libui_sdl/libui/darwin/text.m deleted file mode 100644 index f0d3dab6..00000000 --- a/src/libui_sdl/libui/darwin/text.m +++ /dev/null @@ -1,19 +0,0 @@ -// 10 april 2015 -#import "uipriv_darwin.h" - -char *uiDarwinNSStringToText(NSString *s) -{ - char *out; - - out = strdup([s UTF8String]); - if (out == NULL) { - fprintf(stderr, "memory exhausted in uiDarwinNSStringToText()\n"); - abort(); - } - return out; -} - -void uiFreeText(char *s) -{ - free(s); -} diff --git a/src/libui_sdl/libui/darwin/uipriv_darwin.h b/src/libui_sdl/libui/darwin/uipriv_darwin.h deleted file mode 100644 index 6bca87b2..00000000 --- a/src/libui_sdl/libui/darwin/uipriv_darwin.h +++ /dev/null @@ -1,146 +0,0 @@ -// 6 january 2015 -#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_8 -#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_8 -#import -#import "../ui.h" -#import "../ui_darwin.h" -#import "../common/uipriv.h" - -#if __has_feature(objc_arc) -#error Sorry, libui cannot be compiled with ARC. -#endif - -#define toNSString(str) [NSString stringWithUTF8String:(str)] -#define fromNSString(str) [(str) UTF8String] - -#ifndef NSAppKitVersionNumber10_9 -#define NSAppKitVersionNumber10_9 1265 -#endif - -/*TODO remove this*/typedef struct uiImage uiImage; - -// menu.m -@interface menuManager : NSObject { - struct mapTable *items; - BOOL hasQuit; - BOOL hasPreferences; - BOOL hasAbout; -} -@property (strong) NSMenuItem *quitItem; -@property (strong) NSMenuItem *preferencesItem; -@property (strong) NSMenuItem *aboutItem; -// NSMenuValidation is only informal -- (BOOL)validateMenuItem:(NSMenuItem *)item; -- (NSMenu *)makeMenubar; -@end -extern void finalizeMenus(void); -extern void uninitMenus(void); - -// main.m -@interface applicationClass : NSApplication -@end -// this is needed because NSApp is of type id, confusing clang -#define realNSApp() ((applicationClass *) NSApp) -@interface appDelegate : NSObject -@property (strong) menuManager *menuManager; -@end -#define appDelegate() ((appDelegate *) [realNSApp() delegate]) -struct nextEventArgs { - NSEventMask mask; - NSDate *duration; - // LONGTERM no NSRunLoopMode? - NSString *mode; - BOOL dequeue; -}; -extern int mainStep(struct nextEventArgs *nea, BOOL (^interceptEvent)(NSEvent *)); - -// util.m -extern void disableAutocorrect(NSTextView *); - -// entry.m -extern void finishNewTextField(NSTextField *, BOOL); -extern NSTextField *newEditableTextField(void); - -// window.m -@interface libuiNSWindow : NSWindow -- (void)libui_doMove:(NSEvent *)initialEvent; -- (void)libui_doResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge; -@end -extern uiWindow *windowFromNSWindow(NSWindow *); - -// alloc.m -extern NSMutableArray *delegates; -extern void initAlloc(void); -extern void uninitAlloc(void); - -// autolayout.m -extern NSLayoutConstraint *mkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc); -extern void jiggleViewLayout(NSView *view); -struct singleChildConstraints { - NSLayoutConstraint *leadingConstraint; - NSLayoutConstraint *topConstraint; - NSLayoutConstraint *trailingConstraintGreater; - NSLayoutConstraint *trailingConstraintEqual; - NSLayoutConstraint *bottomConstraintGreater; - NSLayoutConstraint *bottomConstraintEqual; -}; -extern void singleChildConstraintsEstablish(struct singleChildConstraints *c, NSView *contentView, NSView *childView, BOOL hugsTrailing, BOOL hugsBottom, int margined, NSString *desc); -extern void singleChildConstraintsRemove(struct singleChildConstraints *c, NSView *cv); -extern void singleChildConstraintsSetMargined(struct singleChildConstraints *c, int margined); - -// map.m -extern struct mapTable *newMap(void); -extern void mapDestroy(struct mapTable *m); -extern void *mapGet(struct mapTable *m, void *key); -extern void mapSet(struct mapTable *m, void *key, void *value); -extern void mapDelete(struct mapTable *m, void *key); -extern void mapWalk(struct mapTable *m, void (*f)(void *key, void *value)); -extern void mapReset(struct mapTable *m); - -// area.m -extern int sendAreaEvents(NSEvent *); - -// areaevents.m -extern BOOL fromKeycode(unsigned short keycode, uiAreaKeyEvent *ke); -extern BOOL keycodeModifier(unsigned short keycode, uiModifiers *mod); - -// draw.m -extern uiDrawContext *newContext(CGContextRef, CGFloat); -extern void freeContext(uiDrawContext *); - -// drawtext.m -extern uiDrawTextFont *mkTextFont(CTFontRef f, BOOL retain); -extern uiDrawTextFont *mkTextFontFromNSFont(NSFont *f); -extern void doDrawText(CGContextRef c, CGFloat cheight, double x, double y, uiDrawTextLayout *layout); - -// fontbutton.m -extern BOOL fontButtonInhibitSendAction(SEL sel, id from, id to); -extern BOOL fontButtonOverrideTargetForAction(SEL sel, id from, id to, id *override); -extern void setupFontPanel(void); - -// colorbutton.m -extern BOOL colorButtonInhibitSendAction(SEL sel, id from, id to); - -// scrollview.m -struct scrollViewCreateParams { - NSView *DocumentView; - NSColor *BackgroundColor; - BOOL DrawsBackground; - BOOL Bordered; - BOOL HScroll; - BOOL VScroll; -}; -struct scrollViewData; -extern NSScrollView *mkScrollView(struct scrollViewCreateParams *p, struct scrollViewData **dout); -extern void scrollViewSetScrolling(NSScrollView *sv, struct scrollViewData *d, BOOL hscroll, BOOL vscroll); -extern void scrollViewFreeData(NSScrollView *sv, struct scrollViewData *d); - -// label.m -extern NSTextField *newLabel(NSString *str); - -// image.m -extern NSImage *imageImage(uiImage *); - -// winmoveresize.m -extern void doManualMove(NSWindow *w, NSEvent *initialEvent); -extern void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge); diff --git a/src/libui_sdl/libui/darwin/util.m b/src/libui_sdl/libui/darwin/util.m deleted file mode 100644 index ab873906..00000000 --- a/src/libui_sdl/libui/darwin/util.m +++ /dev/null @@ -1,15 +0,0 @@ -// 7 april 2015 -#import "uipriv_darwin.h" - -// LONGTERM do we really want to do this? make it an option? -void disableAutocorrect(NSTextView *tv) -{ - [tv setEnabledTextCheckingTypes:0]; - [tv setAutomaticDashSubstitutionEnabled:NO]; - // don't worry about automatic data detection; it won't change stringValue (thanks pretty_function in irc.freenode.net/#macdev) - [tv setAutomaticSpellingCorrectionEnabled:NO]; - [tv setAutomaticTextReplacementEnabled:NO]; - [tv setAutomaticQuoteSubstitutionEnabled:NO]; - [tv setAutomaticLinkDetectionEnabled:NO]; - [tv setSmartInsertDeleteEnabled:NO]; -} diff --git a/src/libui_sdl/libui/darwin/window.m b/src/libui_sdl/libui/darwin/window.m deleted file mode 100644 index 97c22e62..00000000 --- a/src/libui_sdl/libui/darwin/window.m +++ /dev/null @@ -1,407 +0,0 @@ -// 15 august 2015 -#import "uipriv_darwin.h" - -#define defaultStyleMask (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) - -struct uiWindow { - uiDarwinControl c; - NSWindow *window; - uiControl *child; - int margined; - int (*onClosing)(uiWindow *, void *); - void *onClosingData; - struct singleChildConstraints constraints; - void (*onContentSizeChanged)(uiWindow *, void *); - void *onContentSizeChangedData; - BOOL suppressSizeChanged; - int fullscreen; - int borderless; -}; - -@implementation libuiNSWindow - -- (void)libui_doMove:(NSEvent *)initialEvent -{ - doManualMove(self, initialEvent); -} - -- (void)libui_doResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge -{ - doManualResize(self, initialEvent, edge); -} - -@end - -@interface windowDelegateClass : NSObject { - struct mapTable *windows; -} -- (BOOL)windowShouldClose:(id)sender; -- (void)windowDidResize:(NSNotification *)note; -- (void)windowDidEnterFullScreen:(NSNotification *)note; -- (void)windowDidExitFullScreen:(NSNotification *)note; -- (void)registerWindow:(uiWindow *)w; -- (void)unregisterWindow:(uiWindow *)w; -- (uiWindow *)lookupWindow:(NSWindow *)w; -@end - -@implementation windowDelegateClass - -- (id)init -{ - self = [super init]; - if (self) - self->windows = newMap(); - return self; -} - -- (void)dealloc -{ - mapDestroy(self->windows); - [super dealloc]; -} - -- (BOOL)windowShouldClose:(id)sender -{ - uiWindow *w; - - w = [self lookupWindow:((NSWindow *) sender)]; - // w should not be NULL; we are only the delegate of registered windows - if ((*(w->onClosing))(w, w->onClosingData)) - uiControlDestroy(uiControl(w)); - return NO; -} - -- (void)windowDidResize:(NSNotification *)note -{ - uiWindow *w; - - w = [self lookupWindow:((NSWindow *) [note object])]; - if (!w->suppressSizeChanged) - (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); -} - -- (void)windowDidEnterFullScreen:(NSNotification *)note -{ - uiWindow *w; - - w = [self lookupWindow:((NSWindow *) [note object])]; - if (!w->suppressSizeChanged) - w->fullscreen = 1; -} - -- (void)windowDidExitFullScreen:(NSNotification *)note -{ - uiWindow *w; - - w = [self lookupWindow:((NSWindow *) [note object])]; - if (!w->suppressSizeChanged) - w->fullscreen = 0; -} - -- (void)registerWindow:(uiWindow *)w -{ - mapSet(self->windows, w->window, w); - [w->window setDelegate:self]; -} - -- (void)unregisterWindow:(uiWindow *)w -{ - [w->window setDelegate:nil]; - mapDelete(self->windows, w->window); -} - -- (uiWindow *)lookupWindow:(NSWindow *)w -{ - uiWindow *v; - - v = uiWindow(mapGet(self->windows, w)); - // this CAN (and IS ALLOWED TO) return NULL, just in case we're called with some OS X-provided window as the key window - return v; -} - -@end - -static windowDelegateClass *windowDelegate = nil; - -static void removeConstraints(uiWindow *w) -{ - NSView *cv; - - cv = [w->window contentView]; - singleChildConstraintsRemove(&(w->constraints), cv); -} - -static void uiWindowDestroy(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - // hide the window - [w->window orderOut:w->window]; - removeConstraints(w); - if (w->child != NULL) { - uiControlSetParent(w->child, NULL); - uiDarwinControlSetSuperview(uiDarwinControl(w->child), nil); - uiControlDestroy(w->child); - } - [windowDelegate unregisterWindow:w]; - [w->window release]; - uiFreeControl(uiControl(w)); -} - -uiDarwinControlDefaultHandle(uiWindow, window) - -uiControl *uiWindowParent(uiControl *c) -{ - return NULL; -} - -void uiWindowSetParent(uiControl *c, uiControl *parent) -{ - uiUserBugCannotSetParentOnToplevel("uiWindow"); -} - -static int uiWindowToplevel(uiControl *c) -{ - return 1; -} - -static int uiWindowVisible(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - return [w->window isVisible]; -} - -static void uiWindowShow(uiControl *c) -{ - uiWindow *w = (uiWindow *) c; - - [w->window makeKeyAndOrderFront:w->window]; -} - -static void uiWindowHide(uiControl *c) -{ - uiWindow *w = (uiWindow *) c; - - [w->window orderOut:w->window]; -} - -uiDarwinControlDefaultEnabled(uiWindow, window) -uiDarwinControlDefaultEnable(uiWindow, window) -uiDarwinControlDefaultDisable(uiWindow, window) - -static void uiWindowSyncEnableState(uiDarwinControl *c, int enabled) -{ - uiWindow *w = uiWindow(c); - - if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(w), enabled)) - return; - if (w->child != NULL) - uiDarwinControlSyncEnableState(uiDarwinControl(w->child), enabled); -} - -static void uiWindowSetSuperview(uiDarwinControl *c, NSView *superview) -{ - // TODO -} - -static void windowRelayout(uiWindow *w) -{ - NSView *childView; - NSView *contentView; - - removeConstraints(w); - if (w->child == NULL) - return; - childView = (NSView *) uiControlHandle(w->child); - contentView = [w->window contentView]; - singleChildConstraintsEstablish(&(w->constraints), - contentView, childView, - uiDarwinControlHugsTrailingEdge(uiDarwinControl(w->child)), - uiDarwinControlHugsBottom(uiDarwinControl(w->child)), - w->margined, - @"uiWindow"); -} - -uiDarwinControlDefaultHugsTrailingEdge(uiWindow, window) -uiDarwinControlDefaultHugsBottom(uiWindow, window) - -static void uiWindowChildEdgeHuggingChanged(uiDarwinControl *c) -{ - uiWindow *w = uiWindow(c); - - windowRelayout(w); -} - -// TODO -uiDarwinControlDefaultHuggingPriority(uiWindow, window) -uiDarwinControlDefaultSetHuggingPriority(uiWindow, window) -// end TODO - -static void uiWindowChildVisibilityChanged(uiDarwinControl *c) -{ - uiWindow *w = uiWindow(c); - - windowRelayout(w); -} - -char *uiWindowTitle(uiWindow *w) -{ - return uiDarwinNSStringToText([w->window title]); -} - -void uiWindowSetTitle(uiWindow *w, const char *title) -{ - [w->window setTitle:toNSString(title)]; -} - -void uiWindowContentSize(uiWindow *w, int *width, int *height) -{ - NSRect r; - - r = [w->window contentRectForFrameRect:[w->window frame]]; - *width = r.size.width; - *height = r.size.height; -} - -void uiWindowSetContentSize(uiWindow *w, int width, int height) -{ - w->suppressSizeChanged = YES; - [w->window setContentSize:NSMakeSize(width, height)]; - w->suppressSizeChanged = NO; -} - -int uiWindowFullscreen(uiWindow *w) -{ - return w->fullscreen; -} - -void uiWindowSetFullscreen(uiWindow *w, int fullscreen) -{ - if (w->fullscreen && fullscreen) - return; - if (!w->fullscreen && !fullscreen) - return; - w->fullscreen = fullscreen; - if (w->fullscreen && w->borderless) // borderless doesn't play nice with fullscreen; don't toggle while borderless - return; - w->suppressSizeChanged = YES; - [w->window toggleFullScreen:w->window]; - w->suppressSizeChanged = NO; - if (!w->fullscreen && w->borderless) // borderless doesn't play nice with fullscreen; restore borderless after removing - [w->window setStyleMask:NSBorderlessWindowMask]; -} - -void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onContentSizeChanged = f; - w->onContentSizeChangedData = data; -} - -void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) -{ - w->onClosing = f; - w->onClosingData = data; -} - -int uiWindowBorderless(uiWindow *w) -{ - return w->borderless; -} - -void uiWindowSetBorderless(uiWindow *w, int borderless) -{ - w->borderless = borderless; - if (w->borderless) { - // borderless doesn't play nice with fullscreen; wait for later - if (!w->fullscreen) - [w->window setStyleMask:NSBorderlessWindowMask]; - } else { - [w->window setStyleMask:defaultStyleMask]; - // borderless doesn't play nice with fullscreen; restore state - if (w->fullscreen) { - w->suppressSizeChanged = YES; - [w->window toggleFullScreen:w->window]; - w->suppressSizeChanged = NO; - } - } -} - -void uiWindowSetChild(uiWindow *w, uiControl *child) -{ - NSView *childView; - - if (w->child != NULL) { - childView = (NSView *) uiControlHandle(w->child); - [childView removeFromSuperview]; - uiControlSetParent(w->child, NULL); - } - w->child = child; - if (w->child != NULL) { - uiControlSetParent(w->child, uiControl(w)); - childView = (NSView *) uiControlHandle(w->child); - uiDarwinControlSetSuperview(uiDarwinControl(w->child), [w->window contentView]); - uiDarwinControlSyncEnableState(uiDarwinControl(w->child), uiControlEnabledToUser(uiControl(w))); - } - windowRelayout(w); -} - -int uiWindowMargined(uiWindow *w) -{ - return w->margined; -} - -void uiWindowSetMargined(uiWindow *w, int margined) -{ - w->margined = margined; - singleChildConstraintsSetMargined(&(w->constraints), w->margined); -} - -static int defaultOnClosing(uiWindow *w, void *data) -{ - return 0; -} - -static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) -{ - // do nothing -} - -uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar) -{ - uiWindow *w; - - finalizeMenus(); - - uiDarwinNewControl(uiWindow, w); - - w->window = [[libuiNSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height) - styleMask:defaultStyleMask - backing:NSBackingStoreBuffered - defer:YES]; - [w->window setTitle:toNSString(title)]; - - // do NOT release when closed - // we manually do this in uiWindowDestroy() above - [w->window setReleasedWhenClosed:NO]; - - if (windowDelegate == nil) { - windowDelegate = [[windowDelegateClass new] autorelease]; - [delegates addObject:windowDelegate]; - } - [windowDelegate registerWindow:w]; - uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); - - return w; -} - -// utility function for menus -uiWindow *windowFromNSWindow(NSWindow *w) -{ - if (w == nil) - return NULL; - if (windowDelegate == nil) // no windows were created yet; we're called with some OS X-provided window - return NULL; - return [windowDelegate lookupWindow:w]; -} diff --git a/src/libui_sdl/libui/darwin/winmoveresize.m b/src/libui_sdl/libui/darwin/winmoveresize.m deleted file mode 100644 index 9145b7bb..00000000 --- a/src/libui_sdl/libui/darwin/winmoveresize.m +++ /dev/null @@ -1,253 +0,0 @@ -// 1 november 2016 -#import "uipriv_darwin.h" - -// because we are changing the window frame each time the mouse moves, the successive -[NSEvent locationInWindow]s cannot be meaningfully used together -// make sure they are all following some sort of standard to avoid this problem; the screen is the most obvious possibility since it requires only one conversion (the only one that a NSWindow provides) -static NSPoint makeIndependent(NSPoint p, NSWindow *w) -{ - NSRect r; - - r.origin = p; - // mikeash in irc.freenode.net/#macdev confirms both that any size will do and that we can safely ignore the resultant size - r.size = NSZeroSize; - return [w convertRectToScreen:r].origin; -} - -struct onMoveDragParams { - NSWindow *w; - // using the previous point causes weird issues like the mouse seeming to fall behind the window edge... so do this instead - // TODO will this make things like the menubar and dock easier too? - NSRect initialFrame; - NSPoint initialPoint; -}; - -void onMoveDrag(struct onMoveDragParams *p, NSEvent *e) -{ - NSPoint new; - NSRect frame; - CGFloat offx, offy; - - new = makeIndependent([e locationInWindow], p->w); - frame = p->initialFrame; - - offx = new.x - p->initialPoint.x; - offy = new.y - p->initialPoint.y; - frame.origin.x += offx; - frame.origin.y += offy; - - // TODO handle the menubar - // TODO wait the system does this for us already?! - - [p->w setFrameOrigin:frame.origin]; -} - -void doManualMove(NSWindow *w, NSEvent *initialEvent) -{ - __block struct onMoveDragParams mdp; - struct nextEventArgs nea; - BOOL (^handleEvent)(NSEvent *e); - __block BOOL done; - - // this is only available on 10.11 and newer (LONGTERM FUTURE) - // but use it if available; this lets us use the real OS dragging code, which means we can take advantage of OS features like Spaces - if ([w respondsToSelector:@selector(performWindowDragWithEvent:)]) { - [((id) w) performWindowDragWithEvent:initialEvent]; - return; - } - - mdp.w = w; - mdp.initialFrame = [mdp.w frame]; - mdp.initialPoint = makeIndependent([initialEvent locationInWindow], mdp.w); - - nea.mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask; - nea.duration = [NSDate distantFuture]; - nea.mode = NSEventTrackingRunLoopMode; // nextEventMatchingMask: docs suggest using this for manual mouse tracking - nea.dequeue = YES; - handleEvent = ^(NSEvent *e) { - if ([e type] == NSLeftMouseUp) { - done = YES; - return YES; // do not send - } - onMoveDrag(&mdp, e); - return YES; // do not send - }; - done = NO; - while (mainStep(&nea, handleEvent)) - if (done) - break; -} - -// see http://stackoverflow.com/a/40352996/3408572 -static void minMaxAutoLayoutSizes(NSWindow *w, NSSize *min, NSSize *max) -{ - NSLayoutConstraint *cw, *ch; - NSView *contentView; - NSRect prevFrame; - - // if adding these constraints causes the window to change size somehow, don't show it to the user and change it back afterwards - NSDisableScreenUpdates(); - prevFrame = [w frame]; - - // minimum: encourage the window to be as small as possible - contentView = [w contentView]; - cw = mkConstraint(contentView, NSLayoutAttributeWidth, - NSLayoutRelationEqual, - nil, NSLayoutAttributeNotAnAttribute, - 0, 0, - @"window minimum width finding constraint"); - [cw setPriority:NSLayoutPriorityDragThatCanResizeWindow]; - [contentView addConstraint:cw]; - ch = mkConstraint(contentView, NSLayoutAttributeHeight, - NSLayoutRelationEqual, - nil, NSLayoutAttributeNotAnAttribute, - 0, 0, - @"window minimum height finding constraint"); - [ch setPriority:NSLayoutPriorityDragThatCanResizeWindow]; - [contentView addConstraint:ch]; - *min = [contentView fittingSize]; - [contentView removeConstraint:cw]; - [contentView removeConstraint:ch]; - - // maximum: encourage the window to be as large as possible - contentView = [w contentView]; - cw = mkConstraint(contentView, NSLayoutAttributeWidth, - NSLayoutRelationEqual, - nil, NSLayoutAttributeNotAnAttribute, - 0, CGFLOAT_MAX, - @"window maximum width finding constraint"); - [cw setPriority:NSLayoutPriorityDragThatCanResizeWindow]; - [contentView addConstraint:cw]; - ch = mkConstraint(contentView, NSLayoutAttributeHeight, - NSLayoutRelationEqual, - nil, NSLayoutAttributeNotAnAttribute, - 0, CGFLOAT_MAX, - @"window maximum height finding constraint"); - [ch setPriority:NSLayoutPriorityDragThatCanResizeWindow]; - [contentView addConstraint:ch]; - *max = [contentView fittingSize]; - [contentView removeConstraint:cw]; - [contentView removeConstraint:ch]; - - [w setFrame:prevFrame display:YES]; // TODO really YES? - NSEnableScreenUpdates(); -} - -static void handleResizeLeft(NSRect *frame, NSPoint old, NSPoint new) -{ - frame->origin.x += new.x - old.x; - frame->size.width -= new.x - old.x; -} - -// TODO properly handle the menubar -// TODO wait, OS X does it for us?! -static void handleResizeTop(NSRect *frame, NSPoint old, NSPoint new) -{ - frame->size.height += new.y - old.y; -} - -static void handleResizeRight(NSRect *frame, NSPoint old, NSPoint new) -{ - frame->size.width += new.x - old.x; -} - - -// TODO properly handle the menubar -static void handleResizeBottom(NSRect *frame, NSPoint old, NSPoint new) -{ - frame->origin.y += new.y - old.y; - frame->size.height -= new.y - old.y; -} - -struct onResizeDragParams { - NSWindow *w; - // using the previous point causes weird issues like the mouse seeming to fall behind the window edge... so do this instead - // TODO will this make things like the menubar and dock easier too? - NSRect initialFrame; - NSPoint initialPoint; - uiWindowResizeEdge edge; - NSSize min; - NSSize max; -}; - -static void onResizeDrag(struct onResizeDragParams *p, NSEvent *e) -{ - NSPoint new; - NSRect frame; - - new = makeIndependent([e locationInWindow], p->w); - frame = p->initialFrame; - - // horizontal - switch (p->edge) { - case uiWindowResizeEdgeLeft: - case uiWindowResizeEdgeTopLeft: - case uiWindowResizeEdgeBottomLeft: - handleResizeLeft(&frame, p->initialPoint, new); - break; - case uiWindowResizeEdgeRight: - case uiWindowResizeEdgeTopRight: - case uiWindowResizeEdgeBottomRight: - handleResizeRight(&frame, p->initialPoint, new); - break; - } - // vertical - switch (p->edge) { - case uiWindowResizeEdgeTop: - case uiWindowResizeEdgeTopLeft: - case uiWindowResizeEdgeTopRight: - handleResizeTop(&frame, p->initialPoint, new); - break; - case uiWindowResizeEdgeBottom: - case uiWindowResizeEdgeBottomLeft: - case uiWindowResizeEdgeBottomRight: - handleResizeBottom(&frame, p->initialPoint, new); - break; - } - - // constrain - // TODO should we constrain against anything else as well? minMaxAutoLayoutSizes() already gives us nonnegative sizes, but... - if (frame.size.width < p->min.width) - frame.size.width = p->min.width; - if (frame.size.height < p->min.height) - frame.size.height = p->min.height; - // TODO > or >= ? - if (frame.size.width > p->max.width) - frame.size.width = p->max.width; - if (frame.size.height > p->max.height) - frame.size.height = p->max.height; - - [p->w setFrame:frame display:YES]; // and do reflect the new frame immediately -} - -// TODO do our events get fired with this? *should* they? -void doManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge) -{ - __block struct onResizeDragParams rdp; - struct nextEventArgs nea; - BOOL (^handleEvent)(NSEvent *e); - __block BOOL done; - - rdp.w = w; - rdp.initialFrame = [rdp.w frame]; - rdp.initialPoint = makeIndependent([initialEvent locationInWindow], rdp.w); - rdp.edge = edge; - // TODO what happens if these change during the loop? - minMaxAutoLayoutSizes(rdp.w, &(rdp.min), &(rdp.max)); - - nea.mask = NSLeftMouseDraggedMask | NSLeftMouseUpMask; - nea.duration = [NSDate distantFuture]; - nea.mode = NSEventTrackingRunLoopMode; // nextEventMatchingMask: docs suggest using this for manual mouse tracking - nea.dequeue = YES; - handleEvent = ^(NSEvent *e) { - if ([e type] == NSLeftMouseUp) { - done = YES; - return YES; // do not send - } - onResizeDrag(&rdp, e); - return YES; // do not send - }; - done = NO; - while (mainStep(&nea, handleEvent)) - if (done) - break; -} diff --git a/src/libui_sdl/libui/doc/area.md b/src/libui_sdl/libui/doc/area.md deleted file mode 100644 index d14be9c3..00000000 --- a/src/libui_sdl/libui/doc/area.md +++ /dev/null @@ -1,53 +0,0 @@ -# uiArea - -uiArea is a uiControl that provides a canvas you can draw on. It receives keyboard and mouse events, supports scrolling, is DPI aware, and has several other useful features. A uiArea consists of the drawing area itself and horizontal and vertical scrollbars. - -## The Area Handler - -A uiArea is driven by an *area handler*. An area handler is an object with several methods that uiArea calls to do certain tasks. To create an area handler, simply have a structure whose first member is of type `uiAreaHandler`: - -```c -struct uiAreaHandler { - void (*Draw)(uiAreaHandler *h, uiArea *a, uiAreaDrawParams *p); - void (*HScrollConfig)(uiAreaHandler *h, uiArea *a, uiAreaScrollConfig *c); - void (*VScrollConfig)(uiAreaHandler *h, uiArea *a, uiAreaScrollConfig *c); -} -``` - -## Drawing - -Unlike drawing canvas controls in other toolkits, uiArea does **not** have a fixed size. The coordinate (0, 0) is always the top-left corner of the drawing area, regardless of how big the uiArea is in the current window or where the scrollbars presently are. Instead, you simulate a size by setting the scrollbar bounds, and you are given the current scrolling positions to base your drawing with. - -The visible drawing area is called the *content area* by the drawing machinery. - -TODO have a diagram. - -When a part of the uiArea needs to be redrawn, the area handler's `Draw()` method is called. It receives the area handler, the uiArea, and a structure of parameters necessary for drawing. - -```c -struct uiAreaDrawParams { - uiDrawContext *context; - - intmax_t contentWidth; - intmax_t contentHeight; - - intmax_t hscrollpos; - intmax_t vscrollpos; - - intmax_t clipX; - intmax_t cilpY; - intmax_t clipWidth; - intmax_t clipHeight; - - TODO dpiX; - TODO dpiY; -}; -``` - -`context` is the drawing context; see drawing.md for details. - -`contentWidth` and `contentHeight` is the current width and height of the content area. `hscrollpos` and `vscrollpos` are the current horizontal and vertical positions of the scrollbars, in units defined by the scrollbar configurations; see below. - -`clipX`, `clipY`, `clipWidth`, and `clipHeight` define a rectangle, in content area coordinates, that the OS has requested to be redrawn. You can use this to optimize your drawing by only drawing where drawing is needed; the OS may choose to drop any drawing done outside the clip rectangle. - -`dpiX` and `dpiY` are the uiArea's current DPI in the X and Y directions, respectively. Do not save these values; they are not guaranteed to stay the same once `Draw()` returns. diff --git a/src/libui_sdl/libui/doc/areahandler b/src/libui_sdl/libui/doc/areahandler deleted file mode 100644 index 4c559db5..00000000 --- a/src/libui_sdl/libui/doc/areahandler +++ /dev/null @@ -1 +0,0 @@ -Yes, you keep ownership of the uiAreaHandler. libui only cares about the address you give uiNewArea(); it doesn't copy anything. You can even use the same uiAreaHandler on multiple uiAreas, which is why you get the uiArea as a parameter in each function. diff --git a/src/libui_sdl/libui/doc/draw.md b/src/libui_sdl/libui/doc/draw.md deleted file mode 100644 index ef849fd9..00000000 --- a/src/libui_sdl/libui/doc/draw.md +++ /dev/null @@ -1,42 +0,0 @@ -# The Drawing Model - -> Note: This model is not exclusive to libui; it is also applicable to many 2D graphics libraries, such as Direct2D, cairo, and Core Graphics. - -## The Coordinate System and Points - -In the traditional way we think of drawing, we think of rendering onto a plane of pixels. The pixels have a fixed size, and coordinates refer to the entire space that a pixel occupies. - -For instance, in the traditional model, the coordinate system looks like - -TODO image - -and when we say "draw a line from (0, 0) to (5, 5) exclusive", we mean "fill the spaces that are occupied by the pixels at (0, 0), (1, 1), (2, 2), (3, 3), and (4, 4)": - -TODO image - -Ugh. With pixels as big as the ones TODO. - -But now let's pretend we're working in a coordinate system where the point at (x, y) corresponds strictly to the top-left corner of the area that a pixel occupies. - -TODO image - -In this model, when we say "draw a line from (0, 0) to (5, 5)", we mean "draw a straight line filling every pixel that we cross if we traced a line from the top-left corner of what we used to call the pixel at (0, 0 to the top-left corner of what we used to call the pixel at (5, 5)": - -TODO image - -TODO. - -There are both technical and non-technical reasons for following this model. The technical reason is that implementing certain drawing operations, such as filling shapes, is much easier if we do things this way. The [cairo FAQ](http://www.cairographics.org/FAQ/#sharp_lines) explains in more detail. The non-technical reason has to do with DPI independence. - -## DPI Independence vs. DPI Awareness - -An upcoming trend in computing is the high-resolution display. These displays fit more dots in the same area that older screens could. The conventional term for the number of dots that fit in a given area is the "dots per inch", or DPI, measure. - -A naive approach to writing programs for these new displays is to think "well, if I just take the DPI and only use it in calculations where I need to deal with real-world measurements such as inches, rendering pure pixels as I always have, I should be fine". This kind of design is centered around *DPI awareness*. I know, I used to believe this too. But here's a little secret: this is wrong! A common myth about high-resolution monitors among non-technical people is that it makes the stuff on screen smaller. The mindset I just described causes this: TODO - -Instead, what we want out of a high-resolution display is *to show a more detailed view of the same image in the same space*. [The first image on Apple''s discussion of the topic](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Art/backing_store_2x.png) is the perfect example. On the left, you see a low-resolution monitor. Notice how big chunks of the shapes go into the boxes. When the code that maps points to pixels runs, it can't have two colors in one square, so it has to decide what color to use. TODO - -TODO -- talk about how this relates to the OpenGL unit cube -- talk about the various names (point, user space coordinate, device-independent pixel) -- talk about "scaling" diff --git a/src/libui_sdl/libui/doc/drawtext b/src/libui_sdl/libui/doc/drawtext deleted file mode 100644 index 9d377135..00000000 --- a/src/libui_sdl/libui/doc/drawtext +++ /dev/null @@ -1,13 +0,0 @@ -on some unix systems, alpha blending fonts may not be available; this depends on your installed version of pango and is determined at runtime by libui - -uiDrawTextLayoutExtents: document that the extent width can be greater than the requested width if the requested width is small enough that only one character can fit - - -font matching is closest match but the search method is OS defined - - -weight names in libui do not necessarily line up with their OS names - - -uiDrawFontHandle() may not return a unique handle per instance - diff --git a/src/libui_sdl/libui/doc/export/coretext b/src/libui_sdl/libui/doc/export/coretext deleted file mode 100644 index 0888383b..00000000 --- a/src/libui_sdl/libui/doc/export/coretext +++ /dev/null @@ -1,5 +0,0 @@ -font features are not provided by the collection and have to be added when asking for a font -it does preserve when going from CTFont to CTFontDescriptor -feature 17 has no flags in the header but can also hold small caps info -if a feature is present, it is ignored; other features will still show up - at least in the case of kLetterCaseTrait and kLowerCaseTrait diff --git a/src/libui_sdl/libui/doc/form b/src/libui_sdl/libui/doc/form deleted file mode 100644 index f24a94dc..00000000 --- a/src/libui_sdl/libui/doc/form +++ /dev/null @@ -1 +0,0 @@ -hiding a control also hides its label diff --git a/src/libui_sdl/libui/doc/main b/src/libui_sdl/libui/doc/main deleted file mode 100644 index 9fa9c369..00000000 --- a/src/libui_sdl/libui/doc/main +++ /dev/null @@ -1 +0,0 @@ -after uiQuit or if uiShouldQuit returns nonzero, uiQueueMain's effect is undefined diff --git a/src/libui_sdl/libui/doc/mainsteps b/src/libui_sdl/libui/doc/mainsteps deleted file mode 100644 index f572b21c..00000000 --- a/src/libui_sdl/libui/doc/mainsteps +++ /dev/null @@ -1 +0,0 @@ -the function passed to mainsteps must not return until uiQuit itself has been called; otherwise the results are undefined diff --git a/src/libui_sdl/libui/doc/slider b/src/libui_sdl/libui/doc/slider deleted file mode 100644 index 5a6ac040..00000000 --- a/src/libui_sdl/libui/doc/slider +++ /dev/null @@ -1 +0,0 @@ -if min >= max then they are swapped diff --git a/src/libui_sdl/libui/doc/spinbox b/src/libui_sdl/libui/doc/spinbox deleted file mode 100644 index 5a6ac040..00000000 --- a/src/libui_sdl/libui/doc/spinbox +++ /dev/null @@ -1 +0,0 @@ -if min >= max then they are swapped diff --git a/src/libui_sdl/libui/doc/static b/src/libui_sdl/libui/doc/static deleted file mode 100644 index fe1a09ce..00000000 --- a/src/libui_sdl/libui/doc/static +++ /dev/null @@ -1,2 +0,0 @@ -comctl6 -libui.res diff --git a/src/libui_sdl/libui/doc/windowmovesize b/src/libui_sdl/libui/doc/windowmovesize deleted file mode 100644 index ec8bd966..00000000 --- a/src/libui_sdl/libui/doc/windowmovesize +++ /dev/null @@ -1,3 +0,0 @@ -you should never need to use these functions -they are provided only for the cases when ABSOLUTELY NECESSARY -the operating system may ignore your requests, for instance, if you are giving it invalid numbers or a size too small to fit; this is all system-defined diff --git a/src/libui_sdl/libui/doc/winstatic b/src/libui_sdl/libui/doc/winstatic deleted file mode 100644 index 5f163cfd..00000000 --- a/src/libui_sdl/libui/doc/winstatic +++ /dev/null @@ -1 +0,0 @@ -libui uses resources starting at 29000 diff --git a/src/libui_sdl/libui/examples/CMakeLists.txt b/src/libui_sdl/libui/examples/CMakeLists.txt deleted file mode 100644 index 3a9ec4c9..00000000 --- a/src/libui_sdl/libui/examples/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# 3 june 2016 - -if(WIN32) - set(_EXAMPLE_RESOURCES_RC resources.rc) -endif() - -macro(_add_example _name) - _add_exec(${_name} ${ARGN}) - # because Microsoft's toolchain is dumb - if(MSVC) - set_property(TARGET ${_name} APPEND_STRING PROPERTY - LINK_FLAGS " /ENTRY:mainCRTStartup") - endif() -endmacro() - -_add_example(controlgallery - controlgallery/main.c - ${_EXAMPLE_RESOURCES_RC} -) - -_add_example(histogram - histogram/main.c - ${_EXAMPLE_RESOURCES_RC} -) - -_add_example(cpp-multithread - cpp-multithread/main.cpp - ${_EXAMPLE_RESOURCES_RC} -) -if(NOT WIN32) - target_link_libraries(cpp-multithread pthread) -endif() - -add_custom_target(examples - DEPENDS - controlgallery - histogram - cpp-multithread) diff --git a/src/libui_sdl/libui/examples/controlgallery/darwin.png b/src/libui_sdl/libui/examples/controlgallery/darwin.png deleted file mode 100644 index f61b54ba2d92f69006f789a8f8a1c56993b8db41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97260 zcmZU31CS=o((c%{xntYrj%{;i$F{v=oA21RZQHi(x%-`S?*E^-w<9XDIxEqcQC(ft z`GhOTNx;M4zyJXO!T*#LRRRJ6iTc~@~qTREP-Lp-zM|s8Y?wNSZOl72`#IOOv!UdzLXr(Igl(Qv2 z65kZ!gW46nx4+w;Tc2Cc-Iulmu0599eJwk$ar7X8Y!Dn&RInzX1l>ew7keiZdL}nT zfH)8o{BTP<{L(HkQB4iZ&EaG3-am5=*P;B_xBBaFo4!2XzqL|7K#e|t{4S6#&I$K1 zqjzY4a$7(0OKO1(Adp+_gsm1JzWx|sPzxgg(fWWwS{r7=U$h6KvpZ+vMIu?j0cA(a z6hQzBb{pywZ81RAiVy}j#F2bZA&33O2zdMm82tjWdnDmz-rbGEbwlVy>H4lgeIR7_ z{$BZ!5csuIS!;#S!9+$*9hv#?of-Yz9uzwG`4xhsbQ(~4gn(--epJcMI`;3w1-;KlaLcE`Ne{%ETE!Ti%GGL{R}3aF(gXmA0fSF)g2Jw7l?r`fHq z^A-(L8*HA`jgfp|_Dp?SeY97+soS~49sxH~4C#X{_V-y$Vc;HA%qt&#VkV*cy*3`y zQVhHc^Y&SU18kUm{nuo#K+lRv1n8ImQQs>j2O5fQ2txOpnMCmF=bVHpSWp_5)g;TA zuuRAPb(cu3q@VR9=$SRt>YPo4z?rs6Mb`~#x6ltL;6(q`CC!8C zN(^N|2o)qS5WfqC(QAUL3_9eIdE_5~@=!29Oulc}Hcb$IZlYap5^ax(;Qkqvw;6oG zy`Es9fYuq0U)Bw5cMB3_C|aPEukATN{nyn-vNb~*juljDcZi4rLC#o8rG9q;BNef( zK+J9M^vK=AH_dz#o)e@K+7qY~oMvz>ey$m6J{IoE%%$H(^gvcUoJNxm%O_sQ87$q- zGe%IBstv?in7c7{67_klezaQP*x|q)xXkRTqHppc_P#Bjd@0{wTM*~I(Z?y7dVlmD zF=4j_vYFlhkG3@8->Ia&2iA|avI{;7rVIEg9B1@psEaUQ3d@StB|Zy{@E;T?Th`)z z*VSBB4zOYu3O?tQnaZh(FR$BOa$kdfZKt+KxUpF6wM3C5fcTQc+#L;IP!kCRq?)js zgal*-B?T2w17qLqHU2J6tE+XS_5N;C;&vc~V~HS+?_}^upqX2g)wy5a$>En`!UXU= zx`f@Fzdw@UI&XV`w0it1;N*HBgZ#mm$;omd8vOYgfs+k*>_DyzD45TCiSP`wfLsFM zV&NTnk?rsj0}^s!76QcWpc?|@X5eiC-wlv>fv4kEQo#s&@m?U*h@kp}M8mN6f?kLf zC2^DjSc&*X!0JNqh+Ib?VFE~UIe&39K#m39xLA&_6)o1a1kk%z!+A ziuXD(!cM?O^xoA#SOIDG%GF@vfl2g_+F@iuV)iH5fo_1f_CN1Z+;Dy%>xlxR0S|_t zh>qs7Du|a{QX;Al{rMv$hA)VoPpx>Yh#yuRs<>aGxxkDQVI~fnYZ~{$D!~KzoS8jQ zc@T1n8DF<2%Z3r(-{W!wKh%oK{ zW4svGcp44gd(}rUkZhb$!%-7cgSsMyhcFzTFm$@tv_I0Kp~GGUw(Qp)joT-?*R>Dr z=F@?)g?8;9(__8|d;9o8|AFKK(=FUDNh$>ptIrzBArC)dlx35JoD@m_nU1bSu4S*K zt3|Pfv|3KG3?_}OIa*w?qAbcNs7*P&b4s}Xl z3XoZu$JZR6LE@=NefZVH=W@rXQ2j=NtLW{S67M1`O)Y=x^k&=g%cXAmrG~**hNq z8bBkwCp;ybCM+w=5Nr|576cj`1N{s&9exwB5_W;XMR6ySD6S&Hs?i|%5PcG#+LBtn z!e6UaYhjOI4|{8J>$u18BMfEzM?M)f8G*DB8QTvLvT-uVLIWz*QiD?F($Kk@hICf3 zHl4RPIB{`ha^WJSqf*+e3V*AP3$9fT2P=mqhct&uhnz#P1HOZpvF$j0Wd&6z^$HM;#B5L z?iB1a+E(m5{0R2o^&oc|WsABYzNOZBS=m+7)$J4YmFQm}6ebkdYc2vVQf64c8y}af z_-7X0II%YE7I+^RH9oxlXXz-7GVwgoykn80S(#b;giWgPMCC+Gxz}uz01J@)MPg zL?%S!LTH0+5czQ12##=;(4rBap>1P`#Dc^h#P7t&#rgllM~_A0#4P>cC*YH4%wHN1 zWYS}@uB9DOEf$a?v9aCAaO-@jd%1?DhfYCFLm@?ZPbi3Yh%btlO_;tAzP?*utk<@4 z9lGM6f}ko^&QsZ5$Y$MbsAw2`h8dr>|HxJ?pT0 zv$MUQ@?UyWJOiGUpAZiyj}s3n@NWd{7}SZI8J~}Zx&xmPs0gU}8?rG|IqWnp?FNxA z;=)KtC7SUoC(Xy?r*bH3sD5#g+gCn^JqC*_(|{-|Q88J6#rZ>hJdY;ytZ zi>gA($(zj{tp-+awL;gnxF6fvJhI>Vk9QpHkIis+aUpP{aM!2CvjsK>mJ&UIb;8qX7BTTCsEo$}4q z_f<=qPo6l>TG!>9wx{Zswm!LUx$c72xrcdg{Y^rXz0nffF>N7D@Xm<1h}%9^w=Z9) z>l88KnG)hT9{l)(kAztSu(%n%7~fWh?r*RY5ugm%`WRh%?y9d^ch2)IYcGu)L$+_* z++E)MyBxQ-x)bd=37Xg8*RaJe#b-rHMLgy*<`4oGFO08DXZvGTPZUM+6#UX&U3V#8 z`k#(AjtTb*uaCij`kdXFpJjKA=Cd}pi_JH-G}4e=jy~18OB!AG{g1;7Qho9p(|f9; zi_vW5jhN@V=jVzh)b97xe!|pvSWrEEnm}P!K#ZjBcyym?UytRvxls+qA}L`TMozKo zYQR{2lCiidu>E$Ny#6qPbh(a9Fsb%dT=ZbJGNj_t@_wfZqU0VH5U}FZ^A>Z`82oDb zP11P3*Z0yam`6F!UdiMH;w&~LO?nA$8bT+I65^N6$VX8Nn%-YX|@8* zav38Zwq4oF!!LBp#$N2|^sxHT##LvD^YN)Hi(kL31bpi)PWp+>5PCgD$$aA=0is(@xc|m38ZgR~@Gr?V+6vYqn24zC=fcE4lZikHlSuYrBWT zsPY7nI=*X6Yg{g$n$P!Dn6eBpT`->3oKsv~H)c21@1mFOb)%%$&vIn4q0=v3HLoSS z(&?Wsr%%Uc-F3&pN7k4sT~OXhIuCD4kGh7hD>2IgTf(}^_ zHv}l5Bzd@u9GTDzx%mp)v+qm+soE4Vc{2yp&Q%EXXk_C2?Lq9#umW)r955^pu5^6*Ye< zrO5{?qAPutv4>}>d8c1$IjeN(j=ozG#67CDSG&s&VCcEs~4Yo|RciLUww{+|mm`AHm$T8TW5@Iv6ytZFU zciViQ`F;B539dXBAW0c zxgh*Nx_!=dz38UEOY%~ZCy^k2H`XFjG-OGy(JI(`?p@6B1<~#(9sva*53%ydn}^re zWcS1Y_zG*-K3w>bWZ$Sg9=}k?bODv>@SXZjKAY3|$w~WAVet-o6lc1=wQ~e$W(c9bA z{0j9wiO>zsgx?Cwi#rHk&Hdu@hh@Q=#r4U%dBgOfK4+(lhwAOy)XSXqAoN-Lcmk|4 z^Sls?Dxu!AgRjH8*Isq&>kC6&L;=~F>C5nNj`}iX_lG>}ia#8q1amft9b%ub*^J^Z zkfmUGKv+rVFFbBS(vVjF$Kg0T*V}gsD~nf)6zG`KwJ`G&X{sqNE-qv*XrCFNsMRU`G)~RmUkP zHK<`I>8ao;mrDxDxXVXN`p*D3QR!(~^lM6M<=la7svgkmw2!ZknDB4#(^!Q#?WrSa zMl$-Tx=aEFyT+wvVl_C;Hcg|okHRi6k(;UBfg)`HKtjnp$1#73(y{`FwQIn;V~itD zJl|yJO2^h^$4S@4g@XNB!$0bEL9> zU-@qUL?t@o8>VI>mi>o4wLNWABa}lF^Z2raPFMR&j}9J&L0)vZODSntj_I9AjZwVq z`4ne+TTPdxuA5JKE)U27hw#=2NPWDvGT8Ni#<) zdK*d>8@Hh>o?y^-@EKE7^8C2sUSNJa6l5WV8_5jS`nFq+(0YH zz;<(BjONgORbs#+%6rqVy^wIR^~Q)L5Y4fhpb-~@7z&h5P``y8I;$CZD&Rf)J$JO+ zfW89ugt2o26eVKeKIqc@)I<_yLuW2esNiUZz)(X?bO9RN6~OGko&-EmsD1AH)OOW3 z!Y>9N;2+dcY?D;!whb-~QD7v*0gR%>LaynOL_??)Czq$~*ojzW*j(5#jI)fFWW5D4 zW^j%Ou%yz^<&@{9?8Z%sPm&0{5^TlD$2?Wu8+9AJti(J8`xV^5MQ62}q|Vr!EZ6B80r)Mu2P)L@ji0=X(hkGQUF)>y;BVe- zyt^XtU3S8_M!zw}CV5YOWPW~v&VfvW%POOZFbjwFlf{mBVpPh}MZOXo<7~&?P=)hp z8m8>pJSR3RJUOLD?o2>x{`RDKX1b7{OdDh4Om!~dvi*SiR9ydn9af3nrmmy&QTVOr z(!SBP_g>mHR&^%LCe}Fmm>7b83{PL9=jGU1%T?)Y-afpzxvW*q@cip3WSf6R-J!az z+alNUW_D%)^+S2HR%E)n>ki8{n@A?Un45pcd{7{;d+hiX<4^Y;Z4+%UL;2UsYrW~D zr{gyguo@8#T7cXQMxTg7ENUX0DoNTG?*ue%U*3)V3&aQV=xS8#d;#8KjFylzfN$3Q z#O8rS97bda&6vOtT7%_6&x!#dqJ98>C~8mahUrC{m6sKom9!zfp%|(m2&@k+3wIMV zAGtO`FR&|EC@L?@9(UjRhXg(;cq~RLi>8LgZ_Vb~=-R>B`kH1tH@m(}c%7>a){QJ) zrm*Vb*Qq;Yumi9zXct&~j3*35j6!s8iX~D#x;Rp7(nC^f24j+P(qj7RvfQGQLX#3J zK%EGiFr9X%_2EFzJ#`al* z7xHIOI_JtzU+zZ!#3{EGTb5~*IsUFOzdw69t7ctcm18B-`=P__E>`%eS1!M9H2fu( zZ8^ED+rFE9q&H@r%>(K>e_j6Ii&cWN!8E|?^%=gc%&7GwbN@P?@~%e{)$QYXll63P zp)weG89KQ7nUnlom%7g5Yj3zS{;>RLizhv{ot5nRU84V5Q&#KZHUAyo16|~@In22y*2XmXVPy)=Khzf{b>E z7Pdmwiv9xZ$tK!Fj%~_T=W@e>7o+1Mth)M^5HpvA0}0)b9+}nQNhT~R9PuZwDDyqV zT(t@R*jFM2)d-~)2~C?|q4Z-yn_oz|S=Ul5LU~n+-e(g!C{MqKF;0TreDP5-MssCF zrGzz=OHbE?;_zvuboM&?^B_KEXUW!Ye%LP4uQ}i-A*Eh6Vxv6g-8 z%a~|j!E!r_a!slGDJ?dcXHXqZed9CV$nAJALiYGQZvdZ`T95068*vq7o?F=hz^Y}V za__vfZOrfYMj9yF_V3NJ^yymG0rqHC3%!z-pjJG4(~7~0#!lTlK$r4?)~fRxF4ZQX zP21DcmRg(R8~v%?(q|#0A?P(kCqWc^JHHS2-owLH>RkQDF`@oh=a}c`UDU<;LU`}b z-RE#+M6)1)0pAX$_9x9-hHMjjv2@-Q3YF@GLfnpL=81mlzz74nI)2 z#PYH__1{(=`(qy*h@-E`XML5|5(}8q-Vt$dumA+U{>r0SJiKjr(uc+SJLA$j#cy#*y2NkK|tx+<*K3uo*~* z{w3mM$w#6gt3V`T>tIU6M$bymNWu?8L`1~vU}DCtBr5(N^}ly~B)^=T?6?^iTwPu1 zU0LXD9n2Y+xVX3&7?~NEnd$yY&^fx>I2pRp**KE^+sOa5BWmhs>|kN%WMOMV^p9Ob zBU@)DJ`$3D9R1Jr@8>jiv-n?6Hje)Z>u-Pz|BNs&(K9mqkL|yzy#H{y6)fCLtu#a} ztW9kk|N7u(XJg_0m;C=X^1mMcOH=cIHQCrW{#*0EM*gG8%kWPC{}s@`v-L0T-*oZA z@G|^Q>iJ=!UQ2U+tI9__dO7Q^}BNM>^Z0d&OmIBJJ>h<&Ez>Rq_OX7;mC$+7fceVYV z>nOBPoS-Crs83!M^}45!T-Y@+{lR9D=aT#>+Fda{zE{$S4MzGH> zm|x@FMWo!;PLUG_+7~nwtL2Y(+9_A7qFq-GkLlE1Ng2AENhyYxV?f*(9sTX2(QcAc zf?l1*7a4Q^39(BRIDv{*A7FKd+C$~GU#adc#t+vWU)NRqEA6mc+y?$I`8uZ+@^O%W zsA$ML<7sl%BUZcX`%AY*2a!nzA9^NN0$uDl1E6~B6;%vrE>?Bi0>kU>Rs;fNOzlw1 zdxEG~3MUwyMlCaCM@bV22@DKaNbuieXOGxUF==RGLZ;(oFJh(66c&fW#_QID z>i;*@bYGSwZJI!{5ok1-&chP4*Xy^DLO(2T< z+PA!;zOw`e;XsE5_NRYj0sz3Qhh??`-H6obVY-SbZ?W470{6HCi`~+XlQ!`U7COS- zJZ1nocLa#X+^SClh-1K%J$W+q)C# zoa0g?4TsIZmE5C1I#fS)8=k%umL}fq00>1sXK=MXI|ol2jh1SiX)inUHl~wFOHUE_ zn>Hs3QJp}fzWg@{>wo|~zXOwIY{6AqHo8Ls6U`407sSlQ_Y=E4S9o2Tc zr>d+#ANj6`F}f;=s5%!{7NLO+)T}^UQrh!YTAF;)e%=-yW@WpR9z~7IS*ZFqZW6fE zmvq2*HxmF4M?D7d41Z@nUG!d2O_C2}3Ml^9yb(vkb zVew1^)hc8@&7Y9}6EQi2fq>%4M1y zlv<0l=x{U5dR(NtJYwG;IDO)_NH54|b-rj&3|I#_a+-hvzVjNFQFN>u1g>){-R(hENJt;87-z1^*=l3Z%#H30h!4d~*?Elc zORZ0?t`8Onk?a#V&+PrN(ronWCSBQ95{#M(M?zniZYQh&hHRT_>fMo9*=?hla{c|L zxcOVj@(%G(Vqcn#^&=QWe)0z1I|k9dd$~*rSf8tNce{i#OeEm%=S+utAD}zpBmpyz z@h|WZ$ZI39dBBBL9G3Xbdpzha=jJg}*Wxw-Mf$?Qs_WlFi*dXsfk3o@7M6&|@Ecgh?MDciv)cN99(*~B<`UgmNyc{;rv(HPe)&p~F0;6SUFn$wsp*Mp7L{ZxPNKn2 z^y-!skQpn&@zEC}1Cyn>uE`QG4jEDU0GHD17-H>e6&(hq-rYRB1k(c+uO#UF?9YE8}9CdAb)Jj@CaEoZ)0}$`{)nAAkYYfYQOBht*^{d$$YbERTBX)u z9^=tiCd^gm^OheB0E87O5Xkf*U6=dVnD(VxAWnQcX!cgs&T;yyrCOI%m4@e?Rc+!O z?Ebr*pfpjrOvQ9#=3Iz(<(69YYx)k6$$OVvRMj$MDQS9VzuFg!gk+}d9M$dZt4VUb z6Q{bnQ(?Bx0irs}jo`BFu^+S&z-Yao&8bj^VbfX5d^DXJQxW32A9(u={QVWkRnOle zuN_nFaahJW$Orlku)e(ek@qC8%-EpVPd~AEZ@!lxc5XC7$sP z0nmSk;Pm{(ay0!3V(Gj6^Aqf`p1keZ6OON{yl^ymc>Cf)l=l4v)T`9)u44L}EI9s>&c|4}(NCC^nw}p=##U{C?%*|^;ft89dJaVBk^>)wXg7aMPxL9wLY%?G~F+(`BE$hdvT z=+yR&&FiC1+34x#pRMeA5Ns1B3o3AQ|!^s zX#CmDWdkQNl?jfAA1hqmhf9`hd$-rKTO#mk+W6wL(n*R#9#Hiw+7??3lO+verLlvdo+Df|@_)vQvb6@HD+FHZhZuwwFE zb$@Z@)eAJ^a9TYxuFZ{j$Gg?d2<<$X{tEv-Xsp;8r%x_NW}17DPZg|=aJE>j7xUJeut9SePM=x<#%{+#?~b~k8suZ(VRV;mdSCu5_Nc!Q%o?F-;c12 zX{EJh0r7y@#~5UZ(0~!xhXDx@@qJ%Q1R(jPUMSIapxMPGWvWyP>eT+)@7q zFlT!04sC$3u;AqPW%k)Y^RM$UC-G=p37?gZ?(>-+ks@ss@NtHsO)$$d26xr|GOFP8 zeOLf!NO5BImiW3nI6YXaVGO%m4M0=pyf3lB(@0a(G9|@&e;_^HGOF3~hmmtE_owON z);Jsk$5+Db?d8L}1Unph+7fG*b~D8$WJl^+P{hS%iHU+midU@33UonF!+U^BWG&8~ z*J{T;JUh^SJ~-pqcLYH@#lX^F8MBg+;%at4mWtrIYRXYu7#fa|eVjVVm)|ZmD9f|P zNcR`B6q6)?mAE&Oi-`}}XG(3x$P}Z)+jihDUwIOC<5&Gz_h=MZ)LN9ucYut-kXgB`#1pAeZ2zfe=|bH6bBn!ja<1?p6c~s3%_*Yz_*(_yphoaq=g({N;Q1s zy5*U05_VzYq)o+@Eo<9u;bc`Vj=4biyS zt_rNMUOQe~_>fs)Y^DqA2Ye29{K-I3x_L^NHUyolT(5opLCxnuI3(Z$1K864*{3=% zGs>{rR(9w=amjeWh@Rm(%<|br!p@75aom}UCN3?C+VS=zxlo5cfL15><-&|QfAryp z0a!oJTBJWU|L$G>CM!(h)_8q;zdcjdwKw`)cC$a@82N#;()#P?Z%*;?(+Eyrr);c+j5~8_o8B-(zaUpjD-4r`Js_S9weQ z2H)I+ty}RZiE@S_#*~ z5ANTC{yaFO#2YQj?juHUT|g$Z`={u(yYz3rgvy=PPq16~%m6sH%K~pO;x4vje{4I7 zAPBI(sv-b``E*jXT2>|7Ww6}WIw9~8=eu%k-R{#CPPMm$xAEKRYTLhyU8)pdjE~KW zcSoDp(1aqmncO0ec3 zKUfzCa%~j7(qo2=nrc$@0Q3&twNd6Np9zkTu_mWLfTD7L?>uKne(H~P~ zJQKalTdOIq;RYLI9*OsvR)SPOdh~eoK0(JK3rxL{h3bd3!Kx@x{W>P}xDMbpTRa z2dpd4lv<+_tEyhY5{G2WQIwcBWGYqH^Y>L%7cgCmtKe%5d({eSf`fwcc{TB(kT3}) zB7FK{kC>N&@}~Qr^Mw|FogG_TYwr4_Qbz5j+khYT50sp=ZypVj zlVFz=C`1a$es&S}Qb9Aa?SSR*X;V-S^S^O`w^LU)c)fFe@w(&8zg&t+6{Wwwu_kb1yCl2vaPOkJ z)FeHwlZ4l0PM%D!=Pp(k-h-nL{CJLw(JW(Bt1B>voE-12sY(;Nz8 zp9|>r<&hS?7%EM~Q^N5+M`NYn$+}Vr)Mh$}F0wO=TTJjggA#l6s2y1w$2etdXl-kX z@HUBp_$8A(VvJLmYzsn>fjwt{@MY7cQ7%bT!KTR*SD{YKlZER%!-C|$-+*NHbZ1@W zqn2(aw*4|F6Zxh$Kaqt^p|aYF)#Uo@HOZ_91twBZ?*=2)J{FzfdHpZ&Z4@8c;Y3HHj>rZy;pP)QfE80SDt%xu>_}KM z*6O-8Wt$w%!t zR#^(Dm}FSGvFH2U+5{&eT;tsG`SG)K(F+{AkT@pX*7Le?$W zn6||M!Pz6NRq5^FZlKWLGoN=1^pA)?G^yM-yP<@AKTVsrJj%;gD2!$@G*V~T>fo8H z^e?3xfPEUlqeTRaFRKVnGz19FyHmq%9estI`uS7sIC3QG!KVh$H99{LoNP3J*VU^X zCOICmbWcc=#_ZB%>@Ct-OOsi#Mi%ka{afZXdOo|Yd%B-FB)G;kKk8+bZLAN++$eud zYzRwLm_dyXaOg9LB=|S)t=LM}GKr)Fb9bGm5UTW{Y+-z-ae%oDBX?}M#yaGks{k`V z$O-cCvN~~|iHi}XVJv;rJ?aOEsfl52JMx)u^L4+GN|s*CRZ(vdr+in0Uzjx#RTz4* zQY(iY@c`_*%-ox7>Bs2w3bnWljG@||FC)_1Xt>`O6!B!5hrj7G&`9bLd?egO<%N>9-o%) zthF8Ov#hF;)}cGS3tFtuBxNCWUq|B@CMdTj_mPn;wlC=!@U__IJx z*LLf#bys>WG*L)^ef0x9?Yxa@vbD_parj8c`oQzn#r}D^zobw%{HV>cS|n}G)K0wF z=ysg1xvYZ>`g#*ft9;4YXc3{y~sH%IqCatSv8~cm#C?z6){+E(U@Y^znXdy)5 z?8GYOjbgFkK<8vzb;Orx`b`?)7##$T1s7-hzCQH!os&xovI%z0p#`Un>q4VLWce_Yj za;rVknoiCRaYAo@3%kWK!ON{OY4}rC6@1GMakKr7(GG{vhH7^(Fbi%28O>9lE2Gnh zwwuolUk$!)D75XQgv*9?>hr8fw#|cJUo8~y7(8^0jb6lca+W`f_B-(I#E9VO8{KTa z5N-qfH`;bL7syj&UQ3${48Mmd&ZlH;OQQIZp;wD?ZIb0oOq6PBdoDD$?l#C{8Ca>C zy{Rv848NOtxaA50zT}au9yaj$jL@$vq>yQS{J=)m&)wGNqdZfxDnp^Vs)aj5QUe-s zUN&fXfmQfb&*hyN1e0>~cu5B7G8oeYLP0&R;ZQ#k!kf>kqYKQ@gxdMY0LOOR}A~^Rfeu z{Ig$Vd3kwfC4zK?Klh3KehO~Aw3|<7`)FePm^Z+;sSZ~p>VNOsFVCr9d`9pEeJ-ms0`d$ZXE;rz-gtOX>9`rm`lZ4F92aMQ z@-#x^R3;m|z&o8@?rcoBF|Xt8Sq?5~irXms$r%Ny4NccjB77c99^twcjJiw=zOI1f zUYBe~K(<$=+(o(|k)1Asx)F1E;j}B>Gw^Z9A z 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

ODYohH}_xY*+xp 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 diff --git a/src/libui_sdl/libui/examples/controlgallery/main.c b/src/libui_sdl/libui/examples/controlgallery/main.c deleted file mode 100644 index c0d536c1..00000000 --- a/src/libui_sdl/libui/examples/controlgallery/main.c +++ /dev/null @@ -1,540 +0,0 @@ -// 2 september 2015 -#include -#include -#include "../../ui.h" - -static int onClosing(uiWindow *w, void *data) -{ - uiQuit(); - return 1; -} - -static int onShouldQuit(void *data) -{ - uiWindow *mainwin = uiWindow(data); - - uiControlDestroy(uiControl(mainwin)); - return 1; -} - -static uiControl *makeBasicControlsPage(void) -{ - uiBox *vbox; - uiBox *hbox; - uiGroup *group; - uiForm *entryForm; - - vbox = uiNewVerticalBox(); - uiBoxSetPadded(vbox, 1); - - hbox = uiNewHorizontalBox(); - uiBoxSetPadded(hbox, 1); - uiBoxAppend(vbox, uiControl(hbox), 0); - - uiBoxAppend(hbox, - uiControl(uiNewButton("Button")), - 0); - uiBoxAppend(hbox, - uiControl(uiNewCheckbox("Checkbox")), - 0); - - uiBoxAppend(vbox, - uiControl(uiNewLabel("This is a label. Right now, labels can only span one line.")), - 0); - - uiBoxAppend(vbox, - uiControl(uiNewHorizontalSeparator()), - 0); - - group = uiNewGroup("Entries"); - uiGroupSetMargined(group, 1); - uiBoxAppend(vbox, uiControl(group), 1); - - entryForm = uiNewForm(); - uiFormSetPadded(entryForm, 1); - uiGroupSetChild(group, uiControl(entryForm)); - - uiFormAppend(entryForm, - "Entry", - uiControl(uiNewEntry()), - 0); - uiFormAppend(entryForm, - "Password Entry", - uiControl(uiNewPasswordEntry()), - 0); - uiFormAppend(entryForm, - "Search Entry", - uiControl(uiNewSearchEntry()), - 0); - uiFormAppend(entryForm, - "Multiline Entry", - uiControl(uiNewMultilineEntry()), - 1); - uiFormAppend(entryForm, - "Multiline Entry No Wrap", - uiControl(uiNewNonWrappingMultilineEntry()), - 1); - - return uiControl(vbox); -} - -// TODO make these not global -static uiSpinbox *spinbox; -static uiSlider *slider; -static uiProgressBar *pbar; - -static void onSpinboxChanged(uiSpinbox *s, void *data) -{ - uiSliderSetValue(slider, uiSpinboxValue(s)); - uiProgressBarSetValue(pbar, uiSpinboxValue(s)); -} - -static void onSliderChanged(uiSlider *s, void *data) -{ - uiSpinboxSetValue(spinbox, uiSliderValue(s)); - uiProgressBarSetValue(pbar, uiSliderValue(s)); -} - -static uiControl *makeNumbersPage() -{ - uiBox *hbox; - uiGroup *group; - uiBox *vbox; - uiProgressBar *ip; - uiCombobox *cbox; - uiEditableCombobox *ecbox; - uiRadioButtons *rb; - - hbox = uiNewHorizontalBox(); - uiBoxSetPadded(hbox, 1); - - group = uiNewGroup("Numbers"); - uiGroupSetMargined(group, 1); - uiBoxAppend(hbox, uiControl(group), 1); - - vbox = uiNewVerticalBox(); - uiBoxSetPadded(vbox, 1); - uiGroupSetChild(group, uiControl(vbox)); - - spinbox = uiNewSpinbox(0, 100); - slider = uiNewSlider(0, 100); - pbar = uiNewProgressBar(); - uiSpinboxOnChanged(spinbox, onSpinboxChanged, NULL); - uiSliderOnChanged(slider, onSliderChanged, NULL); - uiBoxAppend(vbox, uiControl(spinbox), 0); - uiBoxAppend(vbox, uiControl(slider), 0); - uiBoxAppend(vbox, uiControl(pbar), 0); - - ip = uiNewProgressBar(); - uiProgressBarSetValue(ip, -1); - uiBoxAppend(vbox, uiControl(ip), 0); - - group = uiNewGroup("Lists"); - uiGroupSetMargined(group, 1); - uiBoxAppend(hbox, uiControl(group), 1); - - vbox = uiNewVerticalBox(); - uiBoxSetPadded(vbox, 1); - uiGroupSetChild(group, uiControl(vbox)); - - cbox = uiNewCombobox(); - uiComboboxAppend(cbox, "Combobox Item 1"); - uiComboboxAppend(cbox, "Combobox Item 2"); - uiComboboxAppend(cbox, "Combobox Item 3"); - uiBoxAppend(vbox, uiControl(cbox), 0); - - ecbox = uiNewEditableCombobox(); - uiEditableComboboxAppend(ecbox, "Editable Item 1"); - uiEditableComboboxAppend(ecbox, "Editable Item 2"); - uiEditableComboboxAppend(ecbox, "Editable Item 3"); - uiBoxAppend(vbox, uiControl(ecbox), 0); - - rb = uiNewRadioButtons(); - uiRadioButtonsAppend(rb, "Radio Button 1"); - uiRadioButtonsAppend(rb, "Radio Button 2"); - uiRadioButtonsAppend(rb, "Radio Button 3"); - uiBoxAppend(vbox, uiControl(rb), 0); - - return uiControl(hbox); -} - -// TODO make this not global -static uiWindow *mainwin; - -static void onOpenFileClicked(uiButton *b, void *data) -{ - uiEntry *entry = uiEntry(data); - char *filename; - - filename = uiOpenFile(mainwin); - if (filename == NULL) { - uiEntrySetText(entry, "(cancelled)"); - return; - } - uiEntrySetText(entry, filename); - uiFreeText(filename); -} - -static void onSaveFileClicked(uiButton *b, void *data) -{ - uiEntry *entry = uiEntry(data); - char *filename; - - filename = uiSaveFile(mainwin); - if (filename == NULL) { - uiEntrySetText(entry, "(cancelled)"); - return; - } - uiEntrySetText(entry, filename); - uiFreeText(filename); -} - -static void onMsgBoxClicked(uiButton *b, void *data) -{ - uiMsgBox(mainwin, - "This is a normal message box.", - "More detailed information can be shown here."); -} - -static void onMsgBoxErrorClicked(uiButton *b, void *data) -{ - uiMsgBoxError(mainwin, - "This message box describes an error.", - "More detailed information can be shown here."); -} - -static uiControl *makeDataChoosersPage(void) -{ - uiBox *hbox; - uiBox *vbox; - uiGrid *grid; - uiButton *button; - uiEntry *entry; - uiGrid *msggrid; - - hbox = uiNewHorizontalBox(); - uiBoxSetPadded(hbox, 1); - - vbox = uiNewVerticalBox(); - uiBoxSetPadded(vbox, 1); - uiBoxAppend(hbox, uiControl(vbox), 0); - - uiBoxAppend(vbox, - uiControl(uiNewDatePicker()), - 0); - uiBoxAppend(vbox, - uiControl(uiNewTimePicker()), - 0); - uiBoxAppend(vbox, - uiControl(uiNewDateTimePicker()), - 0); - - uiBoxAppend(vbox, - uiControl(uiNewFontButton()), - 0); - uiBoxAppend(vbox, - uiControl(uiNewColorButton()), - 0); - - uiBoxAppend(hbox, - uiControl(uiNewVerticalSeparator()), - 0); - - vbox = uiNewVerticalBox(); - uiBoxSetPadded(vbox, 1); - uiBoxAppend(hbox, uiControl(vbox), 1); - - grid = uiNewGrid(); - uiGridSetPadded(grid, 1); - uiBoxAppend(vbox, uiControl(grid), 0); - - button = uiNewButton("Open File"); - entry = uiNewEntry(); - uiEntrySetReadOnly(entry, 1); - uiButtonOnClicked(button, onOpenFileClicked, entry); - uiGridAppend(grid, uiControl(button), - 0, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(grid, uiControl(entry), - 1, 0, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - - button = uiNewButton("Save File"); - entry = uiNewEntry(); - uiEntrySetReadOnly(entry, 1); - uiButtonOnClicked(button, onSaveFileClicked, entry); - uiGridAppend(grid, uiControl(button), - 0, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(grid, uiControl(entry), - 1, 1, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - - msggrid = uiNewGrid(); - uiGridSetPadded(msggrid, 1); - uiGridAppend(grid, uiControl(msggrid), - 0, 2, 2, 1, - 0, uiAlignCenter, 0, uiAlignStart); - - button = uiNewButton("Message Box"); - uiButtonOnClicked(button, onMsgBoxClicked, NULL); - uiGridAppend(msggrid, uiControl(button), - 0, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - button = uiNewButton("Error Box"); - uiButtonOnClicked(button, onMsgBoxErrorClicked, NULL); - uiGridAppend(msggrid, uiControl(button), - 1, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - - return uiControl(hbox); -} - -int main(void) -{ - uiInitOptions options; - const char *err; - uiTab *tab; - - memset(&options, 0, sizeof (uiInitOptions)); - err = uiInit(&options); - if (err != NULL) { - fprintf(stderr, "error initializing libui: %s", err); - uiFreeInitError(err); - return 1; - } - - mainwin = uiNewWindow("libui Control Gallery", 640, 480, 1); - uiWindowOnClosing(mainwin, onClosing, NULL); - uiOnShouldQuit(onShouldQuit, mainwin); - - tab = uiNewTab(); - uiWindowSetChild(mainwin, uiControl(tab)); - uiWindowSetMargined(mainwin, 1); - - uiTabAppend(tab, "Basic Controls", makeBasicControlsPage()); - uiTabSetMargined(tab, 0, 1); - - uiTabAppend(tab, "Numbers and Lists", makeNumbersPage()); - uiTabSetMargined(tab, 1, 1); - - uiTabAppend(tab, "Data Choosers", makeDataChoosersPage()); - uiTabSetMargined(tab, 2, 1); - - uiControlShow(uiControl(mainwin)); - uiMain(); - return 0; -} - -#if 0 - -static void openClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - char *filename; - - filename = uiOpenFile(mainwin); - if (filename == NULL) { - uiMsgBoxError(mainwin, "No file selected", "Don't be alarmed!"); - return; - } - uiMsgBox(mainwin, "File selected", filename); - uiFreeText(filename); -} - -static void saveClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - char *filename; - - filename = uiSaveFile(mainwin); - if (filename == NULL) { - uiMsgBoxError(mainwin, "No file selected", "Don't be alarmed!"); - return; - } - uiMsgBox(mainwin, "File selected (don't worry, it's still there)", filename); - uiFreeText(filename); -} - -static uiSpinbox *spinbox; -static uiSlider *slider; -static uiProgressBar *progressbar; - -static void update(int value) -{ - uiSpinboxSetValue(spinbox, value); - uiSliderSetValue(slider, value); - uiProgressBarSetValue(progressbar, value); -} - -static void onSpinboxChanged(uiSpinbox *s, void *data) -{ - update(uiSpinboxValue(spinbox)); -} - -static void onSliderChanged(uiSlider *s, void *data) -{ - update(uiSliderValue(slider)); -} - -int main(void) -{ - uiInitOptions o; - const char *err; - uiMenu *menu; - uiMenuItem *item; - uiBox *box; - uiBox *hbox; - uiGroup *group; - uiBox *inner; - uiBox *inner2; - uiEntry *entry; - uiCombobox *cbox; - uiEditableCombobox *ecbox; - uiRadioButtons *rb; - uiTab *tab; - - memset(&o, 0, sizeof (uiInitOptions)); - err = uiInit(&o); - if (err != NULL) { - fprintf(stderr, "error initializing ui: %s\n", err); - uiFreeInitError(err); - return 1; - } - - menu = uiNewMenu("File"); - item = uiMenuAppendItem(menu, "Open"); - uiMenuItemOnClicked(item, openClicked, NULL); - item = uiMenuAppendItem(menu, "Save"); - uiMenuItemOnClicked(item, saveClicked, NULL); - item = uiMenuAppendQuitItem(menu); - uiOnShouldQuit(shouldQuit, NULL); - - menu = uiNewMenu("Edit"); - item = uiMenuAppendCheckItem(menu, "Checkable Item"); - uiMenuAppendSeparator(menu); - item = uiMenuAppendItem(menu, "Disabled Item"); - uiMenuItemDisable(item); - item = uiMenuAppendPreferencesItem(menu); - - menu = uiNewMenu("Help"); - item = uiMenuAppendItem(menu, "Help"); - item = uiMenuAppendAboutItem(menu); - - mainwin = uiNewWindow("libui Control Gallery", 640, 480, 1); - uiWindowSetMargined(mainwin, 1); - uiWindowOnClosing(mainwin, onClosing, NULL); - - box = uiNewVerticalBox(); - uiBoxSetPadded(box, 1); - uiWindowSetChild(mainwin, uiControl(box)); - - hbox = uiNewHorizontalBox(); - uiBoxSetPadded(hbox, 1); - uiBoxAppend(box, uiControl(hbox), 1); - - group = uiNewGroup("Basic Controls"); - uiGroupSetMargined(group, 1); - uiBoxAppend(hbox, uiControl(group), 0); - - inner = uiNewVerticalBox(); - uiBoxSetPadded(inner, 1); - uiGroupSetChild(group, uiControl(inner)); - - uiBoxAppend(inner, - uiControl(uiNewButton("Button")), - 0); - uiBoxAppend(inner, - uiControl(uiNewCheckbox("Checkbox")), - 0); - entry = uiNewEntry(); - uiEntrySetText(entry, "Entry"); - uiBoxAppend(inner, - uiControl(entry), - 0); - uiBoxAppend(inner, - uiControl(uiNewLabel("Label")), - 0); - - uiBoxAppend(inner, - uiControl(uiNewHorizontalSeparator()), - 0); - - uiBoxAppend(inner, - uiControl(uiNewDatePicker()), - 0); - uiBoxAppend(inner, - uiControl(uiNewTimePicker()), - 0); - uiBoxAppend(inner, - uiControl(uiNewDateTimePicker()), - 0); - - uiBoxAppend(inner, - uiControl(uiNewFontButton()), - 0); - - uiBoxAppend(inner, - uiControl(uiNewColorButton()), - 0); - - inner2 = uiNewVerticalBox(); - uiBoxSetPadded(inner2, 1); - uiBoxAppend(hbox, uiControl(inner2), 1); - - group = uiNewGroup("Numbers"); - uiGroupSetMargined(group, 1); - uiBoxAppend(inner2, uiControl(group), 0); - - inner = uiNewVerticalBox(); - uiBoxSetPadded(inner, 1); - uiGroupSetChild(group, uiControl(inner)); - - spinbox = uiNewSpinbox(0, 100); - uiSpinboxOnChanged(spinbox, onSpinboxChanged, NULL); - uiBoxAppend(inner, uiControl(spinbox), 0); - - slider = uiNewSlider(0, 100); - uiSliderOnChanged(slider, onSliderChanged, NULL); - uiBoxAppend(inner, uiControl(slider), 0); - - progressbar = uiNewProgressBar(); - uiBoxAppend(inner, uiControl(progressbar), 0); - - group = uiNewGroup("Lists"); - uiGroupSetMargined(group, 1); - uiBoxAppend(inner2, uiControl(group), 0); - - inner = uiNewVerticalBox(); - uiBoxSetPadded(inner, 1); - uiGroupSetChild(group, uiControl(inner)); - - cbox = uiNewCombobox(); - uiComboboxAppend(cbox, "Combobox Item 1"); - uiComboboxAppend(cbox, "Combobox Item 2"); - uiComboboxAppend(cbox, "Combobox Item 3"); - uiBoxAppend(inner, uiControl(cbox), 0); - - ecbox = uiNewEditableCombobox(); - uiEditableComboboxAppend(ecbox, "Editable Item 1"); - uiEditableComboboxAppend(ecbox, "Editable Item 2"); - uiEditableComboboxAppend(ecbox, "Editable Item 3"); - uiBoxAppend(inner, uiControl(ecbox), 0); - - rb = uiNewRadioButtons(); - uiRadioButtonsAppend(rb, "Radio Button 1"); - uiRadioButtonsAppend(rb, "Radio Button 2"); - uiRadioButtonsAppend(rb, "Radio Button 3"); - uiBoxAppend(inner, uiControl(rb), 1); - - tab = uiNewTab(); - uiTabAppend(tab, "Page 1", uiControl(uiNewHorizontalBox())); - uiTabAppend(tab, "Page 2", uiControl(uiNewHorizontalBox())); - uiTabAppend(tab, "Page 3", uiControl(uiNewHorizontalBox())); - uiBoxAppend(inner2, uiControl(tab), 1); - - uiControlShow(uiControl(mainwin)); - uiMain(); - uiUninit(); - return 0; -} - -#endif diff --git a/src/libui_sdl/libui/examples/controlgallery/unix.png b/src/libui_sdl/libui/examples/controlgallery/unix.png deleted file mode 100644 index 0c58d0909678372cbb3db2906d72683814b68626..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41757 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 LwG=Akt={|#wWPVALu?gb?OYB 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 -#include -#include -#include -#include -#include -#include -#include "../../ui.h" -using namespace std; - -uiMultilineEntry *e; -condition_variable cv; -mutex m; -unique_lock ourlock(m); -thread *timeThread; - -void sayTime(void *data) -{ - char *s = (char *) data; - - uiMultilineEntryAppend(e, s); - delete s; -} - -void threadproc(void) -{ - ourlock.lock(); - while (cv.wait_for(ourlock, chrono::seconds(1)) == cv_status::timeout) { - time_t t; - char *base; - char *s; - - t = time(NULL); - base = ctime(&t); - s = new char[strlen(base) + 1]; - strcpy(s, base); - uiQueueMain(sayTime, s); - } -} - -int onClosing(uiWindow *w, void *data) -{ - cv.notify_all(); - // C++ throws a hissy fit if you don't do this - // we might as well, to ensure no uiQueueMain() gets in after uiQuit() - timeThread->join(); - uiQuit(); - return 1; -} - -void saySomething(uiButton *b, void *data) -{ - uiMultilineEntryAppend(e, "Saying something\n"); -} - -int main(void) -{ - uiInitOptions o; - uiWindow *w; - uiBox *b; - uiButton *btn; - - memset(&o, 0, sizeof (uiInitOptions)); - if (uiInit(&o) != NULL) - abort(); - - w = uiNewWindow("Hello", 320, 240, 0); - uiWindowSetMargined(w, 1); - - b = uiNewVerticalBox(); - uiBoxSetPadded(b, 1); - uiWindowSetChild(w, uiControl(b)); - - e = uiNewMultilineEntry(); - uiMultilineEntrySetReadOnly(e, 1); - - btn = uiNewButton("Say Something"); - uiButtonOnClicked(btn, saySomething, NULL); - uiBoxAppend(b, uiControl(btn), 0); - - uiBoxAppend(b, uiControl(e), 1); - - // timeThread needs to lock ourlock itself - see http://stackoverflow.com/a/34121629/3408572 - ourlock.unlock(); - timeThread = new thread(threadproc); - - uiWindowOnClosing(w, onClosing, NULL); - uiControlShow(uiControl(w)); - uiMain(); - return 0; -} diff --git a/src/libui_sdl/libui/examples/example.manifest b/src/libui_sdl/libui/examples/example.manifest deleted file mode 100644 index 41e7c9c5..00000000 --- a/src/libui_sdl/libui/examples/example.manifest +++ /dev/null @@ -1,20 +0,0 @@ - - - -Your application description here. - - - - - - - - - - - diff --git a/src/libui_sdl/libui/examples/example.static.manifest b/src/libui_sdl/libui/examples/example.static.manifest deleted file mode 100644 index d8e83a83..00000000 --- a/src/libui_sdl/libui/examples/example.static.manifest +++ /dev/null @@ -1,32 +0,0 @@ - - - -Your application description here. - - - - - - - - - - - - - - - - diff --git a/src/libui_sdl/libui/examples/histogram/main.c b/src/libui_sdl/libui/examples/histogram/main.c deleted file mode 100644 index f2b0e793..00000000 --- a/src/libui_sdl/libui/examples/histogram/main.c +++ /dev/null @@ -1,309 +0,0 @@ -// 13 october 2015 -#include -#include -#include -#include -#include "../../ui.h" - -uiWindow *mainwin; -uiArea *histogram; -uiAreaHandler handler; -uiSpinbox *datapoints[10]; -uiColorButton *colorButton; -int currentPoint = -1; - -// some metrics -#define xoffLeft 20 /* histogram margins */ -#define yoffTop 20 -#define xoffRight 20 -#define yoffBottom 20 -#define pointRadius 5 - -// helper to quickly set a brush color -static void setSolidBrush(uiDrawBrush *brush, uint32_t color, double alpha) -{ - uint8_t component; - - brush->Type = uiDrawBrushTypeSolid; - component = (uint8_t) ((color >> 16) & 0xFF); - brush->R = ((double) component) / 255; - component = (uint8_t) ((color >> 8) & 0xFF); - brush->G = ((double) component) / 255; - component = (uint8_t) (color & 0xFF); - brush->B = ((double) component) / 255; - brush->A = alpha; -} - -// and some colors -// names and values from https://msdn.microsoft.com/en-us/library/windows/desktop/dd370907%28v=vs.85%29.aspx -#define colorWhite 0xFFFFFF -#define colorBlack 0x000000 -#define colorDodgerBlue 0x1E90FF - -static void pointLocations(double width, double height, double *xs, double *ys) -{ - double xincr, yincr; - int i, n; - - xincr = width / 9; // 10 - 1 to make the last point be at the end - yincr = height / 100; - - for (i = 0; i < 10; i++) { - // get the value of the point - n = uiSpinboxValue(datapoints[i]); - // because y=0 is the top but n=0 is the bottom, we need to flip - n = 100 - n; - xs[i] = xincr * i; - ys[i] = yincr * n; - } -} - -static uiDrawPath *constructGraph(double width, double height, int extend) -{ - uiDrawPath *path; - double xs[10], ys[10]; - int i; - - pointLocations(width, height, xs, ys); - - path = uiDrawNewPath(uiDrawFillModeWinding); - - uiDrawPathNewFigure(path, xs[0], ys[0]); - for (i = 1; i < 10; i++) - uiDrawPathLineTo(path, xs[i], ys[i]); - - if (extend) { - uiDrawPathLineTo(path, width, height); - uiDrawPathLineTo(path, 0, height); - uiDrawPathCloseFigure(path); - } - - uiDrawPathEnd(path); - return path; -} - -static void graphSize(double clientWidth, double clientHeight, double *graphWidth, double *graphHeight) -{ - *graphWidth = clientWidth - xoffLeft - xoffRight; - *graphHeight = clientHeight - yoffTop - yoffBottom; -} - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush brush; - uiDrawStrokeParams sp; - uiDrawMatrix m; - double graphWidth, graphHeight; - double graphR, graphG, graphB, graphA; - - // fill the area with white - setSolidBrush(&brush, colorWhite, 1.0); - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 0, 0, p->AreaWidth, p->AreaHeight); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); - - // figure out dimensions - graphSize(p->AreaWidth, p->AreaHeight, &graphWidth, &graphHeight); - - // clear sp to avoid passing garbage to uiDrawStroke() - // for example, we don't use dashing - memset(&sp, 0, sizeof (uiDrawStrokeParams)); - - // make a stroke for both the axes and the histogram line - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 2; - sp.MiterLimit = uiDrawDefaultMiterLimit; - - // draw the axes - setSolidBrush(&brush, colorBlack, 1.0); - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, - xoffLeft, yoffTop); - uiDrawPathLineTo(path, - xoffLeft, yoffTop + graphHeight); - uiDrawPathLineTo(path, - xoffLeft + graphWidth, yoffTop + graphHeight); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); - - // now transform the coordinate space so (0, 0) is the top-left corner of the graph - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, xoffLeft, yoffTop); - uiDrawTransform(p->Context, &m); - - // now get the color for the graph itself and set up the brush - uiColorButtonColor(colorButton, &graphR, &graphG, &graphB, &graphA); - brush.Type = uiDrawBrushTypeSolid; - brush.R = graphR; - brush.G = graphG; - brush.B = graphB; - // we set brush->A below to different values for the fill and stroke - - // now create the fill for the graph below the graph line - path = constructGraph(graphWidth, graphHeight, 1); - brush.A = graphA / 2; - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); - - // now draw the histogram line - path = constructGraph(graphWidth, graphHeight, 0); - brush.A = graphA; - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); - - // now draw the point being hovered over - if (currentPoint != -1) { - double xs[10], ys[10]; - - pointLocations(graphWidth, graphHeight, xs, ys); - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xs[currentPoint], ys[currentPoint], - pointRadius, - 0, 6.23, // TODO pi - 0); - uiDrawPathEnd(path); - // use the same brush as for the histogram lines - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); - } -} - -static int inPoint(double x, double y, double xtest, double ytest) -{ - // TODO switch to using a matrix - x -= xoffLeft; - y -= yoffTop; - return (x >= xtest - pointRadius) && - (x <= xtest + pointRadius) && - (y >= ytest - pointRadius) && - (y <= ytest + pointRadius); -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - double graphWidth, graphHeight; - double xs[10], ys[10]; - int i; - - graphSize(e->AreaWidth, e->AreaHeight, &graphWidth, &graphHeight); - pointLocations(graphWidth, graphHeight, xs, ys); - - for (i = 0; i < 10; i++) - if (inPoint(e->X, e->Y, xs[i], ys[i])) - break; - if (i == 10) // not in a point - i = -1; - - currentPoint = i; - // TODO only redraw the relevant area - uiAreaQueueRedrawAll(histogram); -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ - // do nothing -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - // do nothing -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - // reject all keys - return 0; -} - -static void onDatapointChanged(uiSpinbox *s, void *data) -{ - uiAreaQueueRedrawAll(histogram); -} - -static void onColorChanged(uiColorButton *b, void *data) -{ - uiAreaQueueRedrawAll(histogram); -} - -static int onClosing(uiWindow *w, void *data) -{ - uiControlDestroy(uiControl(mainwin)); - uiQuit(); - return 0; -} - -static int shouldQuit(void *data) -{ - uiControlDestroy(uiControl(mainwin)); - return 1; -} - -int main(void) -{ - uiInitOptions o; - const char *err; - uiBox *hbox, *vbox; - int i; - uiDrawBrush brush; - - handler.Draw = handlerDraw; - handler.MouseEvent = handlerMouseEvent; - handler.MouseCrossed = handlerMouseCrossed; - handler.DragBroken = handlerDragBroken; - handler.KeyEvent = handlerKeyEvent; - - memset(&o, 0, sizeof (uiInitOptions)); - err = uiInit(&o); - if (err != NULL) { - fprintf(stderr, "error initializing ui: %s\n", err); - uiFreeInitError(err); - return 1; - } - - uiOnShouldQuit(shouldQuit, NULL); - - mainwin = uiNewWindow("libui Histogram Example", 640, 480, 1); - uiWindowSetMargined(mainwin, 1); - uiWindowOnClosing(mainwin, onClosing, NULL); - - hbox = uiNewHorizontalBox(); - uiBoxSetPadded(hbox, 1); - uiWindowSetChild(mainwin, uiControl(hbox)); - - vbox = uiNewVerticalBox(); - uiBoxSetPadded(vbox, 1); - uiBoxAppend(hbox, uiControl(vbox), 0); - - srand(time(NULL)); - for (i = 0; i < 10; i++) { - datapoints[i] = uiNewSpinbox(0, 100); - uiSpinboxSetValue(datapoints[i], rand() % 101); - uiSpinboxOnChanged(datapoints[i], onDatapointChanged, NULL); - uiBoxAppend(vbox, uiControl(datapoints[i]), 0); - } - - colorButton = uiNewColorButton(); - // TODO inline these - setSolidBrush(&brush, colorDodgerBlue, 1.0); - uiColorButtonSetColor(colorButton, - brush.R, - brush.G, - brush.B, - brush.A); - uiColorButtonOnChanged(colorButton, onColorChanged, NULL); - uiBoxAppend(vbox, uiControl(colorButton), 0); - - histogram = uiNewArea(&handler); - uiBoxAppend(hbox, uiControl(histogram), 1); - - uiControlShow(uiControl(mainwin)); - uiMain(); - uiUninit(); - return 0; -} diff --git a/src/libui_sdl/libui/examples/resources.rc b/src/libui_sdl/libui/examples/resources.rc deleted file mode 100644 index 49f486c1..00000000 --- a/src/libui_sdl/libui/examples/resources.rc +++ /dev/null @@ -1,13 +0,0 @@ -// 30 may 2015 - -// this is a UTF-8 file -#pragma code_page(65001) - -// this is the Common Controls 6 manifest -// TODO set up the string values here -// 1 is the value of CREATEPROCESS_MANIFEST_RESOURCE_ID and 24 is the value of RT_MANIFEST; we use it directly to avoid needing to share winapi.h with the tests and examples -#ifndef _UI_STATIC -1 24 "example.manifest" -#else -1 24 "example.static.manifest" -#endif diff --git a/src/libui_sdl/libui/nowintable.diff b/src/libui_sdl/libui/nowintable.diff deleted file mode 100644 index cfbab07d..00000000 --- a/src/libui_sdl/libui/nowintable.diff +++ /dev/null @@ -1,50 +0,0 @@ -diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt -index 7f70403..e909569 100644 ---- a/common/CMakeLists.txt -+++ b/common/CMakeLists.txt -@@ -6,7 +6,7 @@ list(APPEND _LIBUI_SOURCES - common/debug.c - common/matrix.c - common/shouldquit.c -- common/table.c -+# common/table.c - common/userbugs.c - ) - set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) -diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt -index b753a7d..a648c64 100644 ---- a/test/CMakeLists.txt -+++ b/test/CMakeLists.txt -@@ -6,7 +6,7 @@ endif() - - _add_exec(tester - drawtests.c -- images.c -+# images.c - main.c - menus.c - page1.c -@@ -27,7 +27,7 @@ _add_exec(tester - page13.c - page14.c - page15.c -- page16.c -+# page16.c - spaced.c - ${_TEST_RESOURCES_RC} - ) -diff --git a/test/main.c b/test/main.c -index f33f30a..18774dc 100644 ---- a/test/main.c -+++ b/test/main.c -@@ -159,8 +159,8 @@ int main(int argc, char *argv[]) - innerTab = newTab(); - uiTabAppend(outerTab, "Pages 16-?", uiControl(innerTab)); - -- page16 = makePage16(); -- uiTabAppend(innerTab, "Page 16", uiControl(page16)); -+// page16 = makePage16(); -+// uiTabAppend(innerTab, "Page 16", uiControl(page16)); - - if (startspaced) - setSpaced(1); diff --git a/src/libui_sdl/libui/oldhaiku.tgz b/src/libui_sdl/libui/oldhaiku.tgz deleted file mode 100644 index a3b9dd7cec7787ae6e5ef7cbd2c8acb10b5b6693..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13965 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 + 5, p->ClipY + 5); - uiDrawPathLineTo(path, (p->ClipX + p->ClipWidth) - 5, (p->ClipY + p->ClipHeight) - 5); - uiDrawPathEnd(path); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 1; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); - - brush.R = 0; - brush.G = 0; - brush.B = 0.75; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, p->ClipX, p->ClipY); - uiDrawPathLineTo(path, p->ClipX + p->ClipWidth, p->ClipY); - uiDrawPathLineTo(path, 50, 150); - uiDrawPathLineTo(path, 50, 50); - uiDrawPathCloseFigure(path); - uiDrawPathEnd(path); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinRound; - sp.Thickness = 5; - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); - - brush.R = 0; - brush.G = 0.75; - brush.B = 0; - brush.A = 0.5; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 120, 80, 50, 50); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); - brush.A = 1; - - brush.R = 0; - brush.G = 0.5; - brush.B = 0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 5.5, 10.5); - uiDrawPathLineTo(path, 5.5, 50.5); - uiDrawPathEnd(path); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 1; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); - - brush.R = 0.5; - brush.G = 0.75; - brush.B = 0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 400, 100); - uiDrawPathArcTo(path, - 400, 100, - 50, - 30. * (uiPi / 180.), - 300. * (uiPi / 180.), - 0); - // the sweep test below doubles as a clockwise test so a checkbox isn't needed anymore - uiDrawPathLineTo(path, 400, 100); - uiDrawPathNewFigureWithArc(path, - 510, 100, - 50, - 30. * (uiPi / 180.), - 300. * (uiPi / 180.), - 0); - uiDrawPathCloseFigure(path); - // and now with 330 to make sure sweeps work properly - uiDrawPathNewFigure(path, 400, 210); - uiDrawPathArcTo(path, - 400, 210, - 50, - 30. * (uiPi / 180.), - 330. * (uiPi / 180.), - 0); - uiDrawPathLineTo(path, 400, 210); - uiDrawPathNewFigureWithArc(path, - 510, 210, - 50, - 30. * (uiPi / 180.), - 330. * (uiPi / 180.), - 0); - uiDrawPathCloseFigure(path); - uiDrawPathEnd(path); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 1; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); - - brush.R = 0; - brush.G = 0.5; - brush.B = 0.75; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 300, 300); - uiDrawPathBezierTo(path, - 350, 320, - 310, 390, - 435, 372); - uiDrawPathEnd(path); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 1; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &brush, &sp); - uiDrawFreePath(path); -} - -static void drawArcs(uiAreaDrawParams *p) -{ - uiDrawPath *path; - int start = 20; - int step = 20; - int rad = 25; - int x, y; - double angle; - double add; - int i; - uiDrawBrush brush; - uiDrawStrokeParams sp; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - add = (2.0 * uiPi) / 12; - - x = start + rad; - y = start + rad; - angle = 0; - for (i = 0; i < 13; i++) { - uiDrawPathNewFigureWithArc(path, - x, y, - rad, - 0, angle, - 0); - angle += add; - x += 2 * rad + step; - } - - y += 2 * rad + step; - x = start + rad; - angle = 0; - for (i = 0; i < 13; i++) { - uiDrawPathNewFigure(path, x, y); - uiDrawPathArcTo(path, - x, y, - rad, - 0, angle, - 0); - angle += add; - x += 2 * rad + step; - } - - y += 2 * rad + step; - x = start + rad; - angle = 0; - for (i = 0; i < 13; i++) { - uiDrawPathNewFigureWithArc(path, - x, y, - rad, - (uiPi / 4), angle, - 0); - angle += add; - x += 2 * rad + step; - } - - y += 2 * rad + step; - x = start + rad; - angle = 0; - for (i = 0; i < 13; i++) { - uiDrawPathNewFigure(path, x, y); - uiDrawPathArcTo(path, - x, y, - rad, - (uiPi / 4), angle, - 0); - angle += add; - x += 2 * rad + step; - } - - y += 2 * rad + step; - x = start + rad; - angle = 0; - for (i = 0; i < 13; i++) { - uiDrawPathNewFigureWithArc(path, - x, y, - rad, - uiPi + (uiPi / 5), angle, - 0); - angle += add; - x += 2 * rad + step; - } - - y += 2 * rad + step; - x = start + rad; - angle = 0; - for (i = 0; i < 13; i++) { - uiDrawPathNewFigure(path, x, y); - uiDrawPathArcTo(path, - x, y, - rad, - uiPi + (uiPi / 5), angle, - 0); - angle += add; - x += 2 * rad + step; - } - - uiDrawPathEnd(path); - - brush.Type = uiDrawBrushTypeSolid; - brush.R = 0; - brush.G = 0; - brush.B = 0; - brush.A = 1; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 1; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &brush, &sp); - - uiDrawFreePath(path); -} - -// Direct2D Documentation Code - -static void d2dColorToRGB(uint32_t color, double *r, double *g, double *b) -{ - uint8_t rr, gg, bb; - - rr = (color & 0xFF0000) >> 16; - gg = (color & 0x00FF00) >> 8; - bb = color & 0x0000FF; - *r = ((double) rr) / 255.0; - *g = ((double) gg) / 255.0; - *b = ((double) bb) / 255.0; -} -#define d2dBlack 0x000000 -#define d2dLightSlateGray 0x778899 -#define d2dCornflowerBlue 0x6495ED -#define d2dWhite 0xFFFFFF -#define d2dYellowGreen 0x9ACD32 -#define d2dYellow 0xFFFF00 -#define d2dForestGreen 0x228B22 -#define d2dOliveDrab 0x6B8E23 -#define d2dLightSkyBlue 0x87CEFA - -static void d2dSolidBrush(uiDrawBrush *brush, uint32_t color, double alpha) -{ - brush->Type = uiDrawBrushTypeSolid; - d2dColorToRGB(color, &(brush->R), &(brush->G), &(brush->B)); - brush->A = alpha; -} - -static void d2dClear(uiAreaDrawParams *p, uint32_t color, double alpha) -{ - uiDrawPath *path; - uiDrawBrush brush; - - d2dSolidBrush(&brush, color, alpha); - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 0, 0, p->AreaWidth, p->AreaHeight); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/hh780340%28v=vs.85%29.aspx -// also at https://msdn.microsoft.com/en-us/library/windows/desktop/dd535473%28v=vs.85%29.aspx -static void drawD2DW8QS(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush brush; - - d2dSolidBrush(&brush, d2dBlack, 1.0); - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, - 100, - 100, - (p->AreaWidth - 100) - 100, - (p->AreaHeight - 100) - 100); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx -static void drawD2DSimpleApp(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush lightSlateGray; - uiDrawBrush cornflowerBlue; - uiDrawStrokeParams sp; - int x, y; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - d2dSolidBrush(&lightSlateGray, d2dLightSlateGray, 1.0); - d2dSolidBrush(&cornflowerBlue, d2dCornflowerBlue, 1.0); - - d2dClear(p, d2dWhite, 1.0); - - sp.Thickness = 0.5; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - - for (x = 0; x < p->AreaWidth; x += 10) { - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, x, 0); - uiDrawPathLineTo(path, x, p->AreaHeight); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &lightSlateGray, &sp); - uiDrawFreePath(path); - } - - for (y = 0; y < p->AreaHeight; y += 10) { - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 0, y); - uiDrawPathLineTo(path, p->AreaWidth, y); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &lightSlateGray, &sp); - uiDrawFreePath(path); - } - - double left, top, right, bottom; - - left = p->AreaWidth / 2.0 - 50.0; - right = p->AreaWidth / 2.0 + 50.0; - top = p->AreaHeight / 2.0 - 50.0; - bottom = p->AreaHeight / 2.0 + 50.0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, left, top, right - left, bottom - top); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &lightSlateGray); - uiDrawFreePath(path); - - left = p->AreaWidth / 2.0 - 100.0; - right = p->AreaWidth / 2.0 + 100.0; - top = p->AreaHeight / 2.0 - 100.0; - bottom = p->AreaHeight / 2.0 + 100.0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, left, top, right - left, bottom - top); - uiDrawPathEnd(path); - sp.Thickness = 1.0; - uiDrawStroke(p->Context, path, &cornflowerBlue, &sp); - uiDrawFreePath(path); -} - -// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd372260(v=vs.85).aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756654%28v=vs.85%29.aspx - -// TODO? all subsections too? https://msdn.microsoft.com/en-us/library/windows/desktop/hh973240%28v=vs.85%29.aspx - -// TODO differing examples of? https://msdn.microsoft.com/en-us/library/windows/desktop/dd756651%28v=vs.85%29.aspx - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756680%28v=vs.85%29.aspx -static void drawD2DSolidBrush(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush black; - uiDrawBrush yellowGreen; - uiDrawStrokeParams sp; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - d2dSolidBrush(&black, d2dBlack, 1.0); - d2dSolidBrush(&yellowGreen, d2dYellowGreen, 1.0); - - path = uiDrawNewPath(uiDrawFillModeWinding); - // the example doesn't define a rectangle - // 150x150 seems to be right given the other examples though - uiDrawPathAddRectangle(path, 25, 25, 150, 150); - uiDrawPathEnd(path); - - uiDrawFill(p->Context, path, &yellowGreen); - sp.Thickness = 1.0; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &black, &sp); - - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756678%28v=vs.85%29.aspx -static void drawD2DLinearBrush(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush black; - uiDrawBrush gradient; - uiDrawBrushGradientStop stops[2]; - uiDrawStrokeParams sp; - - uiDrawMatrix m; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - // leave some room - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 25, 25); - uiDrawTransform(p->Context, &m); - - gradient.Type = uiDrawBrushTypeLinearGradient; - gradient.X0 = 0; - gradient.Y0 = 0; - gradient.X1 = 150; - gradient.Y1 = 150; - stops[0].Pos = 0.0; - d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B)); - stops[0].A = 1.0; - stops[1].Pos = 1.0; - d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B)); - stops[1].A = 1.0; - gradient.Stops = stops; - gradient.NumStops = 2; - - d2dSolidBrush(&black, d2dBlack, 1.0); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 0, 0, 150, 150); - uiDrawPathEnd(path); - - uiDrawFill(p->Context, path, &gradient); - sp.Thickness = 1.0; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &black, &sp); - - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756679%28v=vs.85%29.aspx -// TODO expand this to change the origin point with a mouse click (not in the original but useful to have) -static void drawD2DRadialBrush(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush black; - uiDrawBrush gradient; - uiDrawBrushGradientStop stops[2]; - uiDrawStrokeParams sp; - - uiDrawMatrix m; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - // leave some room - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 25, 25); - uiDrawTransform(p->Context, &m); - - gradient.Type = uiDrawBrushTypeRadialGradient; - gradient.X0 = 75; - gradient.Y0 = 75; - gradient.X1 = 75; - gradient.Y1 = 75; - gradient.OuterRadius = 75; - stops[0].Pos = 0.0; - d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B)); - stops[0].A = 1.0; - stops[1].Pos = 1.0; - d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B)); - stops[1].A = 1.0; - gradient.Stops = stops; - gradient.NumStops = 2; - - d2dSolidBrush(&black, d2dBlack, 1.0); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 150, 75); - uiDrawPathArcTo(path, - 75, 75, - 75, - 0, - 2 * uiPi, - 0); - uiDrawPathEnd(path); - - uiDrawFill(p->Context, path, &gradient); - sp.Thickness = 1.0; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, path, &black, &sp); - - uiDrawFreePath(path); -} - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756677%28v=vs.85%29.aspx - -// TODO? other pages have some of these https://msdn.microsoft.com/en-us/library/windows/desktop/dd756653%28v=vs.85%29.aspx - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/ee264309%28v=vs.85%29.aspx -static void drawD2DPathGeometries(uiAreaDrawParams *p) -{ - uiDrawPath *leftMountain; - uiDrawPath *rightMountain; - uiDrawPath *sun; - uiDrawPath *sunRays; - uiDrawPath *river; - uiDrawBrush radial; - uiDrawBrush scene; - uiDrawStrokeParams sp; - uiDrawBrushGradientStop stops[2]; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - // TODO this is definitely wrong but the example doesn't have the right brush in it - radial.Type = uiDrawBrushTypeRadialGradient; - radial.X0 = 75; - radial.Y0 = 75; - radial.X1 = 75; - radial.Y1 = 75; - radial.OuterRadius = 75; - stops[0].Pos = 0.0; - d2dColorToRGB(d2dYellow, &(stops[0].R), &(stops[0].G), &(stops[0].B)); - stops[0].A = 1.0; - stops[1].Pos = 1.0; - d2dColorToRGB(d2dForestGreen, &(stops[1].R), &(stops[1].G), &(stops[1].B)); - stops[1].A = 1.0; - radial.Stops = stops; - radial.NumStops = 2; - - leftMountain = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(leftMountain, 346, 255); - uiDrawPathLineTo(leftMountain, 267, 177); - uiDrawPathLineTo(leftMountain, 236, 192); - uiDrawPathLineTo(leftMountain, 212, 160); - uiDrawPathLineTo(leftMountain, 156, 255); - uiDrawPathLineTo(leftMountain, 346, 255); - uiDrawPathCloseFigure(leftMountain); - uiDrawPathEnd(leftMountain); - - rightMountain = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(rightMountain, 575, 263); - uiDrawPathLineTo(rightMountain, 481, 146); - uiDrawPathLineTo(rightMountain, 449, 181); - uiDrawPathLineTo(rightMountain, 433, 159); - uiDrawPathLineTo(rightMountain, 401, 214); - uiDrawPathLineTo(rightMountain, 381, 199); - uiDrawPathLineTo(rightMountain, 323, 263); - uiDrawPathLineTo(rightMountain, 575, 263); - uiDrawPathCloseFigure(rightMountain); - uiDrawPathEnd(rightMountain); - - sun = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(sun, - (440.0 - 270.0) / 2 + 270.0, 255, - 85, - uiPi, uiPi, - 0); - uiDrawPathCloseFigure(sun); - uiDrawPathEnd(sun); - - // the original examples had these as hollow figures - // we don't support them, so we'll have to stroke it separately - sunRays = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(sunRays, 299, 182); - uiDrawPathBezierTo(sunRays, - 299, 182, - 294, 176, - 285, 178); - uiDrawPathBezierTo(sunRays, - 276, 179, - 272, 173, - 272, 173); - uiDrawPathNewFigure(sunRays, 354, 156); - uiDrawPathBezierTo(sunRays, - 354, 156, - 358, 149, - 354, 142); - uiDrawPathBezierTo(sunRays, - 349, 134, - 354, 127, - 354, 127); - uiDrawPathNewFigure(sunRays, 322, 164); - uiDrawPathBezierTo(sunRays, - 322, 164, - 322, 156, - 314, 152); - uiDrawPathBezierTo(sunRays, - 306, 149, - 305, 141, - 305, 141); - uiDrawPathNewFigure(sunRays, 385, 164); - uiDrawPathBezierTo(sunRays, - 385, 164, - 392, 161, - 394, 152); - uiDrawPathBezierTo(sunRays, - 395, 144, - 402, 141, - 402, 142); - uiDrawPathNewFigure(sunRays, 408, 182); - uiDrawPathBezierTo(sunRays, - 408, 182, - 416, 184, - 422, 178); - uiDrawPathBezierTo(sunRays, - 428, 171, - 435, 173, - 435, 173); - uiDrawPathEnd(sunRays); - - river = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(river, 183, 392); - uiDrawPathBezierTo(river, - 238, 284, - 472, 345, - 356, 303); - uiDrawPathBezierTo(river, - 237, 261, - 333, 256, - 333, 256); - uiDrawPathBezierTo(river, - 335, 257, - 241, 261, - 411, 306); - uiDrawPathBezierTo(river, - 574, 350, - 288, 324, - 296, 392); - uiDrawPathEnd(river); - - d2dClear(p, d2dWhite, 1.0); - - // TODO draw the grid - - uiDrawFill(p->Context, sun, &radial); - - d2dSolidBrush(&scene, d2dBlack, 1.0); - sp.Thickness = 1.0; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(p->Context, sun, &scene, &sp); - uiDrawStroke(p->Context, sunRays, &scene, &sp); - - d2dSolidBrush(&scene, d2dOliveDrab, 1.0); - uiDrawFill(p->Context, leftMountain, &scene); - - d2dSolidBrush(&scene, d2dBlack, 1.0); - uiDrawStroke(p->Context, leftMountain, &scene, &sp); - - d2dSolidBrush(&scene, d2dLightSkyBlue, 1.0); - uiDrawFill(p->Context, river, &scene); - - d2dSolidBrush(&scene, d2dBlack, 1.0); - uiDrawStroke(p->Context, river, &scene, &sp); - - d2dSolidBrush(&scene, d2dYellowGreen, 1.0); - uiDrawFill(p->Context, rightMountain, &scene); - - d2dSolidBrush(&scene, d2dBlack, 1.0); - uiDrawStroke(p->Context, rightMountain, &scene, &sp); - - uiDrawFreePath(leftMountain); - uiDrawFreePath(rightMountain); - uiDrawFreePath(sun); - uiDrawFreePath(sunRays); - uiDrawFreePath(river); -} - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756690%28v=vs.85%29.aspx - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756681%28v=vs.85%29.aspx -static void drawD2DGeometryGroup(uiAreaDrawParams *p) -{ - uiDrawPath *alternate; - uiDrawPath *winding; - uiDrawBrush fill; - uiDrawBrush stroke; - uiDrawStrokeParams sp; - uiDrawMatrix m; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - alternate = uiDrawNewPath(uiDrawFillModeAlternate); - uiDrawPathNewFigureWithArc(alternate, - 105, 105, - 25, - 0, 2 * uiPi, - 0); - uiDrawPathNewFigureWithArc(alternate, - 105, 105, - 50, - 0, 2 * uiPi, - 0); - uiDrawPathNewFigureWithArc(alternate, - 105, 105, - 75, - 0, 2 * uiPi, - 0); - uiDrawPathNewFigureWithArc(alternate, - 105, 105, - 100, - 0, 2 * uiPi, - 0); - uiDrawPathEnd(alternate); - - winding = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(winding, - 105, 105, - 25, - 0, 2 * uiPi, - 0); - uiDrawPathNewFigureWithArc(winding, - 105, 105, - 50, - 0, 2 * uiPi, - 0); - uiDrawPathNewFigureWithArc(winding, - 105, 105, - 75, - 0, 2 * uiPi, - 0); - uiDrawPathNewFigureWithArc(winding, - 105, 105, - 100, - 0, 2 * uiPi, - 0); - uiDrawPathEnd(winding); - - d2dClear(p, d2dWhite, 1.0); - - // TODO grid - - // TODO the example doesn't provide these - d2dSolidBrush(&fill, d2dForestGreen, 1.0); - d2dSolidBrush(&stroke, d2dCornflowerBlue, 1.0); - - sp.Thickness = 1.0; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - - uiDrawFill(p->Context, alternate, &fill); - uiDrawStroke(p->Context, alternate, &stroke, &sp); - // TODO text - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 300, 0); - uiDrawTransform(p->Context, &m); - uiDrawFill(p->Context, winding, &fill); - uiDrawStroke(p->Context, winding, &stroke, &sp); -// // TODO text - - uiDrawFreePath(winding); - uiDrawFreePath(alternate); -} - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756676%28v=vs.85%29.aspx - -// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd370971%28v=vs.85%29.aspx - -// TODO are there even examples here? https://msdn.microsoft.com/en-us/library/windows/desktop/dd370966%28v=vs.85%29.aspx - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756687%28v=vs.85%29.aspx -static void drawD2DRotate(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush original; - uiDrawBrush fill; - uiDrawBrush transform; - uiDrawStrokeParams originalsp; - uiDrawStrokeParams transformsp; - uiDrawMatrix m; - - originalsp.Dashes = NULL; - originalsp.NumDashes = 0; - originalsp.DashPhase = 0; - transformsp.Dashes = NULL; - transformsp.NumDashes = 0; - transformsp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 438.0, 301.5, 498.0 - 438.0, 361.5 - 301.5); - uiDrawPathEnd(path); - - // TODO the example doesn't specify what these should be - d2dSolidBrush(&original, d2dBlack, 1.0); - d2dSolidBrush(&fill, d2dWhite, 0.5); - d2dSolidBrush(&transform, d2dForestGreen, 1.0); - // TODO this needs to be dashed - originalsp.Thickness = 1.0; - originalsp.Cap = uiDrawLineCapFlat; - originalsp.Join = uiDrawLineJoinMiter; - originalsp.MiterLimit = uiDrawDefaultMiterLimit; - transformsp.Thickness = 1.0; - transformsp.Cap = uiDrawLineCapFlat; - transformsp.Join = uiDrawLineJoinMiter; - transformsp.MiterLimit = uiDrawDefaultMiterLimit; - - // save for when we do the translated one - uiDrawSave(p->Context); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixRotate(&m, - 468.0, 331.5, - 45.0 * (uiPi / 180)); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawRestore(p->Context); - - // translate to test the corner axis - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, -200, -200); - uiDrawTransform(p->Context, &m); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixRotate(&m, - 438.0, 301.5, - 45.0 * (uiPi / 180)); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756688%28v=vs.85%29.aspx -static void drawD2DScale(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush original; - uiDrawBrush fill; - uiDrawBrush transform; - uiDrawStrokeParams originalsp; - uiDrawStrokeParams transformsp; - uiDrawMatrix m; - - originalsp.Dashes = NULL; - originalsp.NumDashes = 0; - originalsp.DashPhase = 0; - transformsp.Dashes = NULL; - transformsp.NumDashes = 0; - transformsp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 438.0, 80.5, 498.0 - 438.0, 140.5 - 80.5); - uiDrawPathEnd(path); - - // TODO the example doesn't specify what these should be - d2dSolidBrush(&original, d2dBlack, 1.0); - d2dSolidBrush(&fill, d2dWhite, 0.5); - d2dSolidBrush(&transform, d2dForestGreen, 1.0); - // TODO this needs to be dashed - originalsp.Thickness = 1.0; - originalsp.Cap = uiDrawLineCapFlat; - originalsp.Join = uiDrawLineJoinMiter; - originalsp.MiterLimit = uiDrawDefaultMiterLimit; - transformsp.Thickness = 1.0; - transformsp.Cap = uiDrawLineCapFlat; - transformsp.Join = uiDrawLineJoinMiter; - transformsp.MiterLimit = uiDrawDefaultMiterLimit; - - // save for when we do the translated one - uiDrawSave(p->Context); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixScale(&m, - 438.0, 80.5, - 1.3, 1.3); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawRestore(p->Context); - - // for testing purposes, show what happens if we scale about (0, 0) - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, -300, 50); - uiDrawTransform(p->Context, &m); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixScale(&m, - 0, 0, - 1.3, 1.3); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756689%28v=vs.85%29.aspx -// TODO counterclockwise?! -void drawD2DSkew(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush original; - uiDrawBrush fill; - uiDrawBrush transform; - uiDrawStrokeParams originalsp; - uiDrawStrokeParams transformsp; - uiDrawMatrix m; - - originalsp.Dashes = NULL; - originalsp.NumDashes = 0; - originalsp.DashPhase = 0; - transformsp.Dashes = NULL; - transformsp.NumDashes = 0; - transformsp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 126.0, 301.5, 186.0 - 126.0, 361.5 - 301.5); - uiDrawPathEnd(path); - - // TODO the example doesn't specify what these should be - d2dSolidBrush(&original, d2dBlack, 1.0); - d2dSolidBrush(&fill, d2dWhite, 0.5); - d2dSolidBrush(&transform, d2dForestGreen, 1.0); - // TODO this needs to be dashed - originalsp.Thickness = 1.0; - originalsp.Cap = uiDrawLineCapFlat; - originalsp.Join = uiDrawLineJoinMiter; - originalsp.MiterLimit = uiDrawDefaultMiterLimit; - transformsp.Thickness = 1.0; - transformsp.Cap = uiDrawLineCapFlat; - transformsp.Join = uiDrawLineJoinMiter; - transformsp.MiterLimit = uiDrawDefaultMiterLimit; - - // save for when we do the translated one - uiDrawSave(p->Context); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixSkew(&m, - 126.0, 301.5, - 45.0 * (uiPi / 180), 0); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawRestore(p->Context); - - // for testing purposes, show what happens if we skew about (0, 0) - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 0, -200); - uiDrawTransform(p->Context, &m); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixSkew(&m, - 0, 0, - 45.0 * (uiPi / 180), 0); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756691%28v=vs.85%29.aspx -static void drawD2DTranslate(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush original; - uiDrawBrush fill; - uiDrawBrush transform; - uiDrawStrokeParams originalsp; - uiDrawStrokeParams transformsp; - uiDrawMatrix m; - - originalsp.Dashes = NULL; - originalsp.NumDashes = 0; - originalsp.DashPhase = 0; - transformsp.Dashes = NULL; - transformsp.NumDashes = 0; - transformsp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 126.0, 80.5, 186.0 - 126.0, 140.5 - 80.5); - uiDrawPathEnd(path); - - // TODO the example doesn't specify what these should be - d2dSolidBrush(&original, d2dBlack, 1.0); - d2dSolidBrush(&fill, d2dWhite, 0.5); - d2dSolidBrush(&transform, d2dForestGreen, 1.0); - // TODO this needs to be dashed - originalsp.Thickness = 1.0; - originalsp.Cap = uiDrawLineCapFlat; - originalsp.Join = uiDrawLineJoinMiter; - originalsp.MiterLimit = uiDrawDefaultMiterLimit; - transformsp.Thickness = 1.0; - transformsp.Cap = uiDrawLineCapFlat; - transformsp.Join = uiDrawLineJoinMiter; - transformsp.MiterLimit = uiDrawDefaultMiterLimit; - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 20, 10); - uiDrawTransform(p->Context, &m); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawFreePath(path); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756672%28v=vs.85%29.aspx -// TODO the points seem off -static void drawD2DMultiTransforms(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush original; - uiDrawBrush fill; - uiDrawBrush transform; - uiDrawStrokeParams originalsp; - uiDrawStrokeParams transformsp; - uiDrawMatrix mtranslate; - uiDrawMatrix mrotate; - - originalsp.Dashes = NULL; - originalsp.NumDashes = 0; - originalsp.DashPhase = 0; - transformsp.Dashes = NULL; - transformsp.NumDashes = 0; - transformsp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 300.0, 40.0, 360.0 - 300.0, 100.0 - 40.0); - uiDrawPathEnd(path); - - // TODO the example doesn't specify what these should be - d2dSolidBrush(&original, d2dBlack, 1.0); - d2dSolidBrush(&fill, d2dWhite, 0.5); - d2dSolidBrush(&transform, d2dForestGreen, 1.0); - // TODO this needs to be dashed - originalsp.Thickness = 1.0; - originalsp.Cap = uiDrawLineCapFlat; - originalsp.Join = uiDrawLineJoinMiter; - originalsp.MiterLimit = uiDrawDefaultMiterLimit; - transformsp.Thickness = 1.0; - transformsp.Cap = uiDrawLineCapFlat; - transformsp.Join = uiDrawLineJoinMiter; - transformsp.MiterLimit = uiDrawDefaultMiterLimit; - - uiDrawMatrixSetIdentity(&mtranslate); - uiDrawMatrixTranslate(&mtranslate, 20.0, 10.0); - uiDrawMatrixSetIdentity(&mrotate); - uiDrawMatrixRotate(&mrotate, - 330.0, 70.0, - 45.0 * (uiPi / 180)); - - // save for when we do the opposite one - uiDrawSave(p->Context); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawTransform(p->Context, &mrotate); - uiDrawTransform(p->Context, &mtranslate); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawRestore(p->Context); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 40.0, 40.0, 100.0 - 40.0, 100.0 - 40.0); - uiDrawPathEnd(path); - - uiDrawMatrixSetIdentity(&mtranslate); - uiDrawMatrixTranslate(&mtranslate, 20.0, 10.0); - uiDrawMatrixSetIdentity(&mrotate); - uiDrawMatrixRotate(&mrotate, - 70.0, 70.0, - 45.0 * (uiPi / 180)); - - uiDrawStroke(p->Context, path, &original, &originalsp); - - uiDrawTransform(p->Context, &mtranslate); - uiDrawTransform(p->Context, &mrotate); - - uiDrawFill(p->Context, path, &fill); - uiDrawStroke(p->Context, path, &transform, &transformsp); - - uiDrawFreePath(path); -} - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756675%28v=vs.85%29.aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756673%28v=vs.85%29.aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756684%28v=vs.85%29.aspx - -// TODO dashing https://msdn.microsoft.com/en-us/library/windows/desktop/dd756683%28v=vs.85%29.aspx - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx -static void drawD2DComplexShape(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush black; - uiDrawBrush gradient; - uiDrawBrushGradientStop stops[2]; - uiDrawStrokeParams sp; - uiDrawMatrix m; - - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 0, 0); - uiDrawPathLineTo(path, 200, 0); - uiDrawPathBezierTo(path, - 150, 50, - 150, 150, - 200, 200); - uiDrawPathLineTo(path, 0, 200); - uiDrawPathBezierTo(path, - 50, 150, - 50, 50, - 0, 0); - uiDrawPathCloseFigure(path); - uiDrawPathEnd(path); - - d2dSolidBrush(&black, d2dBlack, 1.0); - - stops[0].Pos =0.0; - stops[0].R = 0.0; - stops[0].G = 1.0; - stops[0].B = 1.0; - stops[0].A = 0.25; - stops[1].Pos = 1.0; - stops[1].R = 0.0; - stops[1].G = 0.0; - stops[1].B = 1.0; - stops[1].A = 1.0; - gradient.Type = uiDrawBrushTypeLinearGradient; - gradient.X0 = 100; - gradient.Y0 = 0; - gradient.X1 = 100; - gradient.Y1 = 200; - gradient.Stops = stops; - gradient.NumStops = 2; - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 20, 20); - uiDrawTransform(p->Context, &m); - - sp.Thickness = 10.0; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - - uiDrawStroke(p->Context, path, &black, &sp); - uiDrawFill(p->Context, path, &gradient); - - uiDrawFreePath(path); -} - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756692%28v=vs.85%29.aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756686%28v=vs.85%29.aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756685%28v=vs.85%29.aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/dd756674%28v=vs.85%29.aspx - -// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/ee329947%28v=vs.85%29.aspx - -// TODO https://msdn.microsoft.com/en-us/library/windows/desktop/ff485857%28v=vs.85%29.aspx - -// TODO? https://msdn.microsoft.com/en-us/library/windows/desktop/dd756755%28v=vs.85%29.aspx - -// TODO go through the API reference and spot examples that aren't listed - -// TODO all of these https://msdn.microsoft.com/en-us/library/windows/desktop/dd368187%28v=vs.85%29.aspx - -// cairo Samples Page (http://cairographics.org/samples/) - -static void crsourcergba(uiDrawBrush *brush, double r, double g, double b, double a) -{ - brush->Type = uiDrawBrushTypeSolid; - brush->R = r; - brush->G = g; - brush->B = b; - brush->A = a; -} - -// arc -static void drawCSArc(uiAreaDrawParams *p) -{ - double xc = 128.0; - double yc = 128.0; - double radius = 100.0; - double angle1 = 45.0 * (uiPi / 180.0); - double angle2 = 180.0 * (uiPi / 180.0); - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - sp.Thickness = 10.0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xc, yc, - radius, - angle1, - angle2 - angle1, - 0); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - crsourcergba(&source, 1, 0.2, 0.2, 0.6); - sp.Thickness = 6.0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xc, yc, - 10.0, - 0, 2 * uiPi, - 0); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &source); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xc, yc, - radius, - angle1, 0, - 0); - uiDrawPathLineTo(path, xc, yc); - uiDrawPathNewFigureWithArc(path, - xc, yc, - radius, - angle2, 0, - 0); - uiDrawPathLineTo(path, xc, yc); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// arc negative -static void drawCSArcNegative(uiAreaDrawParams *p) -{ - double xc = 128.0; - double yc = 128.0; - double radius = 100.0; - double angle1 = 45.0 * (uiPi / 180.0); - double angle2 = 180.0 * (uiPi / 180.0); - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - sp.Thickness = 10.0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xc, yc, - radius, - angle1, - angle2 - angle1, - 1); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - crsourcergba(&source, 1, 0.2, 0.2, 0.6); - sp.Thickness = 6.0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xc, yc, - 10.0, - 0, 2 * uiPi, - 0); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &source); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - xc, yc, - radius, - angle1, 0, - 0); - uiDrawPathLineTo(path, xc, yc); - uiDrawPathNewFigureWithArc(path, - xc, yc, - radius, - angle2, 0, - 0); - uiDrawPathLineTo(path, xc, yc); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// clip -static void drawCSClip(uiAreaDrawParams *p) -{ - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - uiDrawPathNewFigureWithArc(path, - 128.0, 128.0, - 76.8, - 0, 2 * uiPi, - 0); - uiDrawPathEnd(path); - uiDrawClip(p->Context, path); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 0, 0, 256, 256); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &source); - uiDrawFreePath(path); - - crsourcergba(&source, 0, 1, 0, 1); - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 0, 0); - uiDrawPathLineTo(path, 256, 256); - uiDrawPathNewFigure(path, 256, 0); - uiDrawPathLineTo(path, 0, 256); - uiDrawPathEnd(path); - sp.Thickness = 10.0; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// TODO clip image - -// curve rectangle -static void drawCSCurveRectangle(uiAreaDrawParams *p) -{ - double x0 = 25.6, /* parameters like cairo_rectangle */ - y0 = 25.6, - rect_width = 204.8, - rect_height = 204.8, - radius = 102.4; /* and an approximate curvature radius */ - - double x1,y1; - - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - x1=x0+rect_width; - y1=y0+rect_height; - if (!rect_width || !rect_height) - return; - if (rect_width/2 < radius) { - if (rect_height/2Context, path, &source); - crsourcergba(&source, 0.5, 0, 0, 0.5); - sp.Thickness = 10.0; - uiDrawStroke(p->Context, path, &source, &sp); - - uiDrawFreePath(path); -} - -// curve to -static void drawCSCurveTo(uiAreaDrawParams *p) -{ - double x=25.6, y=128.0; - double x1=102.4, y1=230.4, - x2=153.6, y2=25.6, - x3=230.4, y3=128.0; - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - uiDrawPathNewFigure(path, x, y); - uiDrawPathBezierTo(path, x1, y1, x2, y2, x3, y3); - uiDrawPathEnd(path); - sp.Thickness = 10.0; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - crsourcergba(&source, 1, 0.2, 0.2, 0.6); - sp.Thickness = 6.0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, x, y); - uiDrawPathLineTo(path, x1, y1); - uiDrawPathNewFigure(path, x2, y2); - uiDrawPathLineTo(path, x3, y3); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// dash -static void drawCSDash(uiAreaDrawParams *p) -{ - double dashes[] = { - 50.0, /* ink */ - 10.0, /* skip */ - 10.0, /* ink */ - 10.0 /* skip*/ - }; - int ndash = sizeof (dashes)/sizeof(dashes[0]); - double offset = -50.0; - - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = dashes; - sp.NumDashes = ndash; - sp.DashPhase = offset; - sp.Thickness = 10.0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 128.0, 25.6); - uiDrawPathLineTo(path, 230.4, 230.4); - uiDrawPathLineTo(path, 230.4 -102.4, 230.4 + 0.0); - uiDrawPathBezierTo(path, - 51.2, 230.4, - 51.2, 128.0, - 128.0, 128.0); - uiDrawPathEnd(path); - - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// fill and stroke2 -static void drawCSFillAndStroke2(uiAreaDrawParams *p) -{ - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - uiDrawPathNewFigure(path, 128.0, 25.6); - uiDrawPathLineTo(path, 230.4, 230.4); - uiDrawPathLineTo(path, 230.4 - 102.4, 230.4 + 0.0); - uiDrawPathBezierTo(path, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); - uiDrawPathCloseFigure(path); - - uiDrawPathNewFigure(path, 64.0, 25.6); - uiDrawPathLineTo(path, 64.0 + 51.2, 25.6 + 51.2); - uiDrawPathLineTo(path, 64.0 + 51.2 -51.2, 25.6 + 51.2 + 51.2); - uiDrawPathLineTo(path, 64.0 + 51.2 -51.2 -51.2, 25.6 + 51.2 + 51.2 -51.2); - uiDrawPathCloseFigure(path); - - uiDrawPathEnd(path); - - sp.Thickness = 10.0; - crsourcergba(&source, 0, 0, 1, 1); - uiDrawFill(p->Context, path, &source); - crsourcergba(&source, 0, 0, 0, 1); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// fill style -static void drawCSFillStyle(uiAreaDrawParams *p) -{ - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - uiDrawMatrix m; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - sp.Thickness = 6; - - path = uiDrawNewPath(uiDrawFillModeAlternate); - uiDrawPathAddRectangle(path, 12, 12, 232, 70); - uiDrawPathNewFigureWithArc(path, - 64, 64, - 40, - 0, 2*uiPi, - 0); - uiDrawPathNewFigureWithArc(path, - 192, 64, - 40, - 0, -2*uiPi, - 1); - uiDrawPathEnd(path); - - crsourcergba(&source, 0, 0.7, 0, 1); - uiDrawFill(p->Context, path, &source); - crsourcergba(&source, 0, 0, 0, 1); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - uiDrawMatrixSetIdentity(&m); - uiDrawMatrixTranslate(&m, 0, 128); - uiDrawTransform(p->Context, &m); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, 12, 12, 232, 70); - uiDrawPathNewFigureWithArc(path, - 64, 64, - 40, - 0, 2*uiPi, - 0); - uiDrawPathNewFigureWithArc(path, - 192, 64, - 40, - 0, -2*uiPi, - 1); - uiDrawPathEnd(path); - - crsourcergba(&source, 0, 0, 0.9, 1); - uiDrawFill(p->Context, path, &source); - crsourcergba(&source, 0, 0, 0, 1); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// TOOD gradient (radial gradient with two circles) - -// TODO image - -// TODO imagepattern - -// multi segment caps -static void drawCSMultiCaps(uiAreaDrawParams *p) -{ - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - uiDrawPathNewFigure(path, 50.0, 75.0); - uiDrawPathLineTo(path, 200.0, 75.0); - - uiDrawPathNewFigure(path, 50.0, 125.0); - uiDrawPathLineTo(path, 200.0, 125.0); - - uiDrawPathNewFigure(path, 50.0, 175.0); - uiDrawPathLineTo(path, 200.0, 175.0); - uiDrawPathEnd(path); - - sp.Thickness = 30.0; - sp.Cap = uiDrawLineCapRound; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// rounded rectangle -static void drawCSRoundRect(uiAreaDrawParams *p) -{ - double x = 25.6, /* parameters like cairo_rectangle */ - y = 25.6, - width = 204.8, - height = 204.8, - aspect = 1.0, /* aspect ratio */ - corner_radius = height / 10.0; /* and corner curvature radius */ - - double radius = corner_radius / aspect; - double degrees = uiPi / 180.0; - - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - path = uiDrawNewPath(uiDrawFillModeWinding); - - // top right corner - uiDrawPathNewFigureWithArc(path, - x + width - radius, y + radius, - radius, - -90 * degrees, uiPi / 2, - 0); - // bottom right corner - uiDrawPathArcTo(path, - x + width - radius, y + height - radius, - radius, - 0 * degrees, uiPi / 2, - 0); - // bottom left corner - uiDrawPathArcTo(path, - x + radius, y + height - radius, - radius, - 90 * degrees, uiPi / 2, - 0); - // top left corner - uiDrawPathArcTo(path, - x + radius, y + radius, - radius, - 180 * degrees, uiPi / 2, - 0); - uiDrawPathCloseFigure(path); - uiDrawPathEnd(path); - - crsourcergba(&source, 0.5, 0.5, 1, 1); - uiDrawFill(p->Context, path, &source); - crsourcergba(&source, 0.5, 0, 0, 0.5); - sp.Thickness = 10.0; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// set line cap -static void drawCSSetLineCap(uiAreaDrawParams *p) -{ - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - sp.Thickness = 30.0; - - sp.Cap = uiDrawLineCapFlat; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 64.0, 50.0); - uiDrawPathLineTo(path, 64.0, 200.0); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - sp.Cap = uiDrawLineCapRound; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 128.0, 50.0); - uiDrawPathLineTo(path, 128.0, 200.0); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - sp.Cap = uiDrawLineCapSquare; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 192.0, 50.0); - uiDrawPathLineTo(path, 192.0, 200.0); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - // draw helping lines - // keep the square cap to match the reference picture on the cairo website - crsourcergba(&source, 1, 0.2, 0.2, 1); - sp.Thickness = 2.56; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 64.0, 50.0); - uiDrawPathLineTo(path, 64.0, 200.0); - uiDrawPathNewFigure(path, 128.0, 50.0); - uiDrawPathLineTo(path, 128.0, 200.0); - uiDrawPathNewFigure(path, 192.0, 50.0); - uiDrawPathLineTo(path, 192.0, 200.0); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// set line join -static void drawCSSetLineJoin(uiAreaDrawParams *p) -{ - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - - crsourcergba(&source, 0, 0, 0, 1); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - sp.Thickness = 40.96; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 76.8, 84.48); - uiDrawPathLineTo(path, 76.8 + 51.2, 84.48 -51.2); - uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 84.48 - 51.2 + 51.2); - uiDrawPathEnd(path); - sp.Join = uiDrawLineJoinMiter; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 76.8, 161.28); - uiDrawPathLineTo(path, 76.8 + 51.2, 161.28 -51.2); - uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 161.28 - 51.2 + 51.2); - uiDrawPathEnd(path); - sp.Join = uiDrawLineJoinBevel; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, 76.8, 238.08); - uiDrawPathLineTo(path, 76.8 + 51.2, 238.08 -51.2); - uiDrawPathLineTo(path, 76.8 + 51.2 + 51.2, 238.08 - 51.2 + 51.2); - uiDrawPathEnd(path); - sp.Join = uiDrawLineJoinRound; - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); -} - -// TODO text - -// TODO text align center - -// TODO text extents - -// Quartz 2D Programming Guide - -static void cgaddrect(uiDrawPath *path, uiAreaDrawParams *p, double x, double y, double width, double height) -{ - uiDrawPathAddRectangle(path, - x, p->AreaHeight - y - height, - width, height); -} - -// Graphics Contexts > Creating a Window Graphics Context in Mac OS X -static void drawQ2DCreateWindowGC(uiAreaDrawParams *p) -{ - uiDrawPath *path; - uiDrawBrush brush; - - crsourcergba(&brush, 1, 0, 0, 1); - path = uiDrawNewPath(uiDrawFillModeWinding); - cgaddrect(path, p, 0, 0, 200, 100); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); - - crsourcergba(&brush, 0, 0, 1, .5); - path = uiDrawNewPath(uiDrawFillModeWinding); - cgaddrect(path, p, 0, 0, 100, 200); - uiDrawPathEnd(path); - uiDrawFill(p->Context, path, &brush); - uiDrawFreePath(path); -} - -// TODO Patterns page? - -// TODO Shadows page? - -// TODO Gradients page (includes some circle-circle radial gradients) - -// TODO Transparency Layers page? - -// TODO Core Graphics Layer Drawing page? - -// Cocoa Drawing Guide - -// TODO Advanced Drawing Techniques page? - -// TODO Text page, if any? - -static const struct drawtest tests[] = { - { "Original uiArea test", drawOriginal }, - { "Arc test", drawArcs }, - { "Direct2D: Direct2D Quickstart for Windows 8", drawD2DW8QS }, - { "Direct2D: Creating a Simple Direct2D Application", drawD2DSimpleApp }, - { "Direct2D: How to Create a Solid Color Brush", drawD2DSolidBrush }, - { "Direct2D: How to Create a Linear Gradient Brush", drawD2DLinearBrush }, - { "Direct2D: How to Create a Radial Gradient Brush", drawD2DRadialBrush }, - { "Direct2D: Path Geometries Overview", drawD2DPathGeometries }, - { "Direct2D: How to Create Geometry Groups", drawD2DGeometryGroup }, - { "Direct2D: How to Rotate an Object", drawD2DRotate }, - { "Direct2D: How to Scale an Object", drawD2DScale }, - { "Direct2D: How to Skew an Object", drawD2DSkew }, - { "Direct2D: How to Translate an Object", drawD2DTranslate }, - { "Direct2D: How to Apply Multiple Transforms to an Object", drawD2DMultiTransforms }, - { "Direct2D: How to Draw and Fill a Complex Shape", drawD2DComplexShape }, - { "cairo samples: arc", drawCSArc }, - { "cairo samples: arc negative", drawCSArcNegative }, - { "cairo samples: clip", drawCSClip }, - { "cairo samples: curve rectangle", drawCSCurveRectangle }, - { "cairo samples: curve to", drawCSCurveTo }, - { "cairo samples: dash", drawCSDash }, - { "cairo samples: fill and stroke2", drawCSFillAndStroke2 }, - { "cairo samples: fill style", drawCSFillStyle }, - { "cairo samples: multi segment caps", drawCSMultiCaps }, - { "cairo samples: rounded rectangle", drawCSRoundRect }, - { "cairo samples: set line cap", drawCSSetLineCap }, - { "cairo samples: set line join", drawCSSetLineJoin }, - { "Quartz 2D PG: Creating a Window Graphics Context in Mac OS X", drawQ2DCreateWindowGC }, - { NULL, NULL }, -}; - -void runDrawTest(int n, uiAreaDrawParams *p) -{ - (*(tests[n].draw))(p); -} - -void populateComboboxWithTests(uiCombobox *c) -{ - size_t i; - - for (i = 0; tests[i].name != NULL; i++) - uiComboboxAppend(c, tests[i].name); -} diff --git a/src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.png b/src/libui_sdl/libui/test/images/andlabs_16x16test_24june2016.png deleted file mode 100644 index a4c27d9ae054c75cfa4e65a872e9287914f77c37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272 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 UWFB|2M*si-07*qoM6N<$f{C8cCjbBd diff --git a/src/libui_sdl/libui/test/main.c b/src/libui_sdl/libui/test/main.c deleted file mode 100644 index 18774dcd..00000000 --- a/src/libui_sdl/libui/test/main.c +++ /dev/null @@ -1,180 +0,0 @@ -// 22 april 2015 -#include "test.h" - -// TODOs -// - blank page affects menus negatively on Windows - -void die(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "[test program] "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - abort(); -} - -int onClosing(uiWindow *w, void *data) -{ - printf("in onClosing()\n"); - uiQuit(); - return 1; -} - -int onShouldQuit(void *data) -{ - printf("in onShouldQuit()\n"); - if (uiMenuItemChecked(shouldQuitItem)) { - uiControlDestroy(uiControl(data)); - return 1; - } - return 0; -} - -uiBox *mainBox; -uiTab *mainTab; - -uiBox *(*newhbox)(void); -uiBox *(*newvbox)(void); - -int main(int argc, char *argv[]) -{ - uiInitOptions o; - int i; - const char *err; - uiWindow *w; - uiBox *page2, *page3, *page4, *page5; - uiBox *page6, *page7, *page8, *page9, *page10; - uiBox *page11, *page12, *page13; - uiTab *page14; - uiBox *page15; - uiBox *page16; - uiTab *outerTab; - uiTab *innerTab; - int nomenus = 0; - int startspaced = 0; - int steps = 0; - - newhbox = uiNewHorizontalBox; - newvbox = uiNewVerticalBox; - - memset(&o, 0, sizeof (uiInitOptions)); - for (i = 1; i < argc; i++) - if (strcmp(argv[i], "nomenus") == 0) - nomenus = 1; - else if (strcmp(argv[i], "startspaced") == 0) - startspaced = 1; - else if (strcmp(argv[i], "swaphv") == 0) { - newhbox = uiNewVerticalBox; - newvbox = uiNewHorizontalBox; - } else if (strcmp(argv[i], "steps") == 0) - steps = 1; - else { - fprintf(stderr, "%s: unrecognized option %s\n", argv[0], argv[i]); - return 1; - } - - err = uiInit(&o); - if (err != NULL) { - fprintf(stderr, "error initializing ui: %s\n", err); - uiFreeInitError(err); - return 1; - } - - if (!nomenus) - initMenus(); - - w = newWindow("Main Window", 320, 240, 1); - uiWindowOnClosing(w, onClosing, NULL); - printf("main window %p\n", (void *) w); - - uiOnShouldQuit(onShouldQuit, w); - - mainBox = newHorizontalBox(); - uiWindowSetChild(w, uiControl(mainBox)); - - outerTab = newTab(); - uiBoxAppend(mainBox, uiControl(outerTab), 1); - - mainTab = newTab(); - uiTabAppend(outerTab, "Pages 1-5", uiControl(mainTab)); - - // page 1 uses page 2's uiGroup - page2 = makePage2(); - - makePage1(w); - uiTabAppend(mainTab, "Page 1", uiControl(page1)); - - uiTabAppend(mainTab, "Page 2", uiControl(page2)); - - uiTabAppend(mainTab, "Empty Page", uiControl(uiNewHorizontalBox())); - - page3 = makePage3(); - uiTabAppend(mainTab, "Page 3", uiControl(page3)); - - page4 = makePage4(); - uiTabAppend(mainTab, "Page 4", uiControl(page4)); - - page5 = makePage5(w); - uiTabAppend(mainTab, "Page 5", uiControl(page5)); - - innerTab = newTab(); - uiTabAppend(outerTab, "Pages 6-10", uiControl(innerTab)); - - page6 = makePage6(); - uiTabAppend(innerTab, "Page 6", uiControl(page6)); - - page7 = makePage7(); - uiTabAppend(innerTab, "Page 7", uiControl(page7)); - - page8 = makePage8(); - uiTabAppend(innerTab, "Page 8", uiControl(page8)); - - page9 = makePage9(); - uiTabAppend(innerTab, "Page 9", uiControl(page9)); - - page10 = makePage10(); - uiTabAppend(innerTab, "Page 10", uiControl(page10)); - - innerTab = newTab(); - uiTabAppend(outerTab, "Pages 11-15", uiControl(innerTab)); - -// page11 = makePage11(); -// uiTabAppend(innerTab, "Page 11", uiControl(page11)); - - page12 = makePage12(); - uiTabAppend(innerTab, "Page 12", uiControl(page12)); - - page13 = makePage13(); - uiTabAppend(innerTab, "Page 13", uiControl(page13)); - - page14 = makePage14(); - uiTabAppend(innerTab, "Page 14", uiControl(page14)); - - page15 = makePage15(w); - uiTabAppend(innerTab, "Page 15", uiControl(page15)); - - innerTab = newTab(); - uiTabAppend(outerTab, "Pages 16-?", uiControl(innerTab)); - -// page16 = makePage16(); -// uiTabAppend(innerTab, "Page 16", uiControl(page16)); - - if (startspaced) - setSpaced(1); - - uiControlShow(uiControl(w)); - if (!steps) - uiMain(); - else { - uiMainSteps(); - while (uiMainStep(1)) - ; - } - printf("after uiMain()\n"); - uiUninit(); - printf("after uiUninit()\n"); - return 0; -} diff --git a/src/libui_sdl/libui/test/menus.c b/src/libui_sdl/libui/test/menus.c deleted file mode 100644 index 87ff80a3..00000000 --- a/src/libui_sdl/libui/test/menus.c +++ /dev/null @@ -1,112 +0,0 @@ -// 23 april 2015 -#include "test.h" - -uiMenu *fileMenu; -uiMenuItem *newItem; -uiMenuItem *openItem; -uiMenuItem *shouldQuitItem; -uiMenuItem *quitItem; -uiMenu *editMenu; -uiMenuItem *undoItem; -uiMenuItem *checkItem; -uiMenuItem *accelItem; -uiMenuItem *prefsItem; -uiMenu *testMenu; -uiMenuItem *enabledItem; -uiMenuItem *enableThisItem; -uiMenuItem *forceCheckedItem; -uiMenuItem *forceUncheckedItem; -uiMenuItem *whatWindowItem; -uiMenu *moreTestsMenu; -uiMenuItem *quitEnabledItem; -uiMenuItem *prefsEnabledItem; -uiMenuItem *aboutEnabledItem; -uiMenuItem *checkEnabledItem; -uiMenu *multiMenu; -uiMenu *helpMenu; -uiMenuItem *helpItem; -uiMenuItem *aboutItem; - -static void enableItemTest(uiMenuItem *item, uiWindow *w, void *data) -{ - if (uiMenuItemChecked(item)) - uiMenuItemEnable(uiMenuItem(data)); - else - uiMenuItemDisable(uiMenuItem(data)); -} - -static void forceOn(uiMenuItem *item, uiWindow *w, void *data) -{ - uiMenuItemSetChecked(enabledItem, 1); -} - -static void forceOff(uiMenuItem *item, uiWindow *w, void *data) -{ - uiMenuItemSetChecked(enabledItem, 0); -} - -static void whatWindow(uiMenuItem *item, uiWindow *w, void *data) -{ - printf("menu item clicked on window %p\n", (void *) w); -} - -void initMenus(void) -{ - fileMenu = uiNewMenu("File"); - newItem = uiMenuAppendItem(fileMenu, "New"); - openItem = uiMenuAppendItem(fileMenu, "Open"); - uiMenuAppendSeparator(fileMenu); - shouldQuitItem = uiMenuAppendCheckItem(fileMenu, "Should Quit"); - quitItem = uiMenuAppendQuitItem(fileMenu); - - editMenu = uiNewMenu("Edit"); - undoItem = uiMenuAppendItem(editMenu, "Undo"); - uiMenuItemDisable(undoItem); - uiMenuAppendSeparator(editMenu); - checkItem = uiMenuAppendCheckItem(editMenu, "Check Me\tTest"); - accelItem = uiMenuAppendItem(editMenu, "A&ccele&&rator T_es__t"); - prefsItem = uiMenuAppendPreferencesItem(editMenu); - - testMenu = uiNewMenu("Test"); - enabledItem = uiMenuAppendCheckItem(testMenu, "Enable Below Item"); - uiMenuItemSetChecked(enabledItem, 1); - enableThisItem = uiMenuAppendItem(testMenu, "This Will Be Enabled"); - uiMenuItemOnClicked(enabledItem, enableItemTest, enableThisItem); - forceCheckedItem = uiMenuAppendItem(testMenu, "Force Above Checked"); - uiMenuItemOnClicked(forceCheckedItem, forceOn, NULL); - forceUncheckedItem = uiMenuAppendItem(testMenu, "Force Above Unchecked"); - uiMenuItemOnClicked(forceUncheckedItem, forceOff, NULL); - uiMenuAppendSeparator(testMenu); - whatWindowItem = uiMenuAppendItem(testMenu, "What Window?"); - uiMenuItemOnClicked(whatWindowItem, whatWindow, NULL); - - moreTestsMenu = uiNewMenu("More Tests"); - quitEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "Quit Item Enabled"); - uiMenuItemSetChecked(quitEnabledItem, 1); - prefsEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "Preferences Item Enabled"); - uiMenuItemSetChecked(prefsEnabledItem, 1); - aboutEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "About Item Enabled"); - uiMenuItemSetChecked(aboutEnabledItem, 1); - uiMenuAppendSeparator(moreTestsMenu); - checkEnabledItem = uiMenuAppendCheckItem(moreTestsMenu, "Check Me Item Enabled"); - uiMenuItemSetChecked(checkEnabledItem, 1); - - multiMenu = uiNewMenu("Multi"); - uiMenuAppendSeparator(multiMenu); - uiMenuAppendSeparator(multiMenu); - uiMenuAppendItem(multiMenu, "Item && Item && Item"); - uiMenuAppendSeparator(multiMenu); - uiMenuAppendSeparator(multiMenu); - uiMenuAppendItem(multiMenu, "Item __ Item __ Item"); - uiMenuAppendSeparator(multiMenu); - uiMenuAppendSeparator(multiMenu); - - helpMenu = uiNewMenu("Help"); - helpItem = uiMenuAppendItem(helpMenu, "Help"); - aboutItem = uiMenuAppendAboutItem(helpMenu); - - uiMenuItemOnClicked(quitEnabledItem, enableItemTest, quitItem); - uiMenuItemOnClicked(prefsEnabledItem, enableItemTest, prefsItem); - uiMenuItemOnClicked(aboutEnabledItem, enableItemTest, aboutItem); - uiMenuItemOnClicked(checkEnabledItem, enableItemTest, checkItem); -} diff --git a/src/libui_sdl/libui/test/page1.c b/src/libui_sdl/libui/test/page1.c deleted file mode 100644 index 2115ba26..00000000 --- a/src/libui_sdl/libui/test/page1.c +++ /dev/null @@ -1,171 +0,0 @@ -// 29 april 2015 -#include "test.h" - -static uiEntry *entry; -static uiCheckbox *spaced; - -#define TEXT(name, type, getter, setter) \ - static void get ## name ## Text(uiButton *b, void *data) \ - { \ - char *text; \ - text = getter(type(data)); \ - uiEntrySetText(entry, text); \ - uiFreeText(text); \ - } \ - static void set ## name ## Text(uiButton *b, void *data) \ - { \ - char *text; \ - text = uiEntryText(entry); \ - setter(type(data), text); \ - uiFreeText(text); \ - } -TEXT(Window, uiWindow, uiWindowTitle, uiWindowSetTitle) -TEXT(Button, uiButton, uiButtonText, uiButtonSetText) -TEXT(Checkbox, uiCheckbox, uiCheckboxText, uiCheckboxSetText) -TEXT(Label, uiLabel, uiLabelText, uiLabelSetText) -TEXT(Group, uiGroup, uiGroupTitle, uiGroupSetTitle) - -static void onChanged(uiEntry *e, void *data) -{ - printf("onChanged()\n"); -} - -static void toggleSpaced(uiCheckbox *c, void *data) -{ - setSpaced(uiCheckboxChecked(spaced)); -} - -static void forceSpaced(uiButton *b, void *data) -{ - uiCheckboxSetChecked(spaced, data != NULL); -} - -static void showSpaced(uiButton *b, void *data) -{ - char s[12]; - - querySpaced(s); - uiEntrySetText(entry, s); -} - -#define SHED(method, Method) \ - static void method ## Control(uiButton *b, void *data) \ - { \ - uiControl ## Method(uiControl(data)); \ - } -SHED(show, Show) -SHED(hide, Hide) -SHED(enable, Enable) -SHED(disable, Disable) - -uiBox *page1; - -void makePage1(uiWindow *w) -{ - uiButton *getButton, *setButton; - uiBox *hbox; - uiBox *testBox; - uiLabel *label; - - page1 = newVerticalBox(); - - entry = uiNewEntry(); - uiEntryOnChanged(entry, onChanged, NULL); - uiBoxAppend(page1, uiControl(entry), 0); - - spaced = uiNewCheckbox("Spaced"); - uiCheckboxOnToggled(spaced, toggleSpaced, NULL); - label = uiNewLabel("Label"); - - hbox = newHorizontalBox(); - getButton = uiNewButton("Get Window Text"); - uiButtonOnClicked(getButton, getWindowText, w); - setButton = uiNewButton("Set Window Text"); - uiButtonOnClicked(setButton, setWindowText, w); - uiBoxAppend(hbox, uiControl(getButton), 1); - uiBoxAppend(hbox, uiControl(setButton), 1); - uiBoxAppend(page1, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - getButton = uiNewButton("Get Button Text"); - uiButtonOnClicked(getButton, getButtonText, getButton); - setButton = uiNewButton("Set Button Text"); - uiButtonOnClicked(setButton, setButtonText, getButton); - uiBoxAppend(hbox, uiControl(getButton), 1); - uiBoxAppend(hbox, uiControl(setButton), 1); - uiBoxAppend(page1, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - getButton = uiNewButton("Get Checkbox Text"); - uiButtonOnClicked(getButton, getCheckboxText, spaced); - setButton = uiNewButton("Set Checkbox Text"); - uiButtonOnClicked(setButton, setCheckboxText, spaced); - uiBoxAppend(hbox, uiControl(getButton), 1); - uiBoxAppend(hbox, uiControl(setButton), 1); - uiBoxAppend(page1, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - getButton = uiNewButton("Get Label Text"); - uiButtonOnClicked(getButton, getLabelText, label); - setButton = uiNewButton("Set Label Text"); - uiButtonOnClicked(setButton, setLabelText, label); - uiBoxAppend(hbox, uiControl(getButton), 1); - uiBoxAppend(hbox, uiControl(setButton), 1); - uiBoxAppend(page1, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - getButton = uiNewButton("Get Group Text"); - uiButtonOnClicked(getButton, getGroupText, page2group); - setButton = uiNewButton("Set Group Text"); - uiButtonOnClicked(setButton, setGroupText, page2group); - uiBoxAppend(hbox, uiControl(getButton), 1); - uiBoxAppend(hbox, uiControl(setButton), 1); - uiBoxAppend(page1, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - uiBoxAppend(hbox, uiControl(spaced), 1); - getButton = uiNewButton("On"); - uiButtonOnClicked(getButton, forceSpaced, getButton); - uiBoxAppend(hbox, uiControl(getButton), 0); - getButton = uiNewButton("Off"); - uiButtonOnClicked(getButton, forceSpaced, NULL); - uiBoxAppend(hbox, uiControl(getButton), 0); - getButton = uiNewButton("Show"); - uiButtonOnClicked(getButton, showSpaced, NULL); - uiBoxAppend(hbox, uiControl(getButton), 0); - uiBoxAppend(page1, uiControl(hbox), 0); - - testBox = newHorizontalBox(); - setButton = uiNewButton("Button"); - uiBoxAppend(testBox, uiControl(setButton), 1); - getButton = uiNewButton("Show"); - uiButtonOnClicked(getButton, showControl, setButton); - uiBoxAppend(testBox, uiControl(getButton), 0); - getButton = uiNewButton("Hide"); - uiButtonOnClicked(getButton, hideControl, setButton); - uiBoxAppend(testBox, uiControl(getButton), 0); - getButton = uiNewButton("Enable"); - uiButtonOnClicked(getButton, enableControl, setButton); - uiBoxAppend(testBox, uiControl(getButton), 0); - getButton = uiNewButton("Disable"); - uiButtonOnClicked(getButton, disableControl, setButton); - uiBoxAppend(testBox, uiControl(getButton), 0); - uiBoxAppend(page1, uiControl(testBox), 0); - - hbox = newHorizontalBox(); - getButton = uiNewButton("Show Box"); - uiButtonOnClicked(getButton, showControl, testBox); - uiBoxAppend(hbox, uiControl(getButton), 1); - getButton = uiNewButton("Hide Box"); - uiButtonOnClicked(getButton, hideControl, testBox); - uiBoxAppend(hbox, uiControl(getButton), 1); - getButton = uiNewButton("Enable Box"); - uiButtonOnClicked(getButton, enableControl, testBox); - uiBoxAppend(hbox, uiControl(getButton), 1); - getButton = uiNewButton("Disable Box"); - uiButtonOnClicked(getButton, disableControl, testBox); - uiBoxAppend(hbox, uiControl(getButton), 1); - uiBoxAppend(page1, uiControl(hbox), 0); - - uiBoxAppend(page1, uiControl(label), 0); -} diff --git a/src/libui_sdl/libui/test/page10.c b/src/libui_sdl/libui/test/page10.c deleted file mode 100644 index d7f26a73..00000000 --- a/src/libui_sdl/libui/test/page10.c +++ /dev/null @@ -1,185 +0,0 @@ -// 22 december 2015 -#include "test.h" - -static uiEntry *textString; -static uiFontButton *textFontButton; -static uiColorButton *textColorButton; -static uiEntry *textWidth; -static uiButton *textApply; -static uiCheckbox *noZ; -static uiArea *textArea; -static uiAreaHandler textAreaHandler; - -static double entryDouble(uiEntry *e) -{ - char *s; - double d; - - s = uiEntryText(e); - d = atof(s); - uiFreeText(s); - return d; -} - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) -{ - uiDrawTextFont *font; - uiDrawTextLayout *layout; - double r, g, b, al; - char surrogates[1 + 4 + 1 + 1]; - char composed[2 + 2 + 2 + 3 + 2 + 1]; - double width, height; - - font = uiFontButtonFont(textFontButton); - - layout = uiDrawNewTextLayout("One two three four", font, -1); - uiDrawTextLayoutSetColor(layout, - 4, 7, - 1, 0, 0, 1); - uiDrawTextLayoutSetColor(layout, - 8, 14, - 1, 0, 0.5, 0.5); - uiColorButtonColor(textColorButton, &r, &g, &b, &al); - uiDrawTextLayoutSetColor(layout, - 14, 18, - r, g, b, al); - uiDrawText(dp->Context, 10, 10, layout); - uiDrawTextLayoutExtents(layout, &width, &height); - uiDrawFreeTextLayout(layout); - - surrogates[0] = 'x'; - surrogates[1] = 0xF0; // surrogates D800 DF08 - surrogates[2] = 0x90; - surrogates[3] = 0x8C; - surrogates[4] = 0x88; - surrogates[5] = 'y'; - surrogates[6] = '\0'; - - layout = uiDrawNewTextLayout(surrogates, font, -1); - uiDrawTextLayoutSetColor(layout, - 1, 2, - 1, 0, 0.5, 0.5); - uiDrawText(dp->Context, 10, 10 + height, layout); - uiDrawFreeTextLayout(layout); - - composed[0] = 'z'; - composed[1] = 'z'; - composed[2] = 0xC3; // 2 - composed[3] = 0xA9; - composed[4] = 'z'; - composed[5] = 'z'; - composed[6] = 0x65; // 5 - composed[7] = 0xCC; - composed[8] = 0x81; - composed[9] = 'z'; - composed[10] = 'z'; - composed[11] = '\0'; - - layout = uiDrawNewTextLayout(composed, font, -1); - uiDrawTextLayoutSetColor(layout, - 2, 3, - 1, 0, 0.5, 0.5); - uiDrawTextLayoutSetColor(layout, - 5, 6, - 1, 0, 0.5, 0.5); - if (!uiCheckboxChecked(noZ)) - uiDrawTextLayoutSetColor(layout, - 6, 7, - 0.5, 0, 1, 0.5); - uiDrawText(dp->Context, 10, 10 + height + height, layout); - uiDrawFreeTextLayout(layout); - - uiDrawFreeTextFont(font); -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - // do nothing -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ - // do nothing -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - // do nothing -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - // do nothing - return 0; -} - -static void onFontChanged(uiFontButton *b, void *data) -{ - uiAreaQueueRedrawAll(textArea); -} - -static void onColorChanged(uiColorButton *b, void *data) -{ - uiAreaQueueRedrawAll(textArea); -} - -static void onNoZ(uiCheckbox *b, void *data) -{ - uiAreaQueueRedrawAll(textArea); -} - -uiBox *makePage10(void) -{ - uiBox *page10; - uiBox *vbox; - uiBox *hbox; - - page10 = newVerticalBox(); - vbox = page10; - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - textString = uiNewEntry(); - // TODO make it placeholder - uiEntrySetText(textString, "Enter text here"); - uiBoxAppend(hbox, uiControl(textString), 1); - - textFontButton = uiNewFontButton(); - uiFontButtonOnChanged(textFontButton, onFontChanged, NULL); - uiBoxAppend(hbox, uiControl(textFontButton), 1); - - textColorButton = uiNewColorButton(); - uiColorButtonOnChanged(textColorButton, onColorChanged, NULL); - uiBoxAppend(hbox, uiControl(textColorButton), 1); - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - textApply = uiNewButton("Apply"); - uiBoxAppend(hbox, uiControl(textApply), 1); - - textWidth = uiNewEntry(); - uiEntrySetText(textWidth, "-1"); - uiBoxAppend(hbox, uiControl(textWidth), 1); - - noZ = uiNewCheckbox("No Z Color"); - uiCheckboxOnToggled(noZ, onNoZ, NULL); - uiBoxAppend(hbox, uiControl(noZ), 0); - - textAreaHandler.Draw = handlerDraw; - textAreaHandler.MouseEvent = handlerMouseEvent; - textAreaHandler.MouseCrossed = handlerMouseCrossed; - textAreaHandler.DragBroken = handlerDragBroken; - textAreaHandler.KeyEvent = handlerKeyEvent; - textArea = uiNewArea(&textAreaHandler); - uiBoxAppend(vbox, uiControl(textArea), 1); - - // dummy objects to test single-activation - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - uiBoxAppend(hbox, uiControl(uiNewFontButton()), 1); - uiBoxAppend(hbox, uiControl(uiNewColorButton()), 1); - - return page10; -} diff --git a/src/libui_sdl/libui/test/page11.c b/src/libui_sdl/libui/test/page11.c deleted file mode 100644 index 02ad213a..00000000 --- a/src/libui_sdl/libui/test/page11.c +++ /dev/null @@ -1,54 +0,0 @@ -// 14 may 2016 -#include "test.h" - -// TODO add a test for childless windows -// TODO add tests for contianers with all controls hidden - -static uiGroup *newg(const char *n, int s) -{ - uiGroup *g; - - g = uiNewGroup(n); - if (s) - uiGroupSetChild(g, NULL); - return g; -} - -static uiTab *newt(int tt) -{ - uiTab *t; - - t = uiNewTab(); - if (tt) - uiTabAppend(t, "Test", NULL); - return t; -} - -uiBox *makePage11(void) -{ - uiBox *page11; - uiBox *ns; - uiBox *s; - - page11 = newHorizontalBox(); - - ns = newVerticalBox(); - uiBoxAppend(ns, uiControl(newg("", 0)), 0); - uiBoxAppend(ns, uiControl(newg("", 1)), 0); - uiBoxAppend(ns, uiControl(newg("Group", 0)), 0); - uiBoxAppend(ns, uiControl(newg("Group", 1)), 0); - uiBoxAppend(ns, uiControl(newt(0)), 0); - uiBoxAppend(ns, uiControl(newt(1)), 0); - uiBoxAppend(page11, uiControl(ns), 1); - - s = newVerticalBox(); - uiBoxAppend(s, uiControl(newg("", 0)), 1); - uiBoxAppend(s, uiControl(newg("", 1)), 1); - uiBoxAppend(s, uiControl(newg("Group", 0)), 1); - uiBoxAppend(s, uiControl(newg("Group", 1)), 1); - uiBoxAppend(s, uiControl(newt(0)), 1); - uiBoxAppend(s, uiControl(newt(1)), 1); - uiBoxAppend(page11, uiControl(s), 1); - - return page11; -} diff --git a/src/libui_sdl/libui/test/page12.c b/src/libui_sdl/libui/test/page12.c deleted file mode 100644 index 5a8e963f..00000000 --- a/src/libui_sdl/libui/test/page12.c +++ /dev/null @@ -1,60 +0,0 @@ -// 22 may 2016 -#include "test.h" - -// TODO OS X: if the hboxes are empty, the text views don't show up - -static void meChanged(uiMultilineEntry *e, void *data) -{ - printf("%s changed\n", (char *) data); -} - -static void setClicked(uiButton *b, void *data) -{ - uiMultilineEntrySetText(uiMultilineEntry(data), "set"); -} - -static void appendClicked(uiButton *b, void *data) -{ - uiMultilineEntryAppend(uiMultilineEntry(data), "append\n"); -} - -static uiBox *half(uiMultilineEntry *(*mk)(void), const char *which) -{ - uiBox *vbox, *hbox; - uiMultilineEntry *me; - uiButton *button; - - vbox = newVerticalBox(); - - me = (*mk)(); - uiMultilineEntryOnChanged(me, meChanged, (void *) which); - uiBoxAppend(vbox, uiControl(me), 1); - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - button = uiNewButton("Set"); - uiButtonOnClicked(button, setClicked, me); - uiBoxAppend(hbox, uiControl(button), 0); - - button = uiNewButton("Append"); - uiButtonOnClicked(button, appendClicked, me); - uiBoxAppend(hbox, uiControl(button), 0); - - return vbox; -} - -uiBox *makePage12(void) -{ - uiBox *page12; - uiBox *b; - - page12 = newHorizontalBox(); - - b = half(uiNewMultilineEntry, "wrap"); - uiBoxAppend(page12, uiControl(b), 1); - b = half(uiNewNonWrappingMultilineEntry, "no wrap"); - uiBoxAppend(page12, uiControl(b), 1); - - return page12; -} diff --git a/src/libui_sdl/libui/test/page13.c b/src/libui_sdl/libui/test/page13.c deleted file mode 100644 index 5e6fd52c..00000000 --- a/src/libui_sdl/libui/test/page13.c +++ /dev/null @@ -1,157 +0,0 @@ -// 28 may 2016 -#include "test.h" - -static int winClose(uiWindow *w, void *data) -{ - return 1; -} - -static void openTestWindow(uiBox *(*mkf)(void)) -{ - uiWindow *w; - uiBox *b; - uiCombobox *c; - uiEditableCombobox *e; - uiRadioButtons *r; - - w = uiNewWindow("Test", 100, 100, 0); - uiWindowOnClosing(w, winClose, NULL); - uiWindowSetMargined(w, 1); - b = (*mkf)(); - uiWindowSetChild(w, uiControl(b)); - -#define BA(x) uiBoxAppend(b, uiControl(x), 0) - BA(uiNewButton("")); - BA(uiNewCheckbox("")); - BA(uiNewEntry()); - BA(uiNewLabel("")); - BA(uiNewSpinbox(0, 100)); - BA(uiNewProgressBar()); - BA(uiNewSlider(0, 100)); - BA(uiNewHorizontalSeparator()); - c = uiNewCombobox(); - uiComboboxAppend(c, ""); - BA(c); - e = uiNewEditableCombobox(); - uiEditableComboboxAppend(e, ""); - BA(e); - r = uiNewRadioButtons(); - uiRadioButtonsAppend(r, ""); - BA(r); - BA(uiNewDateTimePicker()); - BA(uiNewDatePicker()); - BA(uiNewTimePicker()); - BA(uiNewMultilineEntry()); - // TODO nonscrolling and scrolling areas? - BA(uiNewFontButton()); - BA(uiNewColorButton()); - BA(uiNewPasswordEntry()); - BA(uiNewSearchEntry()); - BA(uiNewVerticalSeparator()); - - uiControlShow(uiControl(w)); -} - -static void buttonClicked(uiButton *b, void *data) -{ - openTestWindow((uiBox *(*)(void)) data); -} - -static void entryChanged(uiEntry *e, void *data) -{ - char *text; - - text = uiEntryText(e); - printf("%s entry changed: %s\n", (const char *) data, text); - uiFreeText(text); -} - -static void showHide(uiButton *b, void *data) -{ - uiControl *c = uiControl(data); - - if (uiControlVisible(c)) - uiControlHide(c); - else - uiControlShow(c); -} - -static void setIndeterminate(uiButton *b, void *data) -{ - uiProgressBar *p = uiProgressBar(data); - int value; - - value = uiProgressBarValue(p); - if (value == -1) - value = 50; - else - value = -1; - uiProgressBarSetValue(p, value); -} - -static void deleteFirst(uiButton *b, void *data) -{ - uiForm *f = uiForm(data); - - uiFormDelete(f, 0); -} - -uiBox *makePage13(void) -{ - uiBox *page13; - uiRadioButtons *rb; - uiButton *b; - uiForm *f; - uiEntry *e; - uiProgressBar *p; - - page13 = newVerticalBox(); - - rb = uiNewRadioButtons(); - uiRadioButtonsAppend(rb, "Item 1"); - uiRadioButtonsAppend(rb, "Item 2"); - uiRadioButtonsAppend(rb, "Item 3"); - uiBoxAppend(page13, uiControl(rb), 0); - - rb = uiNewRadioButtons(); - uiRadioButtonsAppend(rb, "Item A"); - uiRadioButtonsAppend(rb, "Item B"); - uiBoxAppend(page13, uiControl(rb), 0); - - b = uiNewButton("Horizontal"); - uiButtonOnClicked(b, buttonClicked, uiNewHorizontalBox); - uiBoxAppend(page13, uiControl(b), 0); - - b = uiNewButton("Vertical"); - uiButtonOnClicked(b, buttonClicked, uiNewVerticalBox); - uiBoxAppend(page13, uiControl(b), 0); - - f = newForm(); - - e = uiNewPasswordEntry(); - uiEntryOnChanged(e, entryChanged, "password"); - uiFormAppend(f, "Password Entry", uiControl(e), 0); - - e = uiNewSearchEntry(); - uiEntryOnChanged(e, entryChanged, "search"); - uiFormAppend(f, "Search Box", uiControl(e), 0); - - uiFormAppend(f, "MLE", uiControl(uiNewMultilineEntry()), 1); - - p = uiNewProgressBar(); - uiProgressBarSetValue(p, 50); - uiBoxAppend(page13, uiControl(p), 0); - b = uiNewButton("Toggle Indeterminate"); - uiButtonOnClicked(b, setIndeterminate, p); - uiBoxAppend(page13, uiControl(b), 0); - - b = uiNewButton("Show/Hide"); - uiButtonOnClicked(b, showHide, e); - uiBoxAppend(page13, uiControl(b), 0); - b = uiNewButton("Delete First"); - uiButtonOnClicked(b, deleteFirst, f); - uiBoxAppend(page13, uiControl(b), 0); - uiBoxAppend(page13, uiControl(f), 1); - - return page13; -} diff --git a/src/libui_sdl/libui/test/page14.c b/src/libui_sdl/libui/test/page14.c deleted file mode 100644 index 880534ce..00000000 --- a/src/libui_sdl/libui/test/page14.c +++ /dev/null @@ -1,350 +0,0 @@ -// 9 june 2016 -#include "test.h" - -// TODOs: -// - GTK+ - make all expanding controls the same size, to match the other OSs? will they match the other OSs? - -enum { - red, - green, - blue, - yellow, - white, - magenta, - orange, - purple, - cyan, -}; - -static const struct { - double r; - double g; - double b; -} colors[] = { - { 1, 0, 0 }, - { 0, 0.5, 0 }, - { 0, 0, 1 }, - { 1, 1, 0 }, - { 1, 1, 1 }, - { 1, 0, 1 }, - { 1, 0.65, 0 }, - { 0.5, 0, 0.5 }, - { 0, 1, 1 }, -}; - -static uiControl *testControl(const char *label, int color) -{ - uiColorButton *b; - - b = uiNewColorButton(); - uiColorButtonSetColor(b, colors[color].r, colors[color].g, colors[color].b, 1.0); - return uiControl(b); -} - -static uiControl *simpleGrid(void) -{ - uiGrid *g; - uiControl *t4; - - g = newGrid(); - uiGridAppend(g, testControl("1", red), - 0, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("2", green), - 1, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("3", blue), - 2, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - t4 = testControl("4", green); - uiGridAppend(g, t4, - 0, 1, 1, 1, - 0, uiAlignFill, 1, uiAlignFill); - uiGridInsertAt(g, testControl("5", blue), - t4, uiAtTrailing, 2, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("6", yellow), - -1, 0, 1, 2, - 1, uiAlignFill, 0, uiAlignFill); - return uiControl(g); -} - -static uiControl *boxComparison(void) -{ - uiBox *vbox; - uiGrid *g; - uiBox *hbox; - - vbox = newVerticalBox(); - uiBoxAppend(vbox, uiControl(uiNewLabel("Above")), 0); - uiBoxAppend(vbox, uiControl(uiNewHorizontalSeparator()), 0); - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - uiBoxAppend(hbox, testControl("1", white), 0); - uiBoxAppend(hbox, uiControl(uiNewLabel("A label")), 1); - uiBoxAppend(hbox, testControl("2", green), 0); - uiBoxAppend(hbox, uiControl(uiNewLabel("Another label")), 1); - uiBoxAppend(hbox, testControl("3", red), 0); - - uiBoxAppend(vbox, uiControl(uiNewHorizontalSeparator()), 0); - - g = newGrid(); - uiBoxAppend(vbox, uiControl(g), 0); - uiGridAppend(g, testControl("1", white), - 0, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, uiControl(uiNewLabel("A label")), - 1, 0, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("2", green), - 2, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, uiControl(uiNewLabel("Another label")), - 3, 0, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("3", red), - 4, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - - uiBoxAppend(vbox, uiControl(uiNewHorizontalSeparator()), 0); - uiBoxAppend(vbox, uiControl(uiNewLabel("Below")), 0); - return uiControl(vbox); -} - -static uiControl *emptyLine(void) -{ - uiGrid *g; - - g = newGrid(); - uiGridAppend(g, testControl("(0, 0)", red), - 0, 0, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - uiGridAppend(g, testControl("(0, 1)", blue), - 0, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("(10, 0)", green), - 10, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("(10, 1)", magenta), - 10, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - return uiControl(g); -} - -static uiControl *emptyGrid(void) -{ - uiGrid *g; - uiControl *t; - - g = newGrid(); - t = testControl("(0, 0)", red); - uiGridAppend(g, t, - 0, 0, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - uiControlHide(t); - return uiControl(g); -} - -// TODO insert (need specialized insert/delete) - -static uiControl *spanningGrid(void) -{ - uiGrid *g; - - g = newGrid(); - uiGridAppend(g, testControl("0", blue), - 0, 4, 4, 1, - 1, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("1", green), - 4, 0, 1, 4, - 0, uiAlignFill, 1, uiAlignFill); - uiGridAppend(g, testControl("2", red), - 3, 3, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - uiGridAppend(g, testControl("3", yellow), - 0, 3, 2, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("4", orange), - 3, 0, 1, 2, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("5", purple), - 1, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("6", white), - 0, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, testControl("7", cyan), - 1, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - return uiControl(g); -} - -// TODO make non-global -static uiButton *hideOne, *one, *showOne; - -static void onHideOne(uiButton *b, void *data) -{ - uiControlHide(uiControl(one)); -} - -static void onShowOne(uiButton *b, void *data) -{ - uiControlShow(uiControl(one)); -} - -static void onHideAll(uiButton *b, void *data) -{ - uiControlHide(uiControl(hideOne)); - uiControlHide(uiControl(one)); - uiControlHide(uiControl(showOne)); -} - -static void onShowAll(uiButton *b, void *data) -{ - uiControlShow(uiControl(hideOne)); - uiControlShow(uiControl(one)); - uiControlShow(uiControl(showOne)); -} - -#define AT(x) static void onInsert ## x(uiButton *b, void *data) \ - { \ - uiGrid *g = uiGrid(data); \ - uiGridInsertAt(g, uiControl(uiNewButton("Button")), \ - uiControl(b), uiAt ## x, 1, 1, \ - 0, uiAlignFill, 0, uiAlignFill); \ - } -AT(Leading) -AT(Top) -AT(Trailing) -AT(Bottom) - -static uiControl *assorted(void) -{ - uiGrid *outergrid; - uiGrid *innergrid; - uiButton *b; - - outergrid = newGrid(); - - innergrid = newGrid(); - one = uiNewButton("Test"); - uiGridAppend(innergrid, uiControl(one), - 1, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - hideOne = uiNewButton("Hide One"); - uiButtonOnClicked(hideOne, onHideOne, NULL); - uiGridAppend(innergrid, uiControl(hideOne), - 0, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - showOne = uiNewButton("Show One"); - uiButtonOnClicked(showOne, onShowOne, NULL); - uiGridAppend(innergrid, uiControl(showOne), - 2, 1, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - b = uiNewButton("Hide All"); - uiButtonOnClicked(b, onHideAll, NULL); - uiGridAppend(innergrid, uiControl(b), - 1, 0, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - b = uiNewButton("Show All"); - uiButtonOnClicked(b, onShowAll, NULL); - uiGridAppend(innergrid, uiControl(b), - 1, 2, 1, 1, - 0, uiAlignFill, 0, uiAlignFill); - uiGridAppend(outergrid, uiControl(innergrid), - 0, 0, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - - innergrid = newGrid(); - b = uiNewButton("Insert Trailing"); - uiButtonOnClicked(b, onInsertTrailing, innergrid); - uiGridAppend(innergrid, uiControl(b), - 0, 0, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - b = uiNewButton("Insert Bottom"); - uiButtonOnClicked(b, onInsertBottom, innergrid); - uiGridAppend(innergrid, uiControl(b), - 1, 0, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - b = uiNewButton("Insert Leading"); - uiButtonOnClicked(b, onInsertLeading, innergrid); - uiGridAppend(innergrid, uiControl(b), - 1, 1, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - b = uiNewButton("Insert Top"); - uiButtonOnClicked(b, onInsertTop, innergrid); - uiGridAppend(innergrid, uiControl(b), - 0, 1, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - uiGridAppend(outergrid, uiControl(innergrid), - 1, 0, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - - innergrid = newGrid(); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 0, 0, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 0, 1, 1, 1, - 1, uiAlignStart, 0, uiAlignFill); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 0, 2, 1, 1, - 1, uiAlignCenter, 0, uiAlignFill); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 0, 3, 1, 1, - 1, uiAlignEnd, 0, uiAlignFill); - uiGridAppend(outergrid, uiControl(innergrid), - 0, 1, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - - // TODO with only this, wrong size on OS X — expand sizing thing? - innergrid = newGrid(); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 0, 0, 1, 1, - 0, uiAlignFill, 1, uiAlignFill); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 1, 0, 1, 1, - 0, uiAlignFill, 1, uiAlignStart); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 2, 0, 1, 1, - 0, uiAlignFill, 1, uiAlignCenter); - uiGridAppend(innergrid, uiControl(uiNewColorButton()), - 3, 0, 1, 1, - 0, uiAlignFill, 1, uiAlignEnd); - uiGridAppend(outergrid, uiControl(innergrid), - 1, 1, 1, 1, - 1, uiAlignFill, 1, uiAlignFill); - - return uiControl(outergrid); -} - -static const struct { - const char *name; - uiControl *(*f)(void); -} pages[] = { - // based on GTK+ test/testgrid.c - { "Simple Grid", simpleGrid }, - { "Box Comparison", boxComparison }, - { "Empty Line", emptyLine }, - { "Empty Grid", emptyGrid }, - { "Spanning Grid", spanningGrid }, - // my own - { "Assorted", assorted }, - { NULL, NULL }, -}; - -uiTab *makePage14(void) -{ - uiTab *page14; - int i; - - page14 = newTab(); - - for (i = 0; pages[i].name != NULL; i++) - uiTabAppend(page14, - pages[i].name, - (*(pages[i].f))()); - - return page14; -} diff --git a/src/libui_sdl/libui/test/page15.c b/src/libui_sdl/libui/test/page15.c deleted file mode 100644 index e703bee2..00000000 --- a/src/libui_sdl/libui/test/page15.c +++ /dev/null @@ -1,260 +0,0 @@ -// 15 june 2016 -#include "test.h" - -static uiAreaHandler borderAH; -static int borderAHInit = 0; -static double lastx = -1, lasty = -1; - -struct trect { - double left; - double top; - double right; - double bottom; - int in; -}; - -#define tsetrect(re, l, t, r, b) re.left = l; re.top = t; re.right = r; re.bottom = b; re.in = lastx >= re.left && lastx < re.right && lasty >= re.top && lasty < re.bottom - -struct tareas { - struct trect move; - struct trect alsomove; - struct trect leftresize; - struct trect topresize; - struct trect rightresize; - struct trect bottomresize; - struct trect topleftresize; - struct trect toprightresize; - struct trect bottomleftresize; - struct trect bottomrightresize; - struct trect close; -}; - -static void filltareas(double awid, double aht, struct tareas *ta) -{ - tsetrect(ta->move, 20, 20, awid - 20, 20 + 30); - tsetrect(ta->alsomove, 30, 200, 100, 270); - tsetrect(ta->leftresize, 5, 20, 15, aht - 20); - tsetrect(ta->topresize, 20, 5, awid - 20, 15); - tsetrect(ta->rightresize, awid - 15, 20, awid - 5, aht - 20); - tsetrect(ta->bottomresize, 20, aht - 15, awid - 20, aht - 5); - tsetrect(ta->topleftresize, 5, 5, 15, 15); - tsetrect(ta->toprightresize, awid - 15, 5, awid - 5, 15); - tsetrect(ta->bottomleftresize, 5, aht - 15, 15, aht - 5); - tsetrect(ta->bottomrightresize, awid - 15, aht - 15, awid - 5, aht - 5); - tsetrect(ta->close, 130, 200, 200, 270); -} - -static void drawtrect(uiDrawContext *c, struct trect tr, double r, double g, double bl) -{ - uiDrawPath *p; - uiDrawBrush b; - - memset(&b, 0, sizeof (uiDrawBrush)); - b.Type = uiDrawBrushTypeSolid; - b.R = r; - b.G = g; - b.B = bl; - b.A = 1.0; - if (tr.in) { - b.R += b.R * 0.75; - b.G += b.G * 0.75; - b.B += b.B * 0.75; - } - p = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(p, - tr.left, - tr.top, - tr.right - tr.left, - tr.bottom - tr.top); - uiDrawPathEnd(p); - uiDrawFill(c, p, &b); - uiDrawFreePath(p); -} - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) -{ - struct tareas ta; - - filltareas(p->AreaWidth, p->AreaHeight, &ta); - drawtrect(p->Context, ta.move, 0, 0.5, 0); - drawtrect(p->Context, ta.alsomove, 0, 0.5, 0); - drawtrect(p->Context, ta.leftresize, 0, 0, 0.5); - drawtrect(p->Context, ta.topresize, 0, 0, 0.5); - drawtrect(p->Context, ta.rightresize, 0, 0, 0.5); - drawtrect(p->Context, ta.bottomresize, 0, 0, 0.5); - drawtrect(p->Context, ta.topleftresize, 0, 0.5, 0.5); - drawtrect(p->Context, ta.toprightresize, 0, 0.5, 0.5); - drawtrect(p->Context, ta.bottomleftresize, 0, 0.5, 0.5); - drawtrect(p->Context, ta.bottomrightresize, 0, 0.5, 0.5); - drawtrect(p->Context, ta.close, 0.5, 0, 0); - - // TODO add current position prints here -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - struct tareas ta; - - lastx = e->X; - lasty = e->Y; - filltareas(e->AreaWidth, e->AreaHeight, &ta); - // redraw our highlighted rect - uiAreaQueueRedrawAll(area); - if (e->Down != 1) - return; - if (ta.move.in || ta.alsomove.in) { - uiAreaBeginUserWindowMove(area); - return; - } -#define resize(cond, edge) if (cond) { uiAreaBeginUserWindowResize(area, edge); return; } - resize(ta.leftresize.in, uiWindowResizeEdgeLeft) - resize(ta.topresize.in, uiWindowResizeEdgeTop) - resize(ta.rightresize.in, uiWindowResizeEdgeRight) - resize(ta.bottomresize.in, uiWindowResizeEdgeBottom) - resize(ta.topleftresize.in, uiWindowResizeEdgeTopLeft) - resize(ta.toprightresize.in, uiWindowResizeEdgeTopRight) - resize(ta.bottomleftresize.in, uiWindowResizeEdgeBottomLeft) - resize(ta.bottomrightresize.in, uiWindowResizeEdgeBottomRight) - if (ta.close.in) { - // TODO - return; - } -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - return 0; -} - -static void borderWindowOpen(uiButton *b, void *data) -{ - uiWindow *w; - uiArea *a; - - if (!borderAHInit) { - borderAH.Draw = handlerDraw; - borderAH.MouseEvent = handlerMouseEvent; - borderAH.MouseCrossed = handlerMouseCrossed; - borderAH.DragBroken = handlerDragBroken; - borderAH.KeyEvent = handlerKeyEvent; - borderAHInit = 1; - } - - w = uiNewWindow("Border Resize Test", 300, 500, 0); - uiWindowSetBorderless(w, 1); - - a = uiNewArea(&borderAH); -// uiWindowSetChild(w, uiControl(a)); -{uiBox *b; -b=uiNewHorizontalBox(); -uiBoxAppend(b,uiControl(a),1); -uiWindowSetChild(w,uiControl(b));} -//TODO why is this hack needed? GTK+ issue - - uiControlShow(uiControl(w)); -} - -static uiSpinbox *width, *height; -static uiCheckbox *fullscreen; - -static void sizeWidth(uiSpinbox *s, void *data) -{ - uiWindow *w = uiWindow(data); - int xp, yp; - - uiWindowContentSize(w, &xp, &yp); - xp = uiSpinboxValue(width); - uiWindowSetContentSize(w, xp, yp); -} - -static void sizeHeight(uiSpinbox *s, void *data) -{ - uiWindow *w = uiWindow(data); - int xp, yp; - - uiWindowContentSize(w, &xp, &yp); - yp = uiSpinboxValue(height); - uiWindowSetContentSize(w, xp, yp); -} - -static void updatesize(uiWindow *w) -{ - int xp, yp; - - uiWindowContentSize(w, &xp, &yp); - uiSpinboxSetValue(width, xp); - uiSpinboxSetValue(height, yp); - // TODO on OS X this is updated AFTER sending the size change, not before - uiCheckboxSetChecked(fullscreen, uiWindowFullscreen(w)); -} - -void onSize(uiWindow *w, void *data) -{ - printf("size\n"); - updatesize(w); -} - -void setFullscreen(uiCheckbox *cb, void *data) -{ - uiWindow *w = uiWindow(data); - - uiWindowSetFullscreen(w, uiCheckboxChecked(fullscreen)); - updatesize(w); -} - -static void borderless(uiCheckbox *c, void *data) -{ - uiWindow *w = uiWindow(data); - - uiWindowSetBorderless(w, uiCheckboxChecked(c)); -} - -uiBox *makePage15(uiWindow *w) -{ - uiBox *page15; - uiBox *hbox; - uiButton *button; - uiCheckbox *checkbox; - - page15 = newVerticalBox(); - - hbox = newHorizontalBox(); - uiBoxAppend(page15, uiControl(hbox), 0); - - uiBoxAppend(hbox, uiControl(uiNewLabel("Size")), 0); - width = uiNewSpinbox(INT_MIN, INT_MAX); - uiBoxAppend(hbox, uiControl(width), 1); - height = uiNewSpinbox(INT_MIN, INT_MAX); - uiBoxAppend(hbox, uiControl(height), 1); - fullscreen = uiNewCheckbox("Fullscreen"); - uiBoxAppend(hbox, uiControl(fullscreen), 0); - - uiSpinboxOnChanged(width, sizeWidth, w); - uiSpinboxOnChanged(height, sizeHeight, w); - uiCheckboxOnToggled(fullscreen, setFullscreen, w); - uiWindowOnContentSizeChanged(w, onSize, NULL); - updatesize(w); - - checkbox = uiNewCheckbox("Borderless"); - uiCheckboxOnToggled(checkbox, borderless, w); - uiBoxAppend(page15, uiControl(checkbox), 0); - - button = uiNewButton("Borderless Resizes"); - uiButtonOnClicked(button, borderWindowOpen, NULL); - uiBoxAppend(page15, uiControl(button), 0); - - hbox = newHorizontalBox(); - uiBoxAppend(page15, uiControl(hbox), 1); - - uiBoxAppend(hbox, uiControl(uiNewVerticalSeparator()), 0); - - return page15; -} diff --git a/src/libui_sdl/libui/test/page2.c b/src/libui_sdl/libui/test/page2.c deleted file mode 100644 index abb06489..00000000 --- a/src/libui_sdl/libui/test/page2.c +++ /dev/null @@ -1,215 +0,0 @@ -// 29 april 2015 -#include "test.h" - -uiGroup *page2group; - -static uiLabel *movingLabel; -static uiBox *movingBoxes[2]; -static int movingCurrent; - -static void moveLabel(uiButton *b, void *data) -{ - int from, to; - - from = movingCurrent; - to = 0; - if (from == 0) - to = 1; - uiBoxDelete(movingBoxes[from], 0); - uiBoxAppend(movingBoxes[to], uiControl(movingLabel), 0); - movingCurrent = to; -} - -static int moveBack; -#define moveOutText "Move Page 1 Out" -#define moveBackText "Move Page 1 Back" - -static void movePage1(uiButton *b, void *data) -{ - if (moveBack) { - uiBoxDelete(mainBox, 1); - uiTabInsertAt(mainTab, "Page 1", 0, uiControl(page1)); - uiButtonSetText(b, moveOutText); - moveBack = 0; - return; - } - uiTabDelete(mainTab, 0); - uiBoxAppend(mainBox, uiControl(page1), 1); - uiButtonSetText(b, moveBackText); - moveBack = 1; -} - -static void openAnotherWindow(uiButton *bb, void *data) -{ - uiWindow *w; - uiBox *b; - - w = uiNewWindow("Another Window", 100, 100, data != NULL); - if (data != NULL) { - b = uiNewVerticalBox(); - uiBoxAppend(b, uiControl(uiNewEntry()), 0); - uiBoxAppend(b, uiControl(uiNewButton("Button")), 0); - uiBoxSetPadded(b, 1); - uiWindowSetChild(w, uiControl(b)); - } else - uiWindowSetChild(w, uiControl(makePage6())); - uiWindowSetMargined(w, 1); - uiControlShow(uiControl(w)); -} - -static void openAnotherDisabledWindow(uiButton *b, void *data) -{ - uiWindow *w; - - w = uiNewWindow("Another Window", 100, 100, data != NULL); - uiControlDisable(uiControl(w)); - uiControlShow(uiControl(w)); -} - -#define SHED(method, Method) \ - static void method ## Control(uiButton *b, void *data) \ - { \ - uiControl ## Method(uiControl(data)); \ - } -SHED(show, Show) -SHED(enable, Enable) -SHED(disable, Disable) - -static void echoReadOnlyText(uiEntry *e, void *data) -{ - char *text; - - text = uiEntryText(e); - uiEntrySetText(uiEntry(data), text); - uiFreeText(text); -} - -uiBox *makePage2(void) -{ - uiBox *page2; - uiBox *hbox; - uiGroup *group; - uiBox *vbox; - uiButton *button; - uiBox *nestedBox; - uiBox *innerhbox; - uiBox *innerhbox2; - uiBox *innerhbox3; - uiTab *disabledTab; - uiEntry *entry; - uiEntry *readonly; - uiButton *button2; - - page2 = newVerticalBox(); - - group = newGroup("Moving Label"); - page2group = group; - uiBoxAppend(page2, uiControl(group), 0); - vbox = newVerticalBox(); - uiGroupSetChild(group, uiControl(vbox)); - - hbox = newHorizontalBox(); - button = uiNewButton("Move the Label!"); - uiButtonOnClicked(button, moveLabel, NULL); - uiBoxAppend(hbox, uiControl(button), 1); - // have a blank label for space - uiBoxAppend(hbox, uiControl(uiNewLabel("")), 1); - uiBoxAppend(vbox, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - movingBoxes[0] = newVerticalBox(); - uiBoxAppend(hbox, uiControl(movingBoxes[0]), 1); - movingBoxes[1] = newVerticalBox(); - uiBoxAppend(hbox, uiControl(movingBoxes[1]), 1); - uiBoxAppend(vbox, uiControl(hbox), 0); - - movingCurrent = 0; - movingLabel = uiNewLabel("This label moves!"); - uiBoxAppend(movingBoxes[movingCurrent], uiControl(movingLabel), 0); - - hbox = newHorizontalBox(); - button = uiNewButton(moveOutText); - uiButtonOnClicked(button, movePage1, NULL); - uiBoxAppend(hbox, uiControl(button), 0); - uiBoxAppend(page2, uiControl(hbox), 0); - moveBack = 0; - - hbox = newHorizontalBox(); - uiBoxAppend(hbox, uiControl(uiNewLabel("Label Alignment Test")), 0); - button = uiNewButton("Open Menued Window"); - uiButtonOnClicked(button, openAnotherWindow, button); - uiBoxAppend(hbox, uiControl(button), 0); - button = uiNewButton("Open Menuless Window"); - uiButtonOnClicked(button, openAnotherWindow, NULL); - uiBoxAppend(hbox, uiControl(button), 0); - button = uiNewButton("Disabled Menued"); - uiButtonOnClicked(button, openAnotherDisabledWindow, button); - uiBoxAppend(hbox, uiControl(button), 0); - button = uiNewButton("Disabled Menuless"); - uiButtonOnClicked(button, openAnotherDisabledWindow, NULL); - uiBoxAppend(hbox, uiControl(button), 0); - uiBoxAppend(page2, uiControl(hbox), 0); - - nestedBox = newHorizontalBox(); - innerhbox = newHorizontalBox(); - uiBoxAppend(innerhbox, uiControl(uiNewButton("These")), 0); - button = uiNewButton("buttons"); - uiControlDisable(uiControl(button)); - uiBoxAppend(innerhbox, uiControl(button), 0); - uiBoxAppend(nestedBox, uiControl(innerhbox), 0); - innerhbox = newHorizontalBox(); - uiBoxAppend(innerhbox, uiControl(uiNewButton("are")), 0); - innerhbox2 = newHorizontalBox(); - button = uiNewButton("in"); - uiControlDisable(uiControl(button)); - uiBoxAppend(innerhbox2, uiControl(button), 0); - uiBoxAppend(innerhbox, uiControl(innerhbox2), 0); - uiBoxAppend(nestedBox, uiControl(innerhbox), 0); - innerhbox = newHorizontalBox(); - innerhbox2 = newHorizontalBox(); - uiBoxAppend(innerhbox2, uiControl(uiNewButton("nested")), 0); - innerhbox3 = newHorizontalBox(); - button = uiNewButton("boxes"); - uiControlDisable(uiControl(button)); - uiBoxAppend(innerhbox3, uiControl(button), 0); - uiBoxAppend(innerhbox2, uiControl(innerhbox3), 0); - uiBoxAppend(innerhbox, uiControl(innerhbox2), 0); - uiBoxAppend(nestedBox, uiControl(innerhbox), 0); - uiBoxAppend(page2, uiControl(nestedBox), 0); - - hbox = newHorizontalBox(); - button = uiNewButton("Enable Nested Box"); - uiButtonOnClicked(button, enableControl, nestedBox); - uiBoxAppend(hbox, uiControl(button), 0); - button = uiNewButton("Disable Nested Box"); - uiButtonOnClicked(button, disableControl, nestedBox); - uiBoxAppend(hbox, uiControl(button), 0); - uiBoxAppend(page2, uiControl(hbox), 0); - - disabledTab = newTab(); - uiTabAppend(disabledTab, "Disabled", uiControl(uiNewButton("Button"))); - uiTabAppend(disabledTab, "Tab", uiControl(uiNewLabel("Label"))); - uiControlDisable(uiControl(disabledTab)); - uiBoxAppend(page2, uiControl(disabledTab), 1); - - entry = uiNewEntry(); - readonly = uiNewEntry(); - uiEntryOnChanged(entry, echoReadOnlyText, readonly); - uiEntrySetText(readonly, "If you can see this, uiEntryReadOnly() isn't working properly."); - uiEntrySetReadOnly(readonly, 1); - if (uiEntryReadOnly(readonly)) - uiEntrySetText(readonly, ""); - uiBoxAppend(page2, uiControl(entry), 0); - uiBoxAppend(page2, uiControl(readonly), 0); - - hbox = newHorizontalBox(); - button = uiNewButton("Show Button 2"); - button2 = uiNewButton("Button 2"); - uiButtonOnClicked(button, showControl, button2); - uiControlHide(uiControl(button2)); - uiBoxAppend(hbox, uiControl(button), 1); - uiBoxAppend(hbox, uiControl(button2), 0); - uiBoxAppend(page2, uiControl(hbox), 0); - - return page2; -} diff --git a/src/libui_sdl/libui/test/page3.c b/src/libui_sdl/libui/test/page3.c deleted file mode 100644 index 1f229e93..00000000 --- a/src/libui_sdl/libui/test/page3.c +++ /dev/null @@ -1,69 +0,0 @@ -// 7 may 2015 -#include "test.h" - -static uiBox *makeSet(int omit, int hidden, int stretch) -{ - uiBox *hbox; - uiButton *buttons[4]; - - // don't use newHorizontalBox() - // the point of this test is to test hidden controls and padded - hbox = (*newhbox)(); - uiBoxSetPadded(hbox, 1); - if (omit != 0) { - buttons[0] = uiNewButton("First"); - uiBoxAppend(hbox, uiControl(buttons[0]), stretch); - } - if (omit != 1) { - buttons[1] = uiNewButton("Second"); - uiBoxAppend(hbox, uiControl(buttons[1]), stretch); - } - if (omit != 2) { - buttons[2] = uiNewButton("Third"); - uiBoxAppend(hbox, uiControl(buttons[2]), stretch); - } - if (omit != 3) { - buttons[3] = uiNewButton("Fourth"); - uiBoxAppend(hbox, uiControl(buttons[3]), stretch); - } - if (hidden != -1) - uiControlHide(uiControl(buttons[hidden])); - return hbox; -} - -uiBox *makePage3(void) -{ - uiBox *page3; - uiBox *hbox; - uiBox *hbox2; - uiBox *vbox; - int hidden; - - page3 = newVerticalBox(); - - // first the non-stretchy type - for (hidden = 0; hidden < 4; hidden++) { - // these two must stay unpadded as well, otherwise the test isn't meaningful - hbox2 = (*newhbox)(); - vbox = (*newvbox)(); - // reference set - hbox = makeSet(hidden, -1, 0); - uiBoxAppend(vbox, uiControl(hbox), 0); - // real thing - hbox = makeSet(-1, hidden, 0); - uiBoxAppend(vbox, uiControl(hbox), 0); - // pack vbox in - uiBoxAppend(hbox2, uiControl(vbox), 0); - // and have a button in there for showing right margins - uiBoxAppend(hbox2, uiControl(uiNewButton("Right Margin Test")), 1); - uiBoxAppend(page3, uiControl(hbox2), 0); - } - - // then the stretchy type - for (hidden = 0; hidden < 4; hidden++) { - hbox = makeSet(-1, hidden, 1); - uiBoxAppend(page3, uiControl(hbox), 0); - } - - return page3; -} diff --git a/src/libui_sdl/libui/test/page4.c b/src/libui_sdl/libui/test/page4.c deleted file mode 100644 index ce4a6afb..00000000 --- a/src/libui_sdl/libui/test/page4.c +++ /dev/null @@ -1,165 +0,0 @@ -// 19 may 2015 -#include "test.h" - -static uiSpinbox *spinbox; -static uiSlider *slider; -static uiProgressBar *pbar; - -#define CHANGED(what) \ - static void on ## what ## Changed(ui ## what *this, void *data) \ - { \ - int value; \ - printf("on %s changed\n", #what); \ - value = ui ## what ## Value(this); \ - uiSpinboxSetValue(spinbox, value); \ - uiSliderSetValue(slider, value); \ - uiProgressBarSetValue(pbar, value); \ - } -CHANGED(Spinbox) -CHANGED(Slider) - -#define SETTOO(what, name, n) \ - static void set ## what ## Too ## name(uiButton *this, void *data) \ - { \ - ui ## what ## SetValue(ui ## what(data), n); \ - } -SETTOO(Spinbox, Low, -80) -SETTOO(Spinbox, High, 80) -SETTOO(Slider, Low, -80) -SETTOO(Slider, High, 80) - -static uiCombobox *cbox; -static uiEditableCombobox *editable; -static uiRadioButtons *rb; - -static void appendCBRB(uiButton *b, void *data) -{ - uiComboboxAppend(cbox, "New Item"); - uiEditableComboboxAppend(editable, "New Item"); - uiRadioButtonsAppend(rb, "New Item"); -} - -static void onCBChanged(uiCombobox *c, void *data) -{ - printf("%s combobox changed to %d\n", - (char *) data, - (int) uiComboboxSelected(c)); - uiEditableComboboxSetText(editable, "changed"); -} - -static void onECBChanged(uiEditableCombobox *c, void *data) -{ - char *t; - - t = uiEditableComboboxText(c); - printf("%s combobox changed to %s\n", - (char *) data, - t); - uiFreeText(t); -} - -static void onRBSelected(uiRadioButtons *r, void *data) -{ - printf("radio buttons %d\n", uiRadioButtonsSelected(r)); -} - -static void selectSecond(uiButton *b, void *data) -{ - // TODO combobox, editable - uiRadioButtonsSetSelected(rb, 1); -} - -static void selectNone(uiButton *b, void *data) -{ - // TODO combobox, editable - uiRadioButtonsSetSelected(rb, -1); -} - -uiBox *makePage4(void) -{ - uiBox *page4; - uiBox *hbox; - uiSpinbox *xsb; - uiButton *b; - uiSlider *xsl; - - page4 = newVerticalBox(); - - spinbox = uiNewSpinbox(0, 100); - uiSpinboxOnChanged(spinbox, onSpinboxChanged, NULL); - uiBoxAppend(page4, uiControl(spinbox), 0); - - slider = uiNewSlider(0, 100); - uiSliderOnChanged(slider, onSliderChanged, NULL); - uiBoxAppend(page4, uiControl(slider), 0); - - pbar = uiNewProgressBar(); - uiBoxAppend(page4, uiControl(pbar), 0); - - uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0); - - hbox = newHorizontalBox(); - xsb = uiNewSpinbox(-40, 40); - uiBoxAppend(hbox, uiControl(xsb), 0); - b = uiNewButton("Bad Low"); - uiButtonOnClicked(b, setSpinboxTooLow, xsb); - uiBoxAppend(hbox, uiControl(b), 0); - b = uiNewButton("Bad High"); - uiButtonOnClicked(b, setSpinboxTooHigh, xsb); - uiBoxAppend(hbox, uiControl(b), 0); - uiBoxAppend(page4, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - xsl = uiNewSlider(-40, 40); - uiBoxAppend(hbox, uiControl(xsl), 0); - b = uiNewButton("Bad Low"); - uiButtonOnClicked(b, setSliderTooLow, xsl); - uiBoxAppend(hbox, uiControl(b), 0); - b = uiNewButton("Bad High"); - uiButtonOnClicked(b, setSliderTooHigh, xsl); - uiBoxAppend(hbox, uiControl(b), 0); - uiBoxAppend(page4, uiControl(hbox), 0); - - uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0); - - cbox = uiNewCombobox(); - uiComboboxAppend(cbox, "Item 1"); - uiComboboxAppend(cbox, "Item 2"); - uiComboboxAppend(cbox, "Item 3"); - uiComboboxOnSelected(cbox, onCBChanged, "noneditable"); - uiBoxAppend(page4, uiControl(cbox), 0); - - editable = uiNewEditableCombobox(); - uiEditableComboboxAppend(editable, "Editable Item 1"); - uiEditableComboboxAppend(editable, "Editable Item 2"); - uiEditableComboboxAppend(editable, "Editable Item 3"); - uiEditableComboboxOnChanged(editable, onECBChanged, "editable"); - uiBoxAppend(page4, uiControl(editable), 0); - - rb = uiNewRadioButtons(); - uiRadioButtonsAppend(rb, "Item 1"); - uiRadioButtonsAppend(rb, "Item 2"); - uiRadioButtonsAppend(rb, "Item 3"); - uiRadioButtonsOnSelected(rb, onRBSelected, NULL); - uiBoxAppend(page4, uiControl(rb), 0); - - hbox = newHorizontalBox(); - b = uiNewButton("Append"); - uiButtonOnClicked(b, appendCBRB, NULL); - uiBoxAppend(hbox, uiControl(b), 0); - b = uiNewButton("Second"); - uiButtonOnClicked(b, selectSecond, NULL); - uiBoxAppend(hbox, uiControl(b), 0); - b = uiNewButton("None"); - uiButtonOnClicked(b, selectNone, NULL); - uiBoxAppend(hbox, uiControl(b), 0); - uiBoxAppend(page4, uiControl(hbox), 0); - - uiBoxAppend(page4, uiControl(uiNewHorizontalSeparator()), 0); - - uiBoxAppend(page4, uiControl(uiNewDateTimePicker()), 0); - uiBoxAppend(page4, uiControl(uiNewDatePicker()), 0); - uiBoxAppend(page4, uiControl(uiNewTimePicker()), 0); - - return page4; -} diff --git a/src/libui_sdl/libui/test/page5.c b/src/libui_sdl/libui/test/page5.c deleted file mode 100644 index 9bc1105a..00000000 --- a/src/libui_sdl/libui/test/page5.c +++ /dev/null @@ -1,99 +0,0 @@ -// 22 may 2015 -#include "test.h" - -static uiWindow *parent; - -static void openFile(uiButton *b, void *data) -{ - char *fn; - - fn = uiOpenFile(parent); - if (fn == NULL) - uiLabelSetText(uiLabel(data), "(cancelled)"); - else { - uiLabelSetText(uiLabel(data), fn); - uiFreeText(fn); - } -} - -static void saveFile(uiButton *b, void *data) -{ - char *fn; - - fn = uiSaveFile(parent); - if (fn == NULL) - uiLabelSetText(uiLabel(data), "(cancelled)"); - else { - uiLabelSetText(uiLabel(data), fn); - uiFreeText(fn); - } -} - -static uiEntry *title, *description; - -static void msgBox(uiButton *b, void *data) -{ - char *t, *d; - - t = uiEntryText(title); - d = uiEntryText(description); - uiMsgBox(parent, t, d); - uiFreeText(d); - uiFreeText(t); -} - -static void msgBoxError(uiButton *b, void *data) -{ - char *t, *d; - - t = uiEntryText(title); - d = uiEntryText(description); - uiMsgBoxError(parent, t, d); - uiFreeText(d); - uiFreeText(t); -} - -uiBox *makePage5(uiWindow *pw) -{ - uiBox *page5; - uiBox *hbox; - uiButton *button; - uiLabel *label; - - parent = pw; - - page5 = newVerticalBox(); - -#define D(n, f) \ - hbox = newHorizontalBox(); \ - button = uiNewButton(n); \ - label = uiNewLabel(""); \ - uiButtonOnClicked(button, f, label); \ - uiBoxAppend(hbox, uiControl(button), 0); \ - uiBoxAppend(hbox, uiControl(label), 0); \ - uiBoxAppend(page5, uiControl(hbox), 0); - - D("Open File", openFile); - D("Save File", saveFile); - - title = uiNewEntry(); - uiEntrySetText(title, "Title"); - description = uiNewEntry(); - uiEntrySetText(description, "Description"); - - hbox = newHorizontalBox(); - button = uiNewButton("Message Box"); - uiButtonOnClicked(button, msgBox, NULL); - uiBoxAppend(hbox, uiControl(button), 0); - uiBoxAppend(hbox, uiControl(title), 0); - uiBoxAppend(page5, uiControl(hbox), 0); - - hbox = newHorizontalBox(); - button = uiNewButton("Error Box"); - uiButtonOnClicked(button, msgBoxError, NULL); - uiBoxAppend(hbox, uiControl(button), 0); - uiBoxAppend(hbox, uiControl(description), 0); - uiBoxAppend(page5, uiControl(hbox), 0); - - return page5; -} diff --git a/src/libui_sdl/libui/test/page6.c b/src/libui_sdl/libui/test/page6.c deleted file mode 100644 index 896b3d50..00000000 --- a/src/libui_sdl/libui/test/page6.c +++ /dev/null @@ -1,126 +0,0 @@ -// 8 october 2015 -#include -#include "test.h" - -static uiArea *area; -static uiCombobox *which; -static uiCheckbox *swallowKeys; - -struct handler { - uiAreaHandler ah; -}; - -static struct handler handler; - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) -{ - runDrawTest(uiComboboxSelected(which), p); -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - printf("mouse (%g,%g):(%g,%g) down:%d up:%d count:%d mods:%x held:0x%" PRIX64 "\n", - e->X, - e->Y, - e->AreaWidth, - e->AreaHeight, - (int) e->Down, - (int) e->Up, - (int) e->Count, - (uint32_t) e->Modifiers, - e->Held1To64); -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ - printf("mouse crossed %d\n", left); -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - printf("drag broken\n"); -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - char k[4]; - - k[0] = '\''; - k[1] = e->Key; - k[2] = '\''; - k[3] = '\0'; - if (e->Key == 0) { - k[0] = '0'; - k[1] = '\0'; - } - printf("key key:%s extkey:%d mod:%d mods:%d up:%d\n", - k, - (int) e->ExtKey, - (int) e->Modifier, - (int) e->Modifiers, - e->Up); - return uiCheckboxChecked(swallowKeys); -} - -static void shouldntHappen(uiCombobox *c, void *data) -{ - fprintf(stderr, "YOU SHOULD NOT SEE THIS. If you do, uiComboboxSetSelected() is triggering uiComboboxOnSelected(), which it should not.\n"); -} - -static void redraw(uiCombobox *c, void *data) -{ - uiAreaQueueRedrawAll(area); -} - -static void enableArea(uiButton *b, void *data) -{ - if (data != NULL) - uiControlEnable(uiControl(area)); - else - uiControlDisable(uiControl(area)); -} - -uiBox *makePage6(void) -{ - uiBox *page6; - uiBox *hbox; - uiButton *button; - - handler.ah.Draw = handlerDraw; - handler.ah.MouseEvent = handlerMouseEvent; - handler.ah.MouseCrossed = handlerMouseCrossed; - handler.ah.DragBroken = handlerDragBroken; - handler.ah.KeyEvent = handlerKeyEvent; - - page6 = newVerticalBox(); - - hbox = newHorizontalBox(); - uiBoxAppend(page6, uiControl(hbox), 0); - - which = uiNewCombobox(); - populateComboboxWithTests(which); - // this is to make sure that uiComboboxOnSelected() doesn't trigger with uiComboboxSetSelected() - uiComboboxOnSelected(which, shouldntHappen, NULL); - uiComboboxSetSelected(which, 0); - uiComboboxOnSelected(which, redraw, NULL); - uiBoxAppend(hbox, uiControl(which), 0); - - area = uiNewArea((uiAreaHandler *) (&handler)); - uiBoxAppend(page6, uiControl(area), 1); - - hbox = newHorizontalBox(); - uiBoxAppend(page6, uiControl(hbox), 0); - - swallowKeys = uiNewCheckbox("Consider key events handled"); - uiBoxAppend(hbox, uiControl(swallowKeys), 1); - - button = uiNewButton("Enable"); - uiButtonOnClicked(button, enableArea, button); - uiBoxAppend(hbox, uiControl(button), 0); - - button = uiNewButton("Disable"); - uiButtonOnClicked(button, enableArea, NULL); - uiBoxAppend(hbox, uiControl(button), 0); - - return page6; -} diff --git a/src/libui_sdl/libui/test/page7.c b/src/libui_sdl/libui/test/page7.c deleted file mode 100644 index 5cc91143..00000000 --- a/src/libui_sdl/libui/test/page7.c +++ /dev/null @@ -1,25 +0,0 @@ -// 13 october 2015 -#include "test.h" - -uiBox *makePage7(void) -{ - uiBox *page7; - uiGroup *group; - uiBox *box2; - - page7 = newHorizontalBox(); - - group = makePage7a(); - uiBoxAppend(page7, uiControl(group), 1); - - box2 = newVerticalBox(); - uiBoxAppend(page7, uiControl(box2), 1); - - group = makePage7b(); - uiBoxAppend(box2, uiControl(group), 1); - - group = makePage7c(); - uiBoxAppend(box2, uiControl(group), 1); - - return page7; -} diff --git a/src/libui_sdl/libui/test/page7a.c b/src/libui_sdl/libui/test/page7a.c deleted file mode 100644 index 72e03216..00000000 --- a/src/libui_sdl/libui/test/page7a.c +++ /dev/null @@ -1,139 +0,0 @@ -// 13 october 2015 -#include "test.h" - -static uiArea *area; -static uiEntry *startAngle; -static uiEntry *sweep; -static uiCheckbox *negative; -static uiCheckbox *radians; - -struct handler { - uiAreaHandler ah; -}; - -static struct handler handler; - -// based on the cairo arc sample -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) -{ - double xc = 128.0; - double yc = 128.0; - double radius = 100.0; - uiDrawBrush source; - uiDrawStrokeParams sp; - uiDrawPath *path; - char *startText; - char *sweepText; - double factor; - - source.Type = uiDrawBrushTypeSolid; - source.R = 0; - source.G = 0; - source.B = 0; - source.A = 1; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Dashes = NULL; - sp.NumDashes = 0; - sp.DashPhase = 0; - - startText = uiEntryText(startAngle); - sweepText = uiEntryText(sweep); - - factor = uiPi / 180; - if (uiCheckboxChecked(radians)) - factor = 1; - - sp.Thickness = 10.0; - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(path, xc, yc); - uiDrawPathArcTo(path, - xc, yc, - radius, - atof(startText) * factor, - atof(sweepText) * factor, - uiCheckboxChecked(negative)); - uiDrawPathEnd(path); - uiDrawStroke(p->Context, path, &source, &sp); - uiDrawFreePath(path); - - uiFreeText(startText); - uiFreeText(sweepText); -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - // do nothing -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ - // do nothing -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - // do nothing -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - return 0; -} - -static void entryChanged(uiEntry *e, void *data) -{ - uiAreaQueueRedrawAll(area); -} - -static void checkboxToggled(uiCheckbox *c, void *data) -{ - uiAreaQueueRedrawAll(area); -} - -uiGroup *makePage7a(void) -{ - uiGroup *group; - uiBox *box, *box2; - - handler.ah.Draw = handlerDraw; - handler.ah.MouseEvent = handlerMouseEvent; - handler.ah.MouseCrossed = handlerMouseCrossed; - handler.ah.DragBroken = handlerDragBroken; - handler.ah.KeyEvent = handlerKeyEvent; - - group = newGroup("Arc Test"); - - box = newVerticalBox(); - uiGroupSetChild(group, uiControl(box)); - - area = uiNewArea((uiAreaHandler *) (&handler)); - uiBoxAppend(box, uiControl(area), 1); - - box2 = newHorizontalBox(); - uiBoxAppend(box, uiControl(box2), 0); - - uiBoxAppend(box2, uiControl(uiNewLabel("Start Angle")), 0); - startAngle = uiNewEntry(); - uiEntryOnChanged(startAngle, entryChanged, NULL); - uiBoxAppend(box2, uiControl(startAngle), 1); - - box2 = newHorizontalBox(); - uiBoxAppend(box, uiControl(box2), 0); - - uiBoxAppend(box2, uiControl(uiNewLabel("Sweep")), 0); - sweep = uiNewEntry(); - uiEntryOnChanged(sweep, entryChanged, NULL); - uiBoxAppend(box2, uiControl(sweep), 1); - - negative = uiNewCheckbox("Negative"); - uiCheckboxOnToggled(negative, checkboxToggled, NULL); - uiBoxAppend(box, uiControl(negative), 0); - - radians = uiNewCheckbox("Radians"); - uiCheckboxOnToggled(radians, checkboxToggled, NULL); - uiBoxAppend(box, uiControl(radians), 0); - - return group; -} diff --git a/src/libui_sdl/libui/test/page7b.c b/src/libui_sdl/libui/test/page7b.c deleted file mode 100644 index d1f98a74..00000000 --- a/src/libui_sdl/libui/test/page7b.c +++ /dev/null @@ -1,71 +0,0 @@ -// 13 october 2015 -#include "test.h" - -static uiArea *area; -static uiCheckbox *label; - -struct handler { - uiAreaHandler ah; -}; - -static struct handler handler; - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *p) -{ - // do nothing -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - char pos[128]; - - // wonderful, vanilla snprintf() isn't in visual studio 2013 - http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx - // we can't use _snprintf() in the test suite because that's msvc-only, so oops. sprintf() it is. - sprintf(pos, "X %g Y %g", e->X, e->Y); - uiCheckboxSetText(label, pos); -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ -printf("%d %d\n", left, !left); - uiCheckboxSetChecked(label, !left); -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - // do nothing -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - if (e->Key == 'h' && !e->Up) { - // TODO hide the widget momentarily on the h key - return 1; - } - return 0; -} - -uiGroup *makePage7b(void) -{ - uiGroup *group; - uiBox *box; - - handler.ah.Draw = handlerDraw; - handler.ah.MouseEvent = handlerMouseEvent; - handler.ah.MouseCrossed = handlerMouseCrossed; - handler.ah.DragBroken = handlerDragBroken; - handler.ah.KeyEvent = handlerKeyEvent; - - group = newGroup("Scrolling Mouse Test"); - - box = newVerticalBox(); - uiGroupSetChild(group, uiControl(box)); - - area = uiNewScrollingArea((uiAreaHandler *) (&handler), 5000, 5000); - uiBoxAppend(box, uiControl(area), 1); - - label = uiNewCheckbox(""); - uiBoxAppend(box, uiControl(label), 0); - - return group; -} diff --git a/src/libui_sdl/libui/test/page7c.c b/src/libui_sdl/libui/test/page7c.c deleted file mode 100644 index ac6a316c..00000000 --- a/src/libui_sdl/libui/test/page7c.c +++ /dev/null @@ -1,133 +0,0 @@ -// 13 october 2015 -#include "test.h" - -static uiArea *area; - -struct handler { - uiAreaHandler ah; -}; - -static struct handler handler; - -#define areaSize 250 -#define borderThickness 1 -#define padding 30 -#define circleRadius ((areaSize - padding) / 2) - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) -{ - uiDrawPath *path; - uiDrawBrush brush; - uiDrawStrokeParams sp; - uiDrawBrushGradientStop stops[2]; - - memset(&brush, 0, sizeof (uiDrawBrush)); - memset(&sp, 0, sizeof (uiDrawStrokeParams)); - - // add some buffering to detect scrolls that aren't on the dot and draws that are outside the scroll area on Windows - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, - -50, -50, - areaSize + 100, areaSize + 100); - uiDrawPathEnd(path); - brush.Type = uiDrawBrushTypeSolid; - brush.R = 0; - brush.G = 1; - brush.B = 0; - brush.A = 1; - uiDrawFill(dp->Context, path, &brush); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(path, - 0, 0, - areaSize, areaSize); - uiDrawPathEnd(path); - brush.Type = uiDrawBrushTypeSolid; - brush.R = 1; - brush.G = 1; - brush.B = 1; - brush.A = 1; - uiDrawFill(dp->Context, path, &brush); - brush.Type = uiDrawBrushTypeSolid; - brush.R = 1; - brush.G = 0; - brush.B = 0; - brush.A = 1; - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.Thickness = 1; - sp.MiterLimit = uiDrawDefaultMiterLimit; - uiDrawStroke(dp->Context, path, &brush, &sp); - uiDrawFreePath(path); - - path = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigureWithArc(path, - areaSize / 2, areaSize / 2, - circleRadius, - 0, 2 * uiPi, - 0); - uiDrawPathEnd(path); - stops[0].Pos =0.0; - stops[0].R = 0.0; - stops[0].G = 1.0; - stops[0].B = 1.0; - stops[0].A = 1.0; - stops[1].Pos = 1.0; - stops[1].R = 0.0; - stops[1].G = 0.0; - stops[1].B = 1.0; - stops[1].A = 1.0; - brush.Type = uiDrawBrushTypeLinearGradient; - brush.X0 = areaSize / 2; - brush.Y0 = padding; - brush.X1 = areaSize / 2; - brush.Y1 = areaSize - padding; - brush.Stops = stops; - brush.NumStops = 2; - uiDrawFill(dp->Context, path, &brush); - uiDrawFreePath(path); -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - // do nothing -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ - // do nothing -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - // do nothing -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - if (e->Key == 'h' && !e->Up) { - // TODO hide the widget momentarily on the h key - return 1; - } - return 0; -} - -uiGroup *makePage7c(void) -{ - uiGroup *group; - - handler.ah.Draw = handlerDraw; - handler.ah.MouseEvent = handlerMouseEvent; - handler.ah.MouseCrossed = handlerMouseCrossed; - handler.ah.DragBroken = handlerDragBroken; - handler.ah.KeyEvent = handlerKeyEvent; - - group = newGroup("Scrolling Drawing Test"); - - area = uiNewScrollingArea((uiAreaHandler *) (&handler), - areaSize, areaSize); - uiGroupSetChild(group, uiControl(area)); - - return group; -} diff --git a/src/libui_sdl/libui/test/page8.c b/src/libui_sdl/libui/test/page8.c deleted file mode 100644 index 7d855560..00000000 --- a/src/libui_sdl/libui/test/page8.c +++ /dev/null @@ -1,46 +0,0 @@ -// 22 december 2015 -#include "test.h" - -static void onListFonts(uiButton *b, void *data) -{ - uiDrawFontFamilies *ff; - char *this; - int i, n; - - uiMultilineEntrySetText(uiMultilineEntry(data), ""); - ff = uiDrawListFontFamilies(); - n = uiDrawFontFamiliesNumFamilies(ff); - for (i = 0; i < n; i++) { - this = uiDrawFontFamiliesFamily(ff, i); - uiMultilineEntryAppend(uiMultilineEntry(data), this); - uiMultilineEntryAppend(uiMultilineEntry(data), "\n"); - uiFreeText(this); - } - uiDrawFreeFontFamilies(ff); -} - -uiBox *makePage8(void) -{ - uiBox *page8; - uiGroup *group; - uiBox *vbox; - uiMultilineEntry *me; - uiButton *button; - - page8 = newHorizontalBox(); - - group = newGroup("Font Families"); - uiBoxAppend(page8, uiControl(group), 1); - - vbox = newVerticalBox(); - uiGroupSetChild(group, uiControl(vbox)); - - me = uiNewMultilineEntry(); - uiBoxAppend(vbox, uiControl(me), 1); - - button = uiNewButton("List Font Families"); - uiButtonOnClicked(button, onListFonts, me); - uiBoxAppend(vbox, uiControl(button), 0); - - return page8; -} diff --git a/src/libui_sdl/libui/test/page9.c b/src/libui_sdl/libui/test/page9.c deleted file mode 100644 index 65b2d3a1..00000000 --- a/src/libui_sdl/libui/test/page9.c +++ /dev/null @@ -1,289 +0,0 @@ -// 22 december 2015 -#include "test.h" - -static uiEntry *textString; -static uiEntry *textFont; -static uiEntry *textSize; -static uiCombobox *textWeight; -static uiCombobox *textItalic; -static uiCheckbox *textSmallCaps; -static uiCombobox *textStretch; -static uiEntry *textWidth; -static uiButton *textApply; -static uiCheckbox *addLeading; -static uiArea *textArea; -static uiAreaHandler textAreaHandler; - -static double entryDouble(uiEntry *e) -{ - char *s; - double d; - - s = uiEntryText(e); - d = atof(s); - uiFreeText(s); - return d; -} - -static void drawGuides(uiDrawContext *c, uiDrawTextFontMetrics *m) -{ - uiDrawPath *p; - uiDrawBrush b; - uiDrawStrokeParams sp; - double leading; - double y; - - leading = 0; - if (uiCheckboxChecked(addLeading)) - leading = m->Leading; - - memset(&b, 0, sizeof (uiDrawBrush)); - b.Type = uiDrawBrushTypeSolid; - memset(&sp, 0, sizeof (uiDrawStrokeParams)); - sp.Cap = uiDrawLineCapFlat; - sp.Join = uiDrawLineJoinMiter; - sp.MiterLimit = uiDrawDefaultMiterLimit; - sp.Thickness = 2; - - uiDrawSave(c); - - p = uiDrawNewPath(uiDrawFillModeWinding); - y = 10; - uiDrawPathNewFigure(p, 8, y); - y += m->Ascent; - uiDrawPathLineTo(p, 8, y); - uiDrawPathEnd(p); - b.R = 0.94; - b.G = 0.5; - b.B = 0.5; - b.A = 1.0; - uiDrawStroke(c, p, &b, &sp); - uiDrawFreePath(p); - - p = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(p, 8, y); - y += m->Descent; - uiDrawPathLineTo(p, 8, y); - uiDrawPathEnd(p); - b.R = 0.12; - b.G = 0.56; - b.B = 1.0; - b.A = 1.0; - uiDrawStroke(c, p, &b, &sp); - uiDrawFreePath(p); - - // and again for the second line - p = uiDrawNewPath(uiDrawFillModeWinding); - y += leading; - uiDrawPathNewFigure(p, 8, y); - y += m->Ascent; - uiDrawPathLineTo(p, 8, y); - uiDrawPathEnd(p); - b.R = 0.94; - b.G = 0.5; - b.B = 0.5; - b.A = 0.75; - uiDrawStroke(c, p, &b, &sp); - uiDrawFreePath(p); - - p = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathNewFigure(p, 8, y); - y += m->Descent; - uiDrawPathLineTo(p, 8, y); - uiDrawPathEnd(p); - b.R = 0.12; - b.G = 0.56; - b.B = 1.0; - b.A = 0.75; - uiDrawStroke(c, p, &b, &sp); - uiDrawFreePath(p); - - // and a box to text layout top-left corners - p = uiDrawNewPath(uiDrawFillModeWinding); - uiDrawPathAddRectangle(p, 0, 0, 10, 10); - uiDrawPathEnd(p); - uiDrawClip(c, p); - b.R = 0.85; - b.G = 0.65; - b.B = 0.13; - b.A = 1.0; - uiDrawStroke(c, p, &b, &sp); - uiDrawFreePath(p); - - uiDrawRestore(c); -} - -static void handlerDraw(uiAreaHandler *a, uiArea *area, uiAreaDrawParams *dp) -{ - uiDrawTextFontDescriptor desc; - uiDrawTextFont *font; - char *s; - char *family; // make compiler happy - uiDrawTextLayout *layout; - uiDrawTextFontMetrics metrics; - double ypos; - double width; - double height; - - memset(&desc, 0, sizeof (uiDrawTextFontDescriptor)); - family = uiEntryText(textFont); - desc.Family = family; - desc.Size = entryDouble(textSize); - desc.Weight = uiComboboxSelected(textWeight); - desc.Italic = uiComboboxSelected(textItalic); - desc.Stretch = uiComboboxSelected(textStretch); - font = uiDrawLoadClosestFont(&desc); - uiFreeText(family); - uiDrawTextFontGetMetrics(font, &metrics); - - width = entryDouble(textWidth); - - drawGuides(dp->Context, &metrics); - - s = uiEntryText(textString); - layout = uiDrawNewTextLayout(s, font, width); - uiFreeText(s); - if (uiCheckboxChecked(textSmallCaps)) - ; // TODO - ypos = 10; - uiDrawText(dp->Context, 10, ypos, layout); - // TODO make these optional? - uiDrawTextLayoutExtents(layout, &width, &height); - uiDrawFreeTextLayout(layout); - - layout = uiDrawNewTextLayout("This is a second line", font, -1); - if (/*TODO reuse width*/entryDouble(textWidth) < 0) { - double ad; - - ad = metrics.Ascent + metrics.Descent; - printf("ad:%g extent:%g\n", ad, height); - } - ypos += height; - if (uiCheckboxChecked(addLeading)) - ypos += metrics.Leading; - uiDrawText(dp->Context, 10, ypos, layout); - uiDrawFreeTextLayout(layout); - - uiDrawFreeTextFont(font); -} - -static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent *e) -{ - // do nothing -} - -static void handlerMouseCrossed(uiAreaHandler *ah, uiArea *a, int left) -{ - // do nothing -} - -static void handlerDragBroken(uiAreaHandler *ah, uiArea *a) -{ - // do nothing -} - -static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) -{ - // do nothing - return 0; -} - -static void onTextApply(uiButton *b, void *data) -{ - uiAreaQueueRedrawAll(textArea); -} - -uiBox *makePage9(void) -{ - uiBox *page9; - uiBox *vbox; - uiBox *hbox; - - page9 = newVerticalBox(); - vbox = page9; - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - textString = uiNewEntry(); - // TODO make it placeholder - uiEntrySetText(textString, "Enter text here"); - uiBoxAppend(hbox, uiControl(textString), 1); - - textFont = uiNewEntry(); - uiEntrySetText(textFont, "Arial"); - uiBoxAppend(hbox, uiControl(textFont), 1); - - textSize = uiNewEntry(); - uiEntrySetText(textSize, "10"); - uiBoxAppend(hbox, uiControl(textSize), 1); - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - textWeight = uiNewCombobox(); - uiComboboxAppend(textWeight, "Thin"); - uiComboboxAppend(textWeight, "Ultra Light"); - uiComboboxAppend(textWeight, "Light"); - uiComboboxAppend(textWeight, "Book"); - uiComboboxAppend(textWeight, "Normal"); - uiComboboxAppend(textWeight, "Medium"); - uiComboboxAppend(textWeight, "Semi Bold"); - uiComboboxAppend(textWeight, "Bold"); - uiComboboxAppend(textWeight, "Ultra Bold"); - uiComboboxAppend(textWeight, "Heavy"); - uiComboboxAppend(textWeight, "Ultra Heavy"); - uiComboboxSetSelected(textWeight, uiDrawTextWeightNormal); - uiBoxAppend(hbox, uiControl(textWeight), 1); - - textItalic = uiNewCombobox(); - uiComboboxAppend(textItalic, "Normal"); - uiComboboxAppend(textItalic, "Oblique"); - uiComboboxAppend(textItalic, "Italic"); - uiComboboxSetSelected(textItalic, uiDrawTextItalicNormal); - uiBoxAppend(hbox, uiControl(textItalic), 1); - - textSmallCaps = uiNewCheckbox("Small Caps"); - uiBoxAppend(hbox, uiControl(textSmallCaps), 1); - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - textStretch = uiNewCombobox(); - uiComboboxAppend(textStretch, "Ultra Condensed"); - uiComboboxAppend(textStretch, "Extra Condensed"); - uiComboboxAppend(textStretch, "Condensed"); - uiComboboxAppend(textStretch, "Semi Condensed"); - uiComboboxAppend(textStretch, "Normal"); - uiComboboxAppend(textStretch, "Semi Expanded"); - uiComboboxAppend(textStretch, "Expanded"); - uiComboboxAppend(textStretch, "Extra Expanded"); - uiComboboxAppend(textStretch, "Ultra Expanded"); - uiComboboxSetSelected(textStretch, uiDrawTextStretchNormal); - uiBoxAppend(hbox, uiControl(textStretch), 1); - - textWidth = uiNewEntry(); - uiEntrySetText(textWidth, "-1"); - uiBoxAppend(hbox, uiControl(textWidth), 1); - - hbox = newHorizontalBox(); - uiBoxAppend(vbox, uiControl(hbox), 0); - - textApply = uiNewButton("Apply"); - uiButtonOnClicked(textApply, onTextApply, NULL); - uiBoxAppend(hbox, uiControl(textApply), 1); - - addLeading = uiNewCheckbox("Add Leading"); - uiCheckboxSetChecked(addLeading, 1); - uiBoxAppend(hbox, uiControl(addLeading), 0); - - textAreaHandler.Draw = handlerDraw; - textAreaHandler.MouseEvent = handlerMouseEvent; - textAreaHandler.MouseCrossed = handlerMouseCrossed; - textAreaHandler.DragBroken = handlerDragBroken; - textAreaHandler.KeyEvent = handlerKeyEvent; - textArea = uiNewArea(&textAreaHandler); - uiBoxAppend(vbox, uiControl(textArea), 1); - - return page9; -} diff --git a/src/libui_sdl/libui/test/resources.rc b/src/libui_sdl/libui/test/resources.rc deleted file mode 100644 index ebc5d6e6..00000000 --- a/src/libui_sdl/libui/test/resources.rc +++ /dev/null @@ -1,13 +0,0 @@ -// 30 may 2015 - -// this is a UTF-8 file -#pragma code_page(65001) - -// this is the Common Controls 6 manifest -// TODO set up the string values here -// 1 is the value of CREATEPROCESS_MANIFEST_RESOURCE_ID and 24 is the value of RT_MANIFEST; we use it directly to avoid needing to share winapi.h with the tests and examples -#ifndef _UI_STATIC -1 24 "test.manifest" -#else -1 24 "test.static.manifest" -#endif diff --git a/src/libui_sdl/libui/test/spaced.c b/src/libui_sdl/libui/test/spaced.c deleted file mode 100644 index 02db99ae..00000000 --- a/src/libui_sdl/libui/test/spaced.c +++ /dev/null @@ -1,177 +0,0 @@ -// 22 april 2015 -#include "test.h" - -struct thing { - void *ptr; - int type; -}; - -static struct thing *things = NULL; -static size_t len = 0; -static size_t cap = 0; - -#define grow 32 - -static void *append(void *thing, int type) -{ - if (len >= cap) { - cap += grow; - things = (struct thing *) realloc(things, cap * sizeof (struct thing)); - if (things == NULL) - die("reallocating things array in test/spaced.c append()"); - } - things[len].ptr = thing; - things[len].type = type; - len++; - return things[len - 1].ptr; -} - -enum types { - window, - box, - tab, - group, - form, - grid, -}; - -void setSpaced(int spaced) -{ - size_t i; - void *p; - size_t j, n; - - for (i = 0; i < len; i++) { - p = things[i].ptr; - switch (things[i].type) { - case window: - uiWindowSetMargined(uiWindow(p), spaced); - break; - case box: - uiBoxSetPadded(uiBox(p), spaced); - break; - case tab: - n = uiTabNumPages(uiTab(p)); - for (j = 0; j < n; j++) - uiTabSetMargined(uiTab(p), j, spaced); - break; - case group: - uiGroupSetMargined(uiGroup(p), spaced); - break; - case form: - uiFormSetPadded(uiForm(p), spaced); - break; - case grid: - uiGridSetPadded(uiGrid(p), spaced); - break; - } - } -} - -void querySpaced(char out[12]) // more than enough -{ - int m = 0; - int p = 0; - size_t i; - void *pp; - size_t j, n; - - for (i = 0; i < len; i++) { - pp = things[i].ptr; - switch (things[i].type) { - case window: - if (uiWindowMargined(uiWindow(pp))) - m++; - break; - case box: - p = uiBoxPadded(uiBox(pp)); - break; - case tab: - n = uiTabNumPages(uiTab(pp)); - for (j = 0; j < n; j++) - if (uiTabMargined(uiTab(pp), j)) - m++; - break; - case group: - if (uiGroupMargined(uiGroup(pp))) - m++; - break; - // TODO form - // TODO grid - } - } - - out[0] = 'm'; - out[1] = ' '; - out[2] = '0' + m; - out[3] = ' '; - out[4] = 'p'; - out[5] = ' '; - out[6] = '0'; - if (p) - out[6] = '1'; - out[7] = '\0'; -} - -uiWindow *newWindow(const char *title, int width, int height, int hasMenubar) -{ - uiWindow *w; - - w = uiNewWindow(title, width, height, hasMenubar); - append(w, window); - return w; -} - -uiBox *newHorizontalBox(void) -{ - uiBox *b; - - b = (*newhbox)(); - append(b, box); - return b; -} - -uiBox *newVerticalBox(void) -{ - uiBox *b; - - b = (*newvbox)(); - append(b, box); - return b; -} - -uiTab *newTab(void) -{ - uiTab *t; - - t = uiNewTab(); - append(t, tab); - return t; -} - -uiGroup *newGroup(const char *text) -{ - uiGroup *g; - - g = uiNewGroup(text); - append(g, group); - return g; -} - -uiForm *newForm(void) -{ - uiForm *f; - - f = uiNewForm(); - append(f, form); - return f; -} - -uiGrid *newGrid(void) -{ - uiGrid *g; - - g = uiNewGrid(); - append(g, grid); - return g; -} diff --git a/src/libui_sdl/libui/test/test.h b/src/libui_sdl/libui/test/test.h deleted file mode 100644 index 66b1baa7..00000000 --- a/src/libui_sdl/libui/test/test.h +++ /dev/null @@ -1,91 +0,0 @@ -// 22 april 2015 -#include -#include -#include -#include -#include -#include -#include -#include "../ui.h" - -// main.c -extern void die(const char *, ...); -extern uiBox *mainBox; -extern uiTab *mainTab; -extern uiBox *(*newhbox)(void); -extern uiBox *(*newvbox)(void); - -// spaced.c -extern void setSpaced(int); -extern void querySpaced(char[12]); -extern uiWindow *newWindow(const char *title, int width, int height, int hasMenubar); -extern uiBox *newHorizontalBox(void); -extern uiBox *newVerticalBox(void); -extern uiTab *newTab(void); -extern uiGroup *newGroup(const char *); -extern uiForm *newForm(void); -extern uiGrid *newGrid(void); - -// menus.c -extern uiMenuItem *shouldQuitItem; -extern void initMenus(void); - -// page1.c -extern uiBox *page1; -extern void makePage1(uiWindow *); - -// page2.c -extern uiGroup *page2group; -extern uiBox *makePage2(void); - -// page3.c -extern uiBox *makePage3(void); - -// page4.c -extern uiBox *makePage4(void); - -// page5.c -extern uiBox *makePage5(uiWindow *); - -// page6.c -extern uiBox *makePage6(void); - -// drawtests.c -extern void runDrawTest(int, uiAreaDrawParams *); -extern void populateComboboxWithTests(uiCombobox *); - -// page7.c -extern uiBox *makePage7(void); - -// page7a.c -extern uiGroup *makePage7a(void); - -// page7b.c -extern uiGroup *makePage7b(void); - -// page7c.c -extern uiGroup *makePage7c(void); - -// page8.c -extern uiBox *makePage8(void); - -// page9.c -extern uiBox *makePage9(void); - -// page10.c -extern uiBox *makePage10(void); - -// page11.c -extern uiBox *makePage11(void); - -// page12.c -extern uiBox *makePage12(void); - -// page13.c -extern uiBox *makePage13(void); - -// page14.c -extern uiTab *makePage14(void); - -// page15.c -extern uiBox *makePage15(uiWindow *); diff --git a/src/libui_sdl/libui/test/test.manifest b/src/libui_sdl/libui/test/test.manifest deleted file mode 100644 index 41e7c9c5..00000000 --- a/src/libui_sdl/libui/test/test.manifest +++ /dev/null @@ -1,20 +0,0 @@ - - - -Your application description here. - - - - - - - - - - - diff --git a/src/libui_sdl/libui/test/test.static.manifest b/src/libui_sdl/libui/test/test.static.manifest deleted file mode 100644 index d8e83a83..00000000 --- a/src/libui_sdl/libui/test/test.static.manifest +++ /dev/null @@ -1,32 +0,0 @@ - - - -Your application description here. - - - - - - - - - - - - - - - - diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h deleted file mode 100644 index 03aef5de..00000000 --- a/src/libui_sdl/libui/ui.h +++ /dev/null @@ -1,763 +0,0 @@ -// 6 april 2015 - -// TODO add a uiVerifyControlType() function that can be used by control implementations to verify controls - -#ifndef __LIBUI_UI_H__ -#define __LIBUI_UI_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// this macro is generated by cmake -#ifdef libui_EXPORTS -#ifdef _WIN32 -#define _UI_EXTERN __declspec(dllexport) extern -#else -#define _UI_EXTERN __attribute__((visibility("default"))) extern -#endif -#else -// TODO add __declspec(dllimport) on windows, but only if not static -#define _UI_EXTERN extern -#endif - -// C++ is really really really really really really dumb about enums, so screw that and just make them anonymous -// This has the advantage of being ABI-able should we ever need an ABI... -#define _UI_ENUM(s) typedef unsigned int s; enum - -// This constant is provided because M_PI is nonstandard. -// This comes from Go's math.Pi, which in turn comes from http://oeis.org/A000796. -#define uiPi 3.14159265358979323846264338327950288419716939937510582097494459 - -// TODO uiBool? - -typedef struct uiInitOptions uiInitOptions; - -struct uiInitOptions { - size_t Size; -}; - -_UI_EXTERN const char *uiInit(uiInitOptions *options); -_UI_EXTERN void uiUninit(void); -_UI_EXTERN void uiFreeInitError(const char *err); - -_UI_EXTERN void uiMain(void); -_UI_EXTERN void uiMainSteps(void); -_UI_EXTERN int uiMainStep(int wait); -_UI_EXTERN void uiQuit(void); - -_UI_EXTERN void uiQueueMain(void (*f)(void *data), void *data); - -_UI_EXTERN void uiOnShouldQuit(int (*f)(void *data), void *data); - -_UI_EXTERN void uiFreeText(char *text); - -typedef struct uiControl uiControl; - -struct uiControl { - uint32_t Signature; - uint32_t OSSignature; - uint32_t TypeSignature; - void (*Destroy)(uiControl *); - uintptr_t (*Handle)(uiControl *); - uiControl *(*Parent)(uiControl *); - void (*SetParent)(uiControl *, uiControl *); - int (*Toplevel)(uiControl *); - int (*Visible)(uiControl *); - void (*Show)(uiControl *); - void (*Hide)(uiControl *); - int (*Enabled)(uiControl *); - void (*Enable)(uiControl *); - void (*Disable)(uiControl *); - void (*SetFocus)(uiControl *); - void (*SetMinSize)(uiControl*, int, int); - - int MinWidth, MinHeight; - - void* UserData; -}; -// TOOD add argument names to all arguments -#define uiControl(this) ((uiControl *) (this)) -_UI_EXTERN void uiControlDestroy(uiControl *); -_UI_EXTERN uintptr_t uiControlHandle(uiControl *); -_UI_EXTERN uiControl *uiControlParent(uiControl *); -_UI_EXTERN void uiControlSetParent(uiControl *, uiControl *); -_UI_EXTERN int uiControlToplevel(uiControl *); -_UI_EXTERN int uiControlVisible(uiControl *); -_UI_EXTERN void uiControlShow(uiControl *); -_UI_EXTERN void uiControlHide(uiControl *); -_UI_EXTERN int uiControlEnabled(uiControl *); -_UI_EXTERN void uiControlEnable(uiControl *); -_UI_EXTERN void uiControlDisable(uiControl *); -_UI_EXTERN void uiControlSetFocus(uiControl *); -_UI_EXTERN void uiControlSetMinSize(uiControl *, int w, int h); // -1 = no minimum - -_UI_EXTERN uiControl *uiAllocControl(size_t n, uint32_t OSsig, uint32_t typesig, const char *typenamestr); -_UI_EXTERN void uiFreeControl(uiControl *); - -// TODO make sure all controls have these -_UI_EXTERN void uiControlVerifySetParent(uiControl *, uiControl *); -_UI_EXTERN int uiControlEnabledToUser(uiControl *); - -_UI_EXTERN void uiUserBugCannotSetParentOnToplevel(const char *type); - -typedef struct uiWindow uiWindow; -#define uiWindow(this) ((uiWindow *) (this)) -_UI_EXTERN char *uiWindowTitle(uiWindow *w); -_UI_EXTERN void uiWindowSetTitle(uiWindow *w, const char *title); -_UI_EXTERN void uiWindowPosition(uiWindow *w, int *x, int *y); -_UI_EXTERN void uiWindowSetPosition(uiWindow *w, int x, int y); -_UI_EXTERN void uiWindowContentSize(uiWindow *w, int *width, int *height); -_UI_EXTERN void uiWindowSetContentSize(uiWindow *w, int width, int height); -_UI_EXTERN int uiWindowMinimized(uiWindow *w); -_UI_EXTERN void uiWindowSetMinimized(uiWindow *w, int minimized); -_UI_EXTERN int uiWindowMaximized(uiWindow *w); -_UI_EXTERN void uiWindowSetMaximized(uiWindow *w, int maximized); -_UI_EXTERN int uiWindowFullscreen(uiWindow *w); -_UI_EXTERN void uiWindowSetFullscreen(uiWindow *w, int fullscreen); -_UI_EXTERN int uiWindowBorderless(uiWindow *w); -_UI_EXTERN void uiWindowSetBorderless(uiWindow *w, int borderless); -_UI_EXTERN void uiWindowSetChild(uiWindow *w, uiControl *child); -_UI_EXTERN int uiWindowMargined(uiWindow *w); -_UI_EXTERN void uiWindowSetMargined(uiWindow *w, int margined); -_UI_EXTERN void uiWindowSetDropTarget(uiWindow* w, int drop); -_UI_EXTERN uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, int hasMenubar, int resizable); - -_UI_EXTERN void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data); -_UI_EXTERN void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *w, void *data), void *data); -_UI_EXTERN void uiWindowOnDropFile(uiWindow *w, void (*f)(uiWindow *w, char *file, void *data), void *data); -_UI_EXTERN void uiWindowOnGetFocus(uiWindow *w, void (*f)(uiWindow *w, void *data), void *data); -_UI_EXTERN void uiWindowOnLoseFocus(uiWindow *w, void (*f)(uiWindow *w, void *data), void *data); - -typedef struct uiButton uiButton; -#define uiButton(this) ((uiButton *) (this)) -_UI_EXTERN char *uiButtonText(uiButton *b); -_UI_EXTERN void uiButtonSetText(uiButton *b, const char *text); -_UI_EXTERN void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *b, void *data), void *data); -_UI_EXTERN uiButton *uiNewButton(const char *text); - -typedef struct uiBox uiBox; -#define uiBox(this) ((uiBox *) (this)) -_UI_EXTERN void uiBoxAppend(uiBox *b, uiControl *child, int stretchy); -_UI_EXTERN void uiBoxDelete(uiBox *b, int index); -_UI_EXTERN int uiBoxPadded(uiBox *b); -_UI_EXTERN void uiBoxSetPadded(uiBox *b, int padded); -_UI_EXTERN uiBox *uiNewHorizontalBox(void); -_UI_EXTERN uiBox *uiNewVerticalBox(void); - -typedef struct uiCheckbox uiCheckbox; -#define uiCheckbox(this) ((uiCheckbox *) (this)) -_UI_EXTERN char *uiCheckboxText(uiCheckbox *c); -_UI_EXTERN void uiCheckboxSetText(uiCheckbox *c, const char *text); -_UI_EXTERN void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *c, void *data), void *data); -_UI_EXTERN int uiCheckboxChecked(uiCheckbox *c); -_UI_EXTERN void uiCheckboxSetChecked(uiCheckbox *c, int checked); -_UI_EXTERN uiCheckbox *uiNewCheckbox(const char *text); - -typedef struct uiEntry uiEntry; -#define uiEntry(this) ((uiEntry *) (this)) -_UI_EXTERN char *uiEntryText(uiEntry *e); -_UI_EXTERN void uiEntrySetText(uiEntry *e, const char *text); -_UI_EXTERN void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *e, void *data), void *data); -_UI_EXTERN int uiEntryReadOnly(uiEntry *e); -_UI_EXTERN void uiEntrySetReadOnly(uiEntry *e, int readonly); -_UI_EXTERN uiEntry *uiNewEntry(void); -_UI_EXTERN uiEntry *uiNewPasswordEntry(void); -_UI_EXTERN uiEntry *uiNewSearchEntry(void); - -typedef struct uiLabel uiLabel; -#define uiLabel(this) ((uiLabel *) (this)) -_UI_EXTERN char *uiLabelText(uiLabel *l); -_UI_EXTERN void uiLabelSetText(uiLabel *l, const char *text); -_UI_EXTERN uiLabel *uiNewLabel(const char *text); - -typedef struct uiTab uiTab; -#define uiTab(this) ((uiTab *) (this)) -_UI_EXTERN void uiTabAppend(uiTab *t, const char *name, uiControl *c); -_UI_EXTERN void uiTabInsertAt(uiTab *t, const char *name, int before, uiControl *c); -_UI_EXTERN void uiTabDelete(uiTab *t, int index); -_UI_EXTERN int uiTabNumPages(uiTab *t); -_UI_EXTERN int uiTabMargined(uiTab *t, int page); -_UI_EXTERN void uiTabSetMargined(uiTab *t, int page, int margined); -_UI_EXTERN uiTab *uiNewTab(void); - -typedef struct uiGroup uiGroup; -#define uiGroup(this) ((uiGroup *) (this)) -_UI_EXTERN char *uiGroupTitle(uiGroup *g); -_UI_EXTERN void uiGroupSetTitle(uiGroup *g, const char *title); -_UI_EXTERN void uiGroupSetChild(uiGroup *g, uiControl *c); -_UI_EXTERN int uiGroupMargined(uiGroup *g); -_UI_EXTERN void uiGroupSetMargined(uiGroup *g, int margined); -_UI_EXTERN uiGroup *uiNewGroup(const char *title); - -// spinbox/slider rules: -// setting value outside of range will automatically clamp -// initial value is minimum -// complaint if min >= max? - -typedef struct uiSpinbox uiSpinbox; -#define uiSpinbox(this) ((uiSpinbox *) (this)) -_UI_EXTERN int uiSpinboxValue(uiSpinbox *s); -_UI_EXTERN void uiSpinboxSetValue(uiSpinbox *s, int value); -_UI_EXTERN void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *s, void *data), void *data); -_UI_EXTERN uiSpinbox *uiNewSpinbox(int min, int max); - -typedef struct uiSlider uiSlider; -#define uiSlider(this) ((uiSlider *) (this)) -_UI_EXTERN int uiSliderValue(uiSlider *s); -_UI_EXTERN void uiSliderSetValue(uiSlider *s, int value); -_UI_EXTERN void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *s, void *data), void *data); -_UI_EXTERN uiSlider *uiNewSlider(int min, int max); - -typedef struct uiProgressBar uiProgressBar; -#define uiProgressBar(this) ((uiProgressBar *) (this)) -_UI_EXTERN int uiProgressBarValue(uiProgressBar *p); -_UI_EXTERN void uiProgressBarSetValue(uiProgressBar *p, int n); -_UI_EXTERN uiProgressBar *uiNewProgressBar(void); - -typedef struct uiSeparator uiSeparator; -#define uiSeparator(this) ((uiSeparator *) (this)) -_UI_EXTERN uiSeparator *uiNewHorizontalSeparator(void); -_UI_EXTERN uiSeparator *uiNewVerticalSeparator(void); - -typedef struct uiCombobox uiCombobox; -#define uiCombobox(this) ((uiCombobox *) (this)) -_UI_EXTERN void uiComboboxAppend(uiCombobox *c, const char *text); -_UI_EXTERN int uiComboboxSelected(uiCombobox *c); -_UI_EXTERN void uiComboboxSetSelected(uiCombobox *c, int n); -_UI_EXTERN void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data); -_UI_EXTERN uiCombobox *uiNewCombobox(void); - -typedef struct uiEditableCombobox uiEditableCombobox; -#define uiEditableCombobox(this) ((uiEditableCombobox *) (this)) -_UI_EXTERN void uiEditableComboboxAppend(uiEditableCombobox *c, const char *text); -_UI_EXTERN char *uiEditableComboboxText(uiEditableCombobox *c); -_UI_EXTERN void uiEditableComboboxSetText(uiEditableCombobox *c, const char *text); -// TODO what do we call a function that sets the currently selected item and fills the text field with it? editable comboboxes have no consistent concept of selected item -_UI_EXTERN void uiEditableComboboxOnChanged(uiEditableCombobox *c, void (*f)(uiEditableCombobox *c, void *data), void *data); -_UI_EXTERN uiEditableCombobox *uiNewEditableCombobox(void); - -typedef struct uiRadioButtons uiRadioButtons; -#define uiRadioButtons(this) ((uiRadioButtons *) (this)) -_UI_EXTERN void uiRadioButtonsAppend(uiRadioButtons *r, const char *text); -_UI_EXTERN int uiRadioButtonsSelected(uiRadioButtons *r); -_UI_EXTERN void uiRadioButtonsSetSelected(uiRadioButtons *r, int n); -_UI_EXTERN void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data); -_UI_EXTERN uiRadioButtons *uiNewRadioButtons(void); - -typedef struct uiDateTimePicker uiDateTimePicker; -#define uiDateTimePicker(this) ((uiDateTimePicker *) (this)) -_UI_EXTERN uiDateTimePicker *uiNewDateTimePicker(void); -_UI_EXTERN uiDateTimePicker *uiNewDatePicker(void); -_UI_EXTERN uiDateTimePicker *uiNewTimePicker(void); - -// TODO provide a facility for entering tab stops? -typedef struct uiMultilineEntry uiMultilineEntry; -#define uiMultilineEntry(this) ((uiMultilineEntry *) (this)) -_UI_EXTERN char *uiMultilineEntryText(uiMultilineEntry *e); -_UI_EXTERN void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text); -_UI_EXTERN void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text); -_UI_EXTERN void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *e, void *data), void *data); -_UI_EXTERN int uiMultilineEntryReadOnly(uiMultilineEntry *e); -_UI_EXTERN void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly); -_UI_EXTERN uiMultilineEntry *uiNewMultilineEntry(void); -_UI_EXTERN uiMultilineEntry *uiNewNonWrappingMultilineEntry(void); - -typedef struct uiMenuItem uiMenuItem; -#define uiMenuItem(this) ((uiMenuItem *) (this)) -_UI_EXTERN void uiMenuItemEnable(uiMenuItem *m); -_UI_EXTERN void uiMenuItemDisable(uiMenuItem *m); -_UI_EXTERN void uiMenuItemOnClicked(uiMenuItem *m, void (*f)(uiMenuItem *sender, uiWindow *window, void *data), void *data); -_UI_EXTERN int uiMenuItemChecked(uiMenuItem *m); -_UI_EXTERN void uiMenuItemSetChecked(uiMenuItem *m, int checked); - -typedef struct uiMenu uiMenu; -#define uiMenu(this) ((uiMenu *) (this)) -_UI_EXTERN uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name); -_UI_EXTERN uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name); -_UI_EXTERN uiMenuItem *uiMenuAppendQuitItem(uiMenu *m); -_UI_EXTERN uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m); -_UI_EXTERN uiMenuItem *uiMenuAppendAboutItem(uiMenu *m); -_UI_EXTERN uiMenuItem *uiMenuAppendSubmenu(uiMenu *m, uiMenu* child); -_UI_EXTERN void uiMenuAppendSeparator(uiMenu *m); -_UI_EXTERN uiMenu *uiNewMenu(const char *name); - -_UI_EXTERN char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath); -_UI_EXTERN char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath); -_UI_EXTERN void uiMsgBox(uiWindow *parent, const char *title, const char *description); -_UI_EXTERN void uiMsgBoxError(uiWindow *parent, const char *title, const char *description); - -typedef struct uiArea uiArea; -typedef struct uiAreaHandler uiAreaHandler; -typedef struct uiAreaDrawParams uiAreaDrawParams; -typedef struct uiAreaMouseEvent uiAreaMouseEvent; -typedef struct uiAreaKeyEvent uiAreaKeyEvent; - -typedef struct uiDrawContext uiDrawContext; - -// TO CONSIDER: the uiAreaHandler param there seems useless -// (might use individual callbacks instead of handler struct?) -struct uiAreaHandler { - void (*Draw)(uiAreaHandler *, uiArea *, uiAreaDrawParams *); - // TODO document that resizes cause a full redraw for non-scrolling areas; implementation-defined for scrolling areas - void (*MouseEvent)(uiAreaHandler *, uiArea *, uiAreaMouseEvent *); - // TODO document that on first show if the mouse is already in the uiArea then one gets sent with left=0 - // TODO what about when the area is hidden and then shown again? - void (*MouseCrossed)(uiAreaHandler *, uiArea *, int left); - void (*DragBroken)(uiAreaHandler *, uiArea *); - int (*KeyEvent)(uiAreaHandler *, uiArea *, uiAreaKeyEvent *); - void (*Resize)(uiAreaHandler *, uiArea *, int, int); -}; - -// TODO RTL layouts? -// TODO reconcile edge and corner naming -_UI_ENUM(uiWindowResizeEdge) { - uiWindowResizeEdgeLeft, - uiWindowResizeEdgeTop, - uiWindowResizeEdgeRight, - uiWindowResizeEdgeBottom, - uiWindowResizeEdgeTopLeft, - uiWindowResizeEdgeTopRight, - uiWindowResizeEdgeBottomLeft, - uiWindowResizeEdgeBottomRight, - // TODO have one for keyboard resizes? - // TODO GDK doesn't seem to have any others, including for keyboards... - // TODO way to bring up the system menu instead? -}; - -#define uiGLVersion(major, minor) ((major) | ((minor)<<16)) -#define uiGLVerMajor(ver) ((ver) & 0xFFFF) -#define uiGLVerMinor(ver) ((ver) >> 16) - -#define uiArea(this) ((uiArea *) (this)) -// TODO give a better name -// TODO document the types of width and height -_UI_EXTERN void uiAreaSetSize(uiArea *a, int width, int height); -// TODO uiAreaQueueRedraw() -_UI_EXTERN void uiAreaQueueRedrawAll(uiArea *a); -_UI_EXTERN void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height); -// TODO document these can only be called within Mouse() handlers -// TODO should these be allowed on scrolling areas? -// TODO decide which mouse events should be accepted; Down is the only one guaranteed to work right now -// TODO what happens to events after calling this up to and including the next mouse up? -// TODO release capture? -_UI_EXTERN void uiAreaBeginUserWindowMove(uiArea *a); -_UI_EXTERN void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge); -_UI_EXTERN void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b); -_UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah); -_UI_EXTERN uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions); -_UI_EXTERN uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height); - -struct uiAreaDrawParams { - uiDrawContext *Context; - - // TODO document that this is only defined for nonscrolling areas - double AreaWidth; - double AreaHeight; - - double ClipX; - double ClipY; - double ClipWidth; - double ClipHeight; -}; - -typedef struct uiDrawPath uiDrawPath; -typedef struct uiDrawBrush uiDrawBrush; -typedef struct uiDrawStrokeParams uiDrawStrokeParams; -typedef struct uiDrawMatrix uiDrawMatrix; - -typedef struct uiDrawBrushGradientStop uiDrawBrushGradientStop; - -typedef struct uiDrawBitmap uiDrawBitmap; - -_UI_ENUM(uiDrawBrushType) { - uiDrawBrushTypeSolid, - uiDrawBrushTypeLinearGradient, - uiDrawBrushTypeRadialGradient, - uiDrawBrushTypeImage, -}; - -_UI_ENUM(uiDrawLineCap) { - uiDrawLineCapFlat, - uiDrawLineCapRound, - uiDrawLineCapSquare, -}; - -_UI_ENUM(uiDrawLineJoin) { - uiDrawLineJoinMiter, - uiDrawLineJoinRound, - uiDrawLineJoinBevel, -}; - -// this is the default for botoh cairo and Direct2D (in the latter case, from the C++ helper functions) -// Core Graphics doesn't explicitly specify a default, but NSBezierPath allows you to choose one, and this is the initial value -// so we're good to use it too! -#define uiDrawDefaultMiterLimit 10.0 - -_UI_ENUM(uiDrawFillMode) { - uiDrawFillModeWinding, - uiDrawFillModeAlternate, -}; - -struct uiDrawMatrix { - double M11; - double M12; - double M21; - double M22; - double M31; - double M32; -}; - -struct uiDrawBrush { - uiDrawBrushType Type; - - // solid brushes - double R; - double G; - double B; - double A; - - // gradient brushes - double X0; // linear: start X, radial: start X - double Y0; // linear: start Y, radial: start Y - double X1; // linear: end X, radial: outer circle center X - double Y1; // linear: end Y, radial: outer circle center Y - double OuterRadius; // radial gradients only - uiDrawBrushGradientStop *Stops; - size_t NumStops; - // TODO extend mode - // cairo: none, repeat, reflect, pad; no individual control - // Direct2D: repeat, reflect, pad; no individual control - // Core Graphics: none, pad; before and after individually - // TODO cairo documentation is inconsistent about pad - - // TODO images - - // TODO transforms -}; - -struct uiDrawBrushGradientStop { - double Pos; - double R; - double G; - double B; - double A; -}; - -struct uiDrawStrokeParams { - uiDrawLineCap Cap; - uiDrawLineJoin Join; - // TODO what if this is 0? on windows there will be a crash with dashing - double Thickness; - double MiterLimit; - double *Dashes; - // TOOD what if this is 1 on Direct2D? - // TODO what if a dash is 0 on Cairo or Quartz? - size_t NumDashes; - double DashPhase; -}; - -struct uiRect { - int X; - int Y; - int Width; - int Height; -}; - -typedef struct uiRect uiRect; - -_UI_EXTERN uiDrawPath *uiDrawNewPath(uiDrawFillMode fillMode); -_UI_EXTERN void uiDrawFreePath(uiDrawPath *p); - -_UI_EXTERN void uiDrawPathNewFigure(uiDrawPath *p, double x, double y); -_UI_EXTERN void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative); -_UI_EXTERN void uiDrawPathLineTo(uiDrawPath *p, double x, double y); -// notes: angles are both relative to 0 and go counterclockwise -// TODO is the initial line segment on cairo and OS X a proper join? -// TODO what if sweep < 0? -_UI_EXTERN void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative); -_UI_EXTERN void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY); -// TODO quadratic bezier -_UI_EXTERN void uiDrawPathCloseFigure(uiDrawPath *p); - -// TODO effect of these when a figure is already started -_UI_EXTERN void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height); - -_UI_EXTERN void uiDrawPathEnd(uiDrawPath *p); - -_UI_EXTERN void uiDrawStroke(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b, uiDrawStrokeParams *p); -_UI_EXTERN void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b); - -// TODO primitives: -// - rounded rectangles -// - elliptical arcs -// - quadratic bezier curves - -_UI_EXTERN void uiDrawMatrixSetIdentity(uiDrawMatrix *m); -_UI_EXTERN void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y); -_UI_EXTERN void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y); -_UI_EXTERN void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount); -_UI_EXTERN void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount); -_UI_EXTERN void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src); -_UI_EXTERN int uiDrawMatrixInvertible(uiDrawMatrix *m); -_UI_EXTERN int uiDrawMatrixInvert(uiDrawMatrix *m); -_UI_EXTERN void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y); -_UI_EXTERN void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y); - -_UI_EXTERN void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m); - -// TODO add a uiDrawPathStrokeToFill() or something like that -_UI_EXTERN void uiDrawClip(uiDrawContext *c, uiDrawPath *path); - -_UI_EXTERN void uiDrawSave(uiDrawContext *c); -_UI_EXTERN void uiDrawRestore(uiDrawContext *c); - -// bitmap API -_UI_EXTERN uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha); -_UI_EXTERN void uiDrawBitmapUpdate(uiDrawBitmap* bmp, const void* data); -_UI_EXTERN void uiDrawBitmapDraw(uiDrawContext* c, uiDrawBitmap* bmp, uiRect* srcrect, uiRect* dstrect, int filter); -_UI_EXTERN void uiDrawFreeBitmap(uiDrawBitmap* bmp); - -// TODO manage the use of Text, Font, and TextFont, and of the uiDrawText prefix in general - -///// TODO reconsider this -typedef struct uiDrawFontFamilies uiDrawFontFamilies; - -_UI_EXTERN uiDrawFontFamilies *uiDrawListFontFamilies(void); -_UI_EXTERN int uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff); -_UI_EXTERN char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, int n); -_UI_EXTERN void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff); -///// END TODO - -typedef struct uiDrawTextLayout uiDrawTextLayout; -typedef struct uiDrawTextFont uiDrawTextFont; -typedef struct uiDrawTextFontDescriptor uiDrawTextFontDescriptor; -typedef struct uiDrawTextFontMetrics uiDrawTextFontMetrics; - -_UI_ENUM(uiDrawTextWeight) { - uiDrawTextWeightThin, - uiDrawTextWeightUltraLight, - uiDrawTextWeightLight, - uiDrawTextWeightBook, - uiDrawTextWeightNormal, - uiDrawTextWeightMedium, - uiDrawTextWeightSemiBold, - uiDrawTextWeightBold, - uiDrawTextWeightUltraBold, - uiDrawTextWeightHeavy, - uiDrawTextWeightUltraHeavy, -}; - -_UI_ENUM(uiDrawTextItalic) { - uiDrawTextItalicNormal, - uiDrawTextItalicOblique, - uiDrawTextItalicItalic, -}; - -_UI_ENUM(uiDrawTextStretch) { - uiDrawTextStretchUltraCondensed, - uiDrawTextStretchExtraCondensed, - uiDrawTextStretchCondensed, - uiDrawTextStretchSemiCondensed, - uiDrawTextStretchNormal, - uiDrawTextStretchSemiExpanded, - uiDrawTextStretchExpanded, - uiDrawTextStretchExtraExpanded, - uiDrawTextStretchUltraExpanded, -}; - -struct uiDrawTextFontDescriptor { - const char *Family; - double Size; - uiDrawTextWeight Weight; - uiDrawTextItalic Italic; - uiDrawTextStretch Stretch; -}; - -struct uiDrawTextFontMetrics { - double Ascent; - double Descent; - double Leading; - // TODO do these two mean the same across all platforms? - double UnderlinePos; - double UnderlineThickness; -}; - -_UI_EXTERN uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc); -_UI_EXTERN void uiDrawFreeTextFont(uiDrawTextFont *font); -_UI_EXTERN uintptr_t uiDrawTextFontHandle(uiDrawTextFont *font); -_UI_EXTERN void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc); -// TODO make copy with given attributes methods? -// TODO yuck this name -_UI_EXTERN void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics); - -// TODO initial line spacing? and what about leading? -_UI_EXTERN uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width); -_UI_EXTERN void uiDrawFreeTextLayout(uiDrawTextLayout *layout); -// TODO get width -_UI_EXTERN void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width); -_UI_EXTERN void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height); - -// and the attributes that you can set on a text layout -_UI_EXTERN void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar, int endChar, double r, double g, double b, double a); - -_UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout); - - -// OpenGL support - -typedef struct uiGLContext uiGLContext; - -_UI_EXTERN uiGLContext *uiAreaGetGLContext(uiArea* a); -_UI_EXTERN void uiGLMakeContextCurrent(uiGLContext* ctx); -_UI_EXTERN void uiGLBegin(uiGLContext* ctx); -_UI_EXTERN void uiGLEnd(uiGLContext* ctx); -_UI_EXTERN unsigned int uiGLGetVersion(uiGLContext* ctx); -_UI_EXTERN void *uiGLGetProcAddress(const char* proc); -_UI_EXTERN int uiGLGetFramebuffer(uiGLContext* ctx); -_UI_EXTERN float uiGLGetFramebufferScale(uiGLContext* ctx); -_UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx); -_UI_EXTERN void uiGLSetVSync(int sync); - - -_UI_ENUM(uiModifiers) { - uiModifierCtrl = 1 << 0, - uiModifierAlt = 1 << 1, - uiModifierShift = 1 << 2, - uiModifierSuper = 1 << 3, -}; - -// TODO document drag captures -struct uiAreaMouseEvent { - // TODO document what these mean for scrolling areas - double X; - double Y; - - // TODO see draw above - double AreaWidth; - double AreaHeight; - - int Down; - int Up; - - int Count; - - uiModifiers Modifiers; - - uint64_t Held1To64; -}; - -_UI_ENUM(uiExtKey) { - uiExtKeyEscape = 1, - uiExtKeyInsert, // equivalent to "Help" on Apple keyboards - uiExtKeyDelete, - uiExtKeyHome, - uiExtKeyEnd, - uiExtKeyPageUp, - uiExtKeyPageDown, - uiExtKeyUp, - uiExtKeyDown, - uiExtKeyLeft, - uiExtKeyRight, - uiExtKeyF1, // F1..F12 are guaranteed to be consecutive - uiExtKeyF2, - uiExtKeyF3, - uiExtKeyF4, - uiExtKeyF5, - uiExtKeyF6, - uiExtKeyF7, - uiExtKeyF8, - uiExtKeyF9, - uiExtKeyF10, - uiExtKeyF11, - uiExtKeyF12, - uiExtKeyN0, // numpad keys; independent of Num Lock state - uiExtKeyN1, // N0..N9 are guaranteed to be consecutive - uiExtKeyN2, - uiExtKeyN3, - uiExtKeyN4, - uiExtKeyN5, - uiExtKeyN6, - uiExtKeyN7, - uiExtKeyN8, - uiExtKeyN9, - uiExtKeyNDot, - uiExtKeyNEnter, - uiExtKeyNAdd, - uiExtKeyNSubtract, - uiExtKeyNMultiply, - uiExtKeyNDivide, -}; - -struct uiAreaKeyEvent { - char Key; - uiExtKey ExtKey; - uiModifiers Modifier; - - uiModifiers Modifiers; - - // additional things - int Scancode; // bit0-7: scancode, bit8: ext flag - - int Up; - int Repeat; -}; - -typedef struct uiFontButton uiFontButton; -#define uiFontButton(this) ((uiFontButton *) (this)) -// TODO document this returns a new font -_UI_EXTERN uiDrawTextFont *uiFontButtonFont(uiFontButton *b); -// TOOD SetFont, mechanics -_UI_EXTERN void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data); -_UI_EXTERN uiFontButton *uiNewFontButton(void); - -typedef struct uiColorButton uiColorButton; -#define uiColorButton(this) ((uiColorButton *) (this)) -_UI_EXTERN void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a); -_UI_EXTERN void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a); -_UI_EXTERN void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data); -_UI_EXTERN uiColorButton *uiNewColorButton(void); - -typedef struct uiForm uiForm; -#define uiForm(this) ((uiForm *) (this)) -_UI_EXTERN void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy); -_UI_EXTERN void uiFormDelete(uiForm *f, int index); -_UI_EXTERN int uiFormPadded(uiForm *f); -_UI_EXTERN void uiFormSetPadded(uiForm *f, int padded); -_UI_EXTERN uiForm *uiNewForm(void); - -_UI_ENUM(uiAlign) { - uiAlignFill, - uiAlignStart, - uiAlignCenter, - uiAlignEnd, -}; - -_UI_ENUM(uiAt) { - uiAtLeading, - uiAtTop, - uiAtTrailing, - uiAtBottom, -}; - -typedef struct uiGrid uiGrid; -#define uiGrid(this) ((uiGrid *) (this)) -_UI_EXTERN void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign); -_UI_EXTERN void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign); -_UI_EXTERN int uiGridPadded(uiGrid *g); -_UI_EXTERN void uiGridSetPadded(uiGrid *g, int padded); -_UI_EXTERN uiGrid *uiNewGrid(void); - - -// misc. - -_UI_EXTERN char* uiKeyName(int scancode); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libui_sdl/libui/ui_darwin.h b/src/libui_sdl/libui/ui_darwin.h deleted file mode 100644 index c9c6ad54..00000000 --- a/src/libui_sdl/libui/ui_darwin.h +++ /dev/null @@ -1,224 +0,0 @@ -// 7 april 2015 - -/* -This file assumes that you have imported and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls on Mac OS X. -*/ - -#ifndef __LIBUI_UI_DARWIN_H__ -#define __LIBUI_UI_DARWIN_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct uiDarwinControl uiDarwinControl; -struct uiDarwinControl { - uiControl c; - uiControl *parent; - BOOL enabled; - BOOL visible; - void (*SyncEnableState)(uiDarwinControl *, int); - void (*SetSuperview)(uiDarwinControl *, NSView *); - BOOL (*HugsTrailingEdge)(uiDarwinControl *); - BOOL (*HugsBottom)(uiDarwinControl *); - void (*ChildEdgeHuggingChanged)(uiDarwinControl *); - NSLayoutPriority (*HuggingPriority)(uiDarwinControl *, NSLayoutConstraintOrientation); - void (*SetHuggingPriority)(uiDarwinControl *, NSLayoutPriority, NSLayoutConstraintOrientation); - void (*ChildVisibilityChanged)(uiDarwinControl *); -}; -#define uiDarwinControl(this) ((uiDarwinControl *) (this)) -// TODO document -_UI_EXTERN void uiDarwinControlSyncEnableState(uiDarwinControl *, int); -_UI_EXTERN void uiDarwinControlSetSuperview(uiDarwinControl *, NSView *); -_UI_EXTERN BOOL uiDarwinControlHugsTrailingEdge(uiDarwinControl *); -_UI_EXTERN BOOL uiDarwinControlHugsBottom(uiDarwinControl *); -_UI_EXTERN void uiDarwinControlChildEdgeHuggingChanged(uiDarwinControl *); -_UI_EXTERN NSLayoutPriority uiDarwinControlHuggingPriority(uiDarwinControl *, NSLayoutConstraintOrientation); -_UI_EXTERN void uiDarwinControlSetHuggingPriority(uiDarwinControl *, NSLayoutPriority, NSLayoutConstraintOrientation); -_UI_EXTERN void uiDarwinControlChildVisibilityChanged(uiDarwinControl *); - -#define uiDarwinControlDefaultDestroy(type, handlefield) \ - static void type ## Destroy(uiControl *c) \ - { \ - [type(c)->handlefield release]; \ - uiFreeControl(c); \ - } -#define uiDarwinControlDefaultHandle(type, handlefield) \ - static uintptr_t type ## Handle(uiControl *c) \ - { \ - return (uintptr_t) (type(c)->handlefield); \ - } -#define uiDarwinControlDefaultParent(type, handlefield) \ - static uiControl *type ## Parent(uiControl *c) \ - { \ - return uiDarwinControl(c)->parent; \ - } -#define uiDarwinControlDefaultSetParent(type, handlefield) \ - static void type ## SetParent(uiControl *c, uiControl *parent) \ - { \ - uiControlVerifySetParent(c, parent); \ - uiDarwinControl(c)->parent = parent; \ - } -#define uiDarwinControlDefaultToplevel(type, handlefield) \ - static int type ## Toplevel(uiControl *c) \ - { \ - return 0; \ - } -#define uiDarwinControlDefaultVisible(type, handlefield) \ - static int type ## Visible(uiControl *c) \ - { \ - return uiDarwinControl(c)->visible; \ - } -#define uiDarwinControlDefaultShow(type, handlefield) \ - static void type ## Show(uiControl *c) \ - { \ - uiDarwinControl(c)->visible = YES; \ - [type(c)->handlefield setHidden:NO]; \ - uiDarwinNotifyVisibilityChanged(uiDarwinControl(c)); \ - } -#define uiDarwinControlDefaultHide(type, handlefield) \ - static void type ## Hide(uiControl *c) \ - { \ - uiDarwinControl(c)->visible = NO; \ - [type(c)->handlefield setHidden:YES]; \ - uiDarwinNotifyVisibilityChanged(uiDarwinControl(c)); \ - } -#define uiDarwinControlDefaultEnabled(type, handlefield) \ - static int type ## Enabled(uiControl *c) \ - { \ - return uiDarwinControl(c)->enabled; \ - } -#define uiDarwinControlDefaultEnable(type, handlefield) \ - static void type ## Enable(uiControl *c) \ - { \ - uiDarwinControl(c)->enabled = YES; \ - uiDarwinControlSyncEnableState(uiDarwinControl(c), uiControlEnabledToUser(c)); \ - } -#define uiDarwinControlDefaultDisable(type, handlefield) \ - static void type ## Disable(uiControl *c) \ - { \ - uiDarwinControl(c)->enabled = NO; \ - uiDarwinControlSyncEnableState(uiDarwinControl(c), uiControlEnabledToUser(c)); \ - } -#define uiDarwinControlDefaultSyncEnableState(type, handlefield) \ - static void type ## SyncEnableState(uiDarwinControl *c, int enabled) \ - { \ - if (uiDarwinShouldStopSyncEnableState(c, enabled)) \ - return; \ - if ([type(c)->handlefield respondsToSelector:@selector(setEnabled:)]) \ - [((id) (type(c)->handlefield)) setEnabled:enabled]; /* id cast to make compiler happy; thanks mikeash in irc.freenode.net/#macdev */ \ - } -#define uiDarwinControlDefaultSetSuperview(type, handlefield) \ - static void type ## SetSuperview(uiDarwinControl *c, NSView *superview) \ - { \ - [type(c)->handlefield setTranslatesAutoresizingMaskIntoConstraints:NO]; \ - if (superview == nil) \ - [type(c)->handlefield removeFromSuperview]; \ - else \ - [superview addSubview:type(c)->handlefield]; \ - } -#define uiDarwinControlDefaultHugsTrailingEdge(type, handlefield) \ - static BOOL type ## HugsTrailingEdge(uiDarwinControl *c) \ - { \ - return YES; /* always hug by default */ \ - } -#define uiDarwinControlDefaultHugsBottom(type, handlefield) \ - static BOOL type ## HugsBottom(uiDarwinControl *c) \ - { \ - return YES; /* always hug by default */ \ - } -#define uiDarwinControlDefaultChildEdgeHuggingChanged(type, handlefield) \ - static void type ## ChildEdgeHuggingChanged(uiDarwinControl *c) \ - { \ - /* do nothing */ \ - } -#define uiDarwinControlDefaultHuggingPriority(type, handlefield) \ - static NSLayoutPriority type ## HuggingPriority(uiDarwinControl *c, NSLayoutConstraintOrientation orientation) \ - { \ - return [type(c)->handlefield contentHuggingPriorityForOrientation:orientation]; \ - } -#define uiDarwinControlDefaultSetHuggingPriority(type, handlefield) \ - static void type ## SetHuggingPriority(uiDarwinControl *c, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation) \ - { \ - [type(c)->handlefield setContentHuggingPriority:priority forOrientation:orientation]; \ - } -#define uiDarwinControlDefaultChildVisibilityChanged(type, handlefield) \ - static void type ## ChildVisibilityChanged(uiDarwinControl *c) \ - { \ - /* do nothing */ \ - } - -#define uiDarwinControlAllDefaultsExceptDestroy(type, handlefield) \ - uiDarwinControlDefaultHandle(type, handlefield) \ - uiDarwinControlDefaultParent(type, handlefield) \ - uiDarwinControlDefaultSetParent(type, handlefield) \ - uiDarwinControlDefaultToplevel(type, handlefield) \ - uiDarwinControlDefaultVisible(type, handlefield) \ - uiDarwinControlDefaultShow(type, handlefield) \ - uiDarwinControlDefaultHide(type, handlefield) \ - uiDarwinControlDefaultEnabled(type, handlefield) \ - uiDarwinControlDefaultEnable(type, handlefield) \ - uiDarwinControlDefaultDisable(type, handlefield) \ - uiDarwinControlDefaultSyncEnableState(type, handlefield) \ - uiDarwinControlDefaultSetSuperview(type, handlefield) \ - uiDarwinControlDefaultHugsTrailingEdge(type, handlefield) \ - uiDarwinControlDefaultHugsBottom(type, handlefield) \ - uiDarwinControlDefaultChildEdgeHuggingChanged(type, handlefield) \ - uiDarwinControlDefaultHuggingPriority(type, handlefield) \ - uiDarwinControlDefaultSetHuggingPriority(type, handlefield) \ - uiDarwinControlDefaultChildVisibilityChanged(type, handlefield) - -#define uiDarwinControlAllDefaults(type, handlefield) \ - uiDarwinControlDefaultDestroy(type, handlefield) \ - uiDarwinControlAllDefaultsExceptDestroy(type, handlefield) - -// TODO document -#define uiDarwinNewControl(type, var) \ - var = type(uiDarwinAllocControl(sizeof (type), type ## Signature, #type)); \ - uiControl(var)->Destroy = type ## Destroy; \ - uiControl(var)->Handle = type ## Handle; \ - uiControl(var)->Parent = type ## Parent; \ - uiControl(var)->SetParent = type ## SetParent; \ - uiControl(var)->Toplevel = type ## Toplevel; \ - uiControl(var)->Visible = type ## Visible; \ - uiControl(var)->Show = type ## Show; \ - uiControl(var)->Hide = type ## Hide; \ - uiControl(var)->Enabled = type ## Enabled; \ - uiControl(var)->Enable = type ## Enable; \ - uiControl(var)->Disable = type ## Disable; \ - uiDarwinControl(var)->SyncEnableState = type ## SyncEnableState; \ - uiDarwinControl(var)->SetSuperview = type ## SetSuperview; \ - uiDarwinControl(var)->HugsTrailingEdge = type ## HugsTrailingEdge; \ - uiDarwinControl(var)->HugsBottom = type ## HugsBottom; \ - uiDarwinControl(var)->ChildEdgeHuggingChanged = type ## ChildEdgeHuggingChanged; \ - uiDarwinControl(var)->HuggingPriority = type ## HuggingPriority; \ - uiDarwinControl(var)->SetHuggingPriority = type ## SetHuggingPriority; \ - uiDarwinControl(var)->ChildVisibilityChanged = type ## ChildVisibilityChanged; \ - uiDarwinControl(var)->visible = YES; \ - uiDarwinControl(var)->enabled = YES; -// TODO document -_UI_EXTERN uiDarwinControl *uiDarwinAllocControl(size_t n, uint32_t typesig, const char *typenamestr); - -// Use this function as a shorthand for setting control fonts. -_UI_EXTERN void uiDarwinSetControlFont(NSControl *c, NSControlSize size); - -// You can use this function from within your control implementations to return text strings that can be freed with uiFreeText(). -_UI_EXTERN char *uiDarwinNSStringToText(NSString *); - -// TODO document -_UI_EXTERN BOOL uiDarwinShouldStopSyncEnableState(uiDarwinControl *, BOOL); - -// TODO document -_UI_EXTERN void uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl *); -_UI_EXTERN void uiDarwinNotifyVisibilityChanged(uiDarwinControl *c); - -// TODO document -// TODO document that values should not be cached -_UI_EXTERN CGFloat uiDarwinMarginAmount(void *reserved); -_UI_EXTERN CGFloat uiDarwinPaddingAmount(void *reserved); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libui_sdl/libui/ui_unix.h b/src/libui_sdl/libui/ui_unix.h deleted file mode 100644 index fac44bcf..00000000 --- a/src/libui_sdl/libui/ui_unix.h +++ /dev/null @@ -1,154 +0,0 @@ -// 7 april 2015 - -/* -This file assumes that you have included and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls on Unix systems that use GTK+ to provide their UI (currently all except Mac OS X). -*/ - -#ifndef __LIBUI_UI_UNIX_H__ -#define __LIBUI_UI_UNIX_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct uiUnixControl uiUnixControl; -struct uiUnixControl { - uiControl c; - uiControl *parent; - gboolean addedBefore; - void (*SetContainer)(uiUnixControl *, GtkContainer *, gboolean); -}; -#define uiUnixControl(this) ((uiUnixControl *) (this)) -// TODO document -_UI_EXTERN void uiUnixControlSetContainer(uiUnixControl *, GtkContainer *, gboolean); - -#define uiUnixControlDefaultDestroy(type) \ - static void type ## Destroy(uiControl *c) \ - { \ - /* TODO is this safe on floating refs? */ \ - g_object_unref(type(c)->widget); \ - uiFreeControl(c); \ - } -#define uiUnixControlDefaultHandle(type) \ - static uintptr_t type ## Handle(uiControl *c) \ - { \ - return (uintptr_t) (type(c)->widget); \ - } -#define uiUnixControlDefaultParent(type) \ - static uiControl *type ## Parent(uiControl *c) \ - { \ - return uiUnixControl(c)->parent; \ - } -#define uiUnixControlDefaultSetParent(type) \ - static void type ## SetParent(uiControl *c, uiControl *parent) \ - { \ - uiControlVerifySetParent(c, parent); \ - uiUnixControl(c)->parent = parent; \ - } -#define uiUnixControlDefaultToplevel(type) \ - static int type ## Toplevel(uiControl *c) \ - { \ - return 0; \ - } -#define uiUnixControlDefaultVisible(type) \ - static int type ## Visible(uiControl *c) \ - { \ - return gtk_widget_get_visible(type(c)->widget); \ - } -#define uiUnixControlDefaultShow(type) \ - static void type ## Show(uiControl *c) \ - { \ - gtk_widget_show(type(c)->widget); \ - } -#define uiUnixControlDefaultHide(type) \ - static void type ## Hide(uiControl *c) \ - { \ - gtk_widget_hide(type(c)->widget); \ - } -#define uiUnixControlDefaultEnabled(type) \ - static int type ## Enabled(uiControl *c) \ - { \ - return gtk_widget_get_sensitive(type(c)->widget); \ - } -#define uiUnixControlDefaultEnable(type) \ - static void type ## Enable(uiControl *c) \ - { \ - gtk_widget_set_sensitive(type(c)->widget, TRUE); \ - } -#define uiUnixControlDefaultDisable(type) \ - static void type ## Disable(uiControl *c) \ - { \ - gtk_widget_set_sensitive(type(c)->widget, FALSE); \ - } -#define uiUnixControlDefaultSetFocus(type) \ - static void type ## SetFocus(uiControl *c) \ - { \ - gtk_widget_grab_focus(type(c)->widget); \ - } -#define uiUnixControlDefaultSetMinSize(type) \ - static void type ## SetMinSize(uiControl *c, int w, int h) \ - { \ - gtk_widget_set_size_request(type(c)->widget, w, h); \ - } -// TODO this whole addedBefore stuff is a MASSIVE HACK. -#define uiUnixControlDefaultSetContainer(type) \ - static void type ## SetContainer(uiUnixControl *c, GtkContainer *container, gboolean remove) \ - { \ - if (!uiUnixControl(c)->addedBefore) { \ - g_object_ref_sink(type(c)->widget); /* our own reference, which we release in Destroy() */ \ - gtk_widget_show(type(c)->widget); \ - uiUnixControl(c)->addedBefore = TRUE; \ - } \ - if (remove) \ - gtk_container_remove(container, type(c)->widget); \ - else \ - gtk_container_add(container, type(c)->widget); \ - } - -#define uiUnixControlAllDefaultsExceptDestroy(type) \ - uiUnixControlDefaultHandle(type) \ - uiUnixControlDefaultParent(type) \ - uiUnixControlDefaultSetParent(type) \ - uiUnixControlDefaultToplevel(type) \ - uiUnixControlDefaultVisible(type) \ - uiUnixControlDefaultShow(type) \ - uiUnixControlDefaultHide(type) \ - uiUnixControlDefaultEnabled(type) \ - uiUnixControlDefaultEnable(type) \ - uiUnixControlDefaultDisable(type) \ - uiUnixControlDefaultSetFocus(type) \ - uiUnixControlDefaultSetMinSize(type) \ - uiUnixControlDefaultSetContainer(type) - -#define uiUnixControlAllDefaults(type) \ - uiUnixControlDefaultDestroy(type) \ - uiUnixControlAllDefaultsExceptDestroy(type) - -// TODO document -#define uiUnixNewControl(type, var) \ - var = type(uiUnixAllocControl(sizeof (type), type ## Signature, #type)); \ - uiControl(var)->Destroy = type ## Destroy; \ - uiControl(var)->Handle = type ## Handle; \ - uiControl(var)->Parent = type ## Parent; \ - uiControl(var)->SetParent = type ## SetParent; \ - uiControl(var)->Toplevel = type ## Toplevel; \ - uiControl(var)->Visible = type ## Visible; \ - uiControl(var)->Show = type ## Show; \ - uiControl(var)->Hide = type ## Hide; \ - uiControl(var)->Enabled = type ## Enabled; \ - uiControl(var)->Enable = type ## Enable; \ - uiControl(var)->Disable = type ## Disable; \ - uiControl(var)->SetFocus = type ## SetFocus; \ - uiControl(var)->SetMinSize = type ## SetMinSize; \ - uiUnixControl(var)->SetContainer = type ## SetContainer; -// TODO document -_UI_EXTERN uiUnixControl *uiUnixAllocControl(size_t n, uint32_t typesig, const char *typenamestr); - -// uiUnixStrdupText() takes the given string and produces a copy of it suitable for being freed by uiFreeText(). -_UI_EXTERN char *uiUnixStrdupText(const char *); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libui_sdl/libui/ui_windows.h b/src/libui_sdl/libui/ui_windows.h deleted file mode 100644 index 85c3137b..00000000 --- a/src/libui_sdl/libui/ui_windows.h +++ /dev/null @@ -1,280 +0,0 @@ -// 21 april 2016 - -/* -This file assumes that you have included and "ui.h" beforehand. It provides API-specific functions for interfacing with foreign controls in Windows. -*/ - -#ifndef __LIBUI_UI_WINDOWS_H__ -#define __LIBUI_UI_WINDOWS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct uiWindowsSizing uiWindowsSizing; - -typedef struct uiWindowsControl uiWindowsControl; -struct uiWindowsControl { - uiControl c; - uiControl *parent; - // TODO this should be int on both os x and windows - BOOL enabled; - BOOL visible; - void (*SyncEnableState)(uiWindowsControl *, int); - void (*SetParentHWND)(uiWindowsControl *, HWND); - void (*MinimumSize)(uiWindowsControl *, int *, int *); - void (*MinimumSizeChanged)(uiWindowsControl *); - void (*LayoutRect)(uiWindowsControl *c, RECT *r); - void (*AssignControlIDZOrder)(uiWindowsControl *, LONG_PTR *, HWND *); - void (*ChildVisibilityChanged)(uiWindowsControl *); -}; -#define uiWindowsControl(this) ((uiWindowsControl *) (this)) -// TODO document -_UI_EXTERN void uiWindowsControlSyncEnableState(uiWindowsControl *, int); -_UI_EXTERN void uiWindowsControlSetParentHWND(uiWindowsControl *, HWND); -_UI_EXTERN void uiWindowsControlMinimumSize(uiWindowsControl *, int *, int *); -_UI_EXTERN void uiWindowsControlMinimumSizeChanged(uiWindowsControl *); -_UI_EXTERN void uiWindowsControlLayoutRect(uiWindowsControl *, RECT *); -_UI_EXTERN void uiWindowsControlAssignControlIDZOrder(uiWindowsControl *, LONG_PTR *, HWND *); -_UI_EXTERN void uiWindowsControlChildVisibilityChanged(uiWindowsControl *); - -// TODO document -#define uiWindowsControlDefaultDestroy(type) \ - static void type ## Destroy(uiControl *c) \ - { \ - uiWindowsEnsureDestroyWindow(type(c)->hwnd); \ - uiFreeControl(c); \ - } -#define uiWindowsControlDefaultHandle(type) \ - static uintptr_t type ## Handle(uiControl *c) \ - { \ - return (uintptr_t) (type(c)->hwnd); \ - } -#define uiWindowsControlDefaultParent(type) \ - static uiControl *type ## Parent(uiControl *c) \ - { \ - return uiWindowsControl(c)->parent; \ - } -#define uiWindowsControlDefaultSetParent(type) \ - static void type ## SetParent(uiControl *c, uiControl *parent) \ - { \ - uiControlVerifySetParent(c, parent); \ - uiWindowsControl(c)->parent = parent; \ - } -#define uiWindowsControlDefaultToplevel(type) \ - static int type ## Toplevel(uiControl *c) \ - { \ - return 0; \ - } -#define uiWindowsControlDefaultVisible(type) \ - static int type ## Visible(uiControl *c) \ - { \ - return uiWindowsControl(c)->visible; \ - } -#define uiWindowsControlDefaultShow(type) \ - static void type ## Show(uiControl *c) \ - { \ - uiWindowsControl(c)->visible = 1; \ - ShowWindow(type(c)->hwnd, SW_SHOW); \ - uiWindowsControlNotifyVisibilityChanged(uiWindowsControl(c)); \ - } -#define uiWindowsControlDefaultHide(type) \ - static void type ## Hide(uiControl *c) \ - { \ - uiWindowsControl(c)->visible = 0; \ - ShowWindow(type(c)->hwnd, SW_HIDE); \ - uiWindowsControlNotifyVisibilityChanged(uiWindowsControl(c)); \ - } -#define uiWindowsControlDefaultEnabled(type) \ - static int type ## Enabled(uiControl *c) \ - { \ - return uiWindowsControl(c)->enabled; \ - } -#define uiWindowsControlDefaultEnable(type) \ - static void type ## Enable(uiControl *c) \ - { \ - uiWindowsControl(c)->enabled = 1; \ - uiWindowsControlSyncEnableState(uiWindowsControl(c), uiControlEnabledToUser(c)); \ - } -#define uiWindowsControlDefaultDisable(type) \ - static void type ## Disable(uiControl *c) \ - { \ - uiWindowsControl(c)->enabled = 0; \ - uiWindowsControlSyncEnableState(uiWindowsControl(c), uiControlEnabledToUser(c)); \ - } -#define uiWindowsControlDefaultSetFocus(type) \ - static void type ## SetFocus(uiControl *c) \ - { \ - SetFocus(type(c)->hwnd); \ - } -#define uiWindowsControlDefaultSetMinSize(type) \ - static void type ## SetMinSize(uiControl *c, int w, int h) \ - { \ - } -#define uiWindowsControlDefaultSyncEnableState(type) \ - static void type ## SyncEnableState(uiWindowsControl *c, int enabled) \ - { \ - if (uiWindowsShouldStopSyncEnableState(c, enabled)) \ - return; \ - EnableWindow(type(c)->hwnd, enabled); \ - } -#define uiWindowsControlDefaultSetParentHWND(type) \ - static void type ## SetParentHWND(uiWindowsControl *c, HWND parent) \ - { \ - uiWindowsEnsureSetParentHWND(type(c)->hwnd, parent); \ - } -// note that there is no uiWindowsControlDefaultMinimumSize(); you MUST define this yourself! -#define uiWindowsControlDefaultMinimumSizeChanged(type) \ - static void type ## MinimumSizeChanged(uiWindowsControl *c) \ - { \ - if (uiWindowsControlTooSmall(c)) { \ - uiWindowsControlContinueMinimumSizeChanged(c); \ - return; \ - } \ - /* otherwise do nothing; we have no children */ \ - } -#define uiWindowsControlDefaultLayoutRect(type) \ - static void type ## LayoutRect(uiWindowsControl *c, RECT *r) \ - { \ - /* use the window rect as we include the non-client area in the sizes */ \ - uiWindowsEnsureGetWindowRect(type(c)->hwnd, r); \ - } -#define uiWindowsControlDefaultAssignControlIDZOrder(type) \ - static void type ## AssignControlIDZOrder(uiWindowsControl *c, LONG_PTR *controlID, HWND *insertAfter) \ - { \ - uiWindowsEnsureAssignControlIDZOrder(type(c)->hwnd, controlID, insertAfter); \ - } -#define uiWindowsControlDefaultChildVisibilityChanged(type) \ - static void type ## ChildVisibilityChanged(uiWindowsControl *c) \ - { \ - /* do nothing */ \ - } - -#define uiWindowsControlAllDefaultsExceptDestroy(type) \ - uiWindowsControlDefaultHandle(type) \ - uiWindowsControlDefaultParent(type) \ - uiWindowsControlDefaultSetParent(type) \ - uiWindowsControlDefaultToplevel(type) \ - uiWindowsControlDefaultVisible(type) \ - uiWindowsControlDefaultShow(type) \ - uiWindowsControlDefaultHide(type) \ - uiWindowsControlDefaultEnabled(type) \ - uiWindowsControlDefaultEnable(type) \ - uiWindowsControlDefaultDisable(type) \ - uiWindowsControlDefaultSetFocus(type) \ - uiWindowsControlDefaultSetMinSize(type) \ - uiWindowsControlDefaultSyncEnableState(type) \ - uiWindowsControlDefaultSetParentHWND(type) \ - uiWindowsControlDefaultMinimumSizeChanged(type) \ - uiWindowsControlDefaultLayoutRect(type) \ - uiWindowsControlDefaultAssignControlIDZOrder(type) \ - uiWindowsControlDefaultChildVisibilityChanged(type) - -#define uiWindowsControlAllDefaults(type) \ - uiWindowsControlDefaultDestroy(type) \ - uiWindowsControlAllDefaultsExceptDestroy(type) - -// TODO document -#define uiWindowsNewControl(type, var) \ - var = type(uiWindowsAllocControl(sizeof (type), type ## Signature, #type)); \ - uiControl(var)->Destroy = type ## Destroy; \ - uiControl(var)->Handle = type ## Handle; \ - uiControl(var)->Parent = type ## Parent; \ - uiControl(var)->SetParent = type ## SetParent; \ - uiControl(var)->Toplevel = type ## Toplevel; \ - uiControl(var)->Visible = type ## Visible; \ - uiControl(var)->Show = type ## Show; \ - uiControl(var)->Hide = type ## Hide; \ - uiControl(var)->Enabled = type ## Enabled; \ - uiControl(var)->Enable = type ## Enable; \ - uiControl(var)->Disable = type ## Disable; \ - uiControl(var)->SetFocus = type ## SetFocus; \ - uiControl(var)->SetMinSize = type ## SetMinSize; \ - uiWindowsControl(var)->SyncEnableState = type ## SyncEnableState; \ - uiWindowsControl(var)->SetParentHWND = type ## SetParentHWND; \ - uiWindowsControl(var)->MinimumSize = type ## MinimumSize; \ - uiWindowsControl(var)->MinimumSizeChanged = type ## MinimumSizeChanged; \ - uiWindowsControl(var)->LayoutRect = type ## LayoutRect; \ - uiWindowsControl(var)->AssignControlIDZOrder = type ## AssignControlIDZOrder; \ - uiWindowsControl(var)->ChildVisibilityChanged = type ## ChildVisibilityChanged; \ - uiWindowsControl(var)->visible = 1; \ - uiWindowsControl(var)->enabled = 1; -// TODO document -_UI_EXTERN uiWindowsControl *uiWindowsAllocControl(size_t n, uint32_t typesig, const char *typenamestr); - -// TODO document -_UI_EXTERN HWND uiWindowsEnsureCreateControlHWND(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, HINSTANCE hInstance, LPVOID lpParam, BOOL useStandardControlFont); - -// TODO document -_UI_EXTERN void uiWindowsEnsureDestroyWindow(HWND hwnd); - -// TODO document -// TODO document that this should only be used in SetParentHWND() implementations -_UI_EXTERN void uiWindowsEnsureSetParentHWND(HWND hwnd, HWND parent); - -// TODO document -_UI_EXTERN void uiWindowsEnsureAssignControlIDZOrder(HWND hwnd, LONG_PTR *controlID, HWND *insertAfter); - -// TODO document -_UI_EXTERN void uiWindowsEnsureGetClientRect(HWND hwnd, RECT *r); -_UI_EXTERN void uiWindowsEnsureGetWindowRect(HWND hwnd, RECT *r); - -// TODO document -_UI_EXTERN char *uiWindowsWindowText(HWND hwnd); -_UI_EXTERN void uiWindowsSetWindowText(HWND hwnd, const char *text); - -// TODO document -_UI_EXTERN int uiWindowsWindowTextWidth(HWND hwnd); - -// TODO document -// TODO point out this should only be used in a resize cycle -_UI_EXTERN void uiWindowsEnsureMoveWindowDuringResize(HWND hwnd, int x, int y, int width, int height); - -// TODO document -_UI_EXTERN void uiWindowsRegisterWM_COMMANDHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *), uiControl *c); -_UI_EXTERN void uiWindowsUnregisterWM_COMMANDHandler(HWND hwnd); - -// TODO document -_UI_EXTERN void uiWindowsRegisterWM_NOTIFYHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, NMHDR *, LRESULT *), uiControl *c); -_UI_EXTERN void uiWindowsUnregisterWM_NOTIFYHandler(HWND hwnd); - -// TODO document -_UI_EXTERN void uiWindowsRegisterWM_HSCROLLHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *), uiControl *c); -_UI_EXTERN void uiWindowsUnregisterWM_HSCROLLHandler(HWND hwnd); - -// TODO document -_UI_EXTERN void uiWindowsRegisterReceiveWM_WININICHANGE(HWND hwnd); -_UI_EXTERN void uiWindowsUnregisterReceiveWM_WININICHANGE(HWND hwnd); - -// TODO document -typedef struct uiWindowsSizing uiWindowsSizing; -struct uiWindowsSizing { - int BaseX; - int BaseY; - LONG InternalLeading; -}; -_UI_EXTERN void uiWindowsGetSizing(HWND hwnd, uiWindowsSizing *sizing); -_UI_EXTERN void uiWindowsSizingDlgUnitsToPixels(uiWindowsSizing *sizing, int *x, int *y); -_UI_EXTERN void uiWindowsSizingStandardPadding(uiWindowsSizing *sizing, int *x, int *y); - -// TODO document -_UI_EXTERN HWND uiWindowsMakeContainer(uiWindowsControl *c, void (*onResize)(uiWindowsControl *)); - -// TODO document -_UI_EXTERN BOOL uiWindowsControlTooSmall(uiWindowsControl *c); -_UI_EXTERN void uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl *c); - -// TODO document -_UI_EXTERN void uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl *); - -// TODO document -_UI_EXTERN BOOL uiWindowsShouldStopSyncEnableState(uiWindowsControl *c, int enabled); - -// TODO document -_UI_EXTERN void uiWindowsControlNotifyVisibilityChanged(uiWindowsControl *c); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/libui_sdl/libui/unix/CMakeLists.txt b/src/libui_sdl/libui/unix/CMakeLists.txt deleted file mode 100644 index c69081ee..00000000 --- a/src/libui_sdl/libui/unix/CMakeLists.txt +++ /dev/null @@ -1,87 +0,0 @@ -# 3 june 2016 - -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED gtk+-3.0) - -list(APPEND _LIBUI_SOURCES - unix/alloc.c - unix/area.c - unix/box.c - unix/button.c - unix/cellrendererbutton.c - unix/checkbox.c - unix/child.c - unix/colorbutton.c - unix/combobox.c - unix/control.c - unix/datetimepicker.c - unix/debug.c - unix/draw.c - unix/drawmatrix.c - unix/drawpath.c - unix/drawtext.c - unix/editablecombo.c - unix/entry.c - unix/fontbutton.c - unix/form.c - unix/future.c - unix/graphemes.c - unix/grid.c - unix/group.c - unix/image.c - unix/label.c - unix/main.c - unix/menu.c - unix/multilineentry.c - unix/progressbar.c - unix/radiobuttons.c - unix/separator.c - unix/slider.c - unix/spinbox.c - unix/stddialogs.c - unix/tab.c - unix/text.c - unix/util.c - unix/window.c - unix/gl.c -) -set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) - -list(APPEND _LIBUI_INCLUDEDIRS - unix -) -set(_LIBUI_INCLUDEDIRS _LIBUI_INCLUDEDIRS PARENT_SCOPE) - -set(_LIBUINAME libui PARENT_SCOPE) -if(NOT BUILD_SHARED_LIBS) - set(_LIBUINAME libui-temporary PARENT_SCOPE) -endif() -macro(_handle_static) - set_target_properties(${_LIBUINAME} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") - set(_aname $) - set(_oname libui-combined.o) - add_custom_command( - OUTPUT ${_oname} - DEPENDS ${_LIBUINAME} - COMMAND - ld -r --whole-archive ${_aname} -o ${_oname} - COMMAND - objcopy --localize-hidden ${_oname} - COMMENT "Removing hidden symbols") - add_library(libui STATIC ${_oname}) - # otherwise cmake won't know which linker to use - set_target_properties(libui PROPERTIES - LINKER_LANGUAGE C) - set(_aname) - set(_oname) -endmacro() - -# TODO the other variables don't work? -set(_LIBUI_CFLAGS - ${GTK_CFLAGS} -PARENT_SCOPE) - -set(_LIBUI_LIBS - ${GTK_LDFLAGS} m ${CMAKE_DL_LIBS} -PARENT_SCOPE) diff --git a/src/libui_sdl/libui/unix/alloc.c b/src/libui_sdl/libui/unix/alloc.c deleted file mode 100644 index 2561efa6..00000000 --- a/src/libui_sdl/libui/unix/alloc.c +++ /dev/null @@ -1,84 +0,0 @@ -// 7 april 2015 -#include -#include "uipriv_unix.h" - -static GPtrArray *allocations; - -#define UINT8(p) ((uint8_t *) (p)) -#define PVOID(p) ((void *) (p)) -#define EXTRA (sizeof (size_t) + sizeof (const char **)) -#define DATA(p) PVOID(UINT8(p) + EXTRA) -#define BASE(p) PVOID(UINT8(p) - EXTRA) -#define SIZE(p) ((size_t *) (p)) -#define CCHAR(p) ((const char **) (p)) -#define TYPE(p) CCHAR(UINT8(p) + sizeof (size_t)) - -void initAlloc(void) -{ - allocations = g_ptr_array_new(); -} - -static void uninitComplain(gpointer ptr, gpointer data) -{ - char **str = (char **) data; - char *str2; - - if (*str == NULL) - *str = g_strdup_printf(""); - str2 = g_strdup_printf("%s%p %s\n", *str, ptr, *TYPE(ptr)); - g_free(*str); - *str = str2; -} - -void uninitAlloc(void) -{ - char *str = NULL; - - if (allocations->len == 0) { - g_ptr_array_free(allocations, TRUE); - return; - } - g_ptr_array_foreach(allocations, uninitComplain, &str); - userbug("Some data was leaked; either you left a uiControl lying around or there's a bug in libui itself. Leaked data:\n%s", str); - g_free(str); -} - -void *uiAlloc(size_t size, const char *type) -{ - void *out; - - out = g_malloc0(EXTRA + size); - *SIZE(out) = size; - *TYPE(out) = type; - g_ptr_array_add(allocations, out); - return DATA(out); -} - -void *uiRealloc(void *p, size_t new, const char *type) -{ - void *out; - size_t *s; - - if (p == NULL) - return uiAlloc(new, type); - p = BASE(p); - out = g_realloc(p, EXTRA + new); - s = SIZE(out); - if (new <= *s) - memset(((uint8_t *) DATA(out)) + *s, 0, new - *s); - *s = new; - if (g_ptr_array_remove(allocations, p) == FALSE) - implbug("%p not found in allocations array in uiRealloc()", p); - g_ptr_array_add(allocations, out); - return DATA(out); -} - -void uiFree(void *p) -{ - if (p == NULL) - implbug("attempt to uiFree(NULL)"); - p = BASE(p); - g_free(p); - if (g_ptr_array_remove(allocations, p) == FALSE) - implbug("%p not found in allocations array in uiFree()", p); -} diff --git a/src/libui_sdl/libui/unix/area.c b/src/libui_sdl/libui/unix/area.c deleted file mode 100644 index 5734b4b6..00000000 --- a/src/libui_sdl/libui/unix/area.c +++ /dev/null @@ -1,853 +0,0 @@ -// 4 september 2015 -#include "uipriv_unix.h" - -extern GThread* gtkthread; - -// notes: -// - G_DECLARE_DERIVABLE/FINAL_INTERFACE() requires glib 2.44 and that's starting with debian stretch (testing) (GTK+ 3.18) and ubuntu 15.04 (GTK+ 3.14) - debian jessie has 2.42 (GTK+ 3.14) -#define areaWidgetType (areaWidget_get_type()) -#define areaWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), areaWidgetType, areaWidget)) -#define isAreaWidget(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), areaWidgetType)) -#define areaWidgetClass(class) (G_TYPE_CHECK_CLASS_CAST((class), areaWidgetType, areaWidgetClass)) -#define isAreaWidgetClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), areaWidget)) -#define getAreaWidgetClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), areaWidgetType, areaWidgetClass)) - -typedef struct areaWidget areaWidget; -typedef struct areaWidgetClass areaWidgetClass; - -struct areaWidget { - GtkDrawingArea parent_instance; - uiArea *a; - // construct-only parameters aare not set until after the init() function has returned - // we need this particular object available during init(), so put it here instead of in uiArea - // keep a pointer in uiArea for convenience, though - clickCounter cc; -}; - -struct areaWidgetClass { - GtkDrawingAreaClass parent_class; -}; - -typedef struct uiGLContext uiGLContext; - -struct uiArea { - uiUnixControl c; - GtkWidget *widget; // either swidget or areaWidget depending on whether it is scrolling - - GtkWidget *swidget; - GtkContainer *scontainer; - GtkScrolledWindow *sw; - - GtkWidget *areaWidget; - GtkDrawingArea *drawingArea; - areaWidget *area; - - gboolean opengl; - uiGLContext *glContext; - unsigned int* req_versions; - - int bgR, bgG, bgB; - - uiAreaHandler *ah; - - gboolean scrolling; - int scrollWidth; - int scrollHeight; - - // note that this is a pointer; see above - clickCounter *cc; - - // for user window drags - GdkEventButton *dragevent; -}; - -G_DEFINE_TYPE(areaWidget, areaWidget, GTK_TYPE_DRAWING_AREA) - -int boub(GtkWidget* w) { return isAreaWidget(w); } -void baba(GtkWidget* w) -{ - if (!isAreaWidget(w)) return; - - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - if (!a->opengl) return; - - GdkGLContext* oldctx = gdk_gl_context_get_current(); - uiGLMakeContextCurrent(a->glContext); - glFinish(); - gdk_gl_context_make_current(oldctx); -} - -static void areaWidget_init(areaWidget *aw) -{ - // for events - gtk_widget_add_events(GTK_WIDGET(aw), - GDK_POINTER_MOTION_MASK | - GDK_BUTTON_MOTION_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_KEY_PRESS_MASK | - GDK_KEY_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK); - - gtk_widget_set_can_focus(GTK_WIDGET(aw), TRUE); - - clickCounterReset(&(aw->cc)); -} - -static void areaWidget_dispose(GObject *obj) -{ - // remove any draw order that might still be pending - areaWidget *aw = areaWidget(obj); - while (g_idle_remove_by_data(aw->a)); - - G_OBJECT_CLASS(areaWidget_parent_class)->dispose(obj); -} - -static void areaWidget_finalize(GObject *obj) -{ - G_OBJECT_CLASS(areaWidget_parent_class)->finalize(obj); -} - -static void areaWidget_size_allocate(GtkWidget *w, GtkAllocation *allocation) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - - // GtkDrawingArea has a size_allocate() implementation; we need to call it - // this will call gtk_widget_set_allocation() for us - GTK_WIDGET_CLASS(areaWidget_parent_class)->size_allocate(w, allocation); - - if (!a->scrolling) - // we must redraw everything on resize because Windows requires it - gtk_widget_queue_resize(w); - - a->ah->Resize(a->ah, a, allocation->width, allocation->height); -} - -static void loadAreaSize(uiArea *a, double *width, double *height) -{ - GtkAllocation allocation; - - *width = 0; - *height = 0; - // don't provide size information for scrolling areas - if (!a->scrolling) { - gtk_widget_get_allocation(a->areaWidget, &allocation); - // these are already in drawing space coordinates - // for drawing, the size of drawing space has the same value as the widget allocation - // thanks to tristan in irc.gimp.net/#gtk+ - *width = allocation.width; - *height = allocation.height; - } -} - -static gboolean areaWidget_draw(GtkWidget *w, cairo_t *cr) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - uiAreaDrawParams dp; - double clipX0, clipY0, clipX1, clipY1; - - dp.Context = newContext(cr); - - loadAreaSize(a, &(dp.AreaWidth), &(dp.AreaHeight)); - - if (!a->opengl) - { - cairo_clip_extents(cr, &clipX0, &clipY0, &clipX1, &clipY1); - dp.ClipX = clipX0; - dp.ClipY = clipY0; - dp.ClipWidth = clipX1 - clipX0; - dp.ClipHeight = clipY1 - clipY0; - - if (a->bgR != -1) - { - cairo_set_source_rgb(cr, a->bgR/255.0, a->bgG/255.0, a->bgB/255.0); - cairo_paint(cr); - } - - // no need to save or restore the graphics state to reset transformations; GTK+ does that for us - (*(a->ah->Draw))(a->ah, a, &dp); - } - else - { - areaDrawGL(w, &dp, cr, a->glContext); - } - - freeContext(dp.Context); - return FALSE; -} - -// to do this properly for scrolling areas, we need to -// - return the same value for min and nat -// - call gtk_widget_queue_resize() when the size changes -// thanks to Company in irc.gimp.net/#gtk+ -static void areaWidget_get_preferred_height(GtkWidget *w, gint *min, gint *nat) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - - // always chain up just in case - GTK_WIDGET_CLASS(areaWidget_parent_class)->get_preferred_height(w, min, nat); - if (a->scrolling) { - *min = a->scrollHeight; - *nat = a->scrollHeight; - } - - // TODO: min size -} - -static void areaWidget_get_preferred_width(GtkWidget *w, gint *min, gint *nat) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - - // always chain up just in case - GTK_WIDGET_CLASS(areaWidget_parent_class)->get_preferred_width(w, min, nat); - if (a->scrolling) { - *min = a->scrollWidth; - *nat = a->scrollWidth; - } -} - -static guint translateModifiers(guint state, GdkWindow *window) -{ - GdkModifierType statetype; - - // GDK doesn't initialize the modifier flags fully; we have to explicitly tell it to (thanks to Daniel_S and daniels (two different people) in irc.gimp.net/#gtk+) - statetype = state; - gdk_keymap_add_virtual_modifiers( - gdk_keymap_get_for_display(gdk_window_get_display(window)), - &statetype); - return statetype; -} - -static uiModifiers toModifiers(guint state) -{ - uiModifiers m; - - m = 0; - if ((state & GDK_CONTROL_MASK) != 0) - m |= uiModifierCtrl; - if ((state & GDK_META_MASK) != 0) - m |= uiModifierAlt; - if ((state & GDK_MOD1_MASK) != 0) // GTK+ itself requires this to be Alt (just read through gtkaccelgroup.c) - m |= uiModifierAlt; - if ((state & GDK_SHIFT_MASK) != 0) - m |= uiModifierShift; - if ((state & GDK_SUPER_MASK) != 0) - m |= uiModifierSuper; - return m; -} - -// capture on drag is done automatically on GTK+ -static void finishMouseEvent(uiArea *a, uiAreaMouseEvent *me, guint mb, gdouble x, gdouble y, guint state, GdkWindow *window) -{ - // on GTK+, mouse buttons 4-7 are for scrolling; if we got here, that's a mistake - if (mb >= 4 && mb <= 7) - return; - // if the button ID >= 8, continue counting from 4, as in the MouseEvent spec - if (me->Down >= 8) - me->Down -= 4; - if (me->Up >= 8) - me->Up -= 4; - - state = translateModifiers(state, window); - me->Modifiers = toModifiers(state); - - // the mb != # checks exclude the Up/Down button from Held - me->Held1To64 = 0; - if (mb != 1 && (state & GDK_BUTTON1_MASK) != 0) - me->Held1To64 |= 1 << 0; - if (mb != 2 && (state & GDK_BUTTON2_MASK) != 0) - me->Held1To64 |= 1 << 1; - if (mb != 3 && (state & GDK_BUTTON3_MASK) != 0) - me->Held1To64 |= 1 << 2; - // don't check GDK_BUTTON4_MASK or GDK_BUTTON5_MASK because those are for the scrolling buttons mentioned above - // GDK expressly does not support any more buttons in the GdkModifierType; see https://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkdevice-xi2.c#n763 (thanks mclasen in irc.gimp.net/#gtk+) - - // these are already in drawing space coordinates - // the size of drawing space has the same value as the widget allocation - // thanks to tristan in irc.gimp.net/#gtk+ - me->X = x; - me->Y = y; - - loadAreaSize(a, &(me->AreaWidth), &(me->AreaHeight)); - - (*(a->ah->MouseEvent))(a->ah, a, me); -} - -static gboolean areaWidget_button_press_event(GtkWidget *w, GdkEventButton *e) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - gint maxTime, maxDistance; - GtkSettings *settings; - uiAreaMouseEvent me; - - // clicking doesn't automatically transfer keyboard focus; we must do so manually (thanks tristan in irc.gimp.net/#gtk+) - gtk_widget_grab_focus(w); - - // we handle multiple clicks ourselves here, in the same way as we do on Windows - if (e->type != GDK_BUTTON_PRESS) - // ignore GDK's generated double-clicks and beyond - return GDK_EVENT_PROPAGATE; - settings = gtk_widget_get_settings(w); - g_object_get(settings, - "gtk-double-click-time", &maxTime, - "gtk-double-click-distance", &maxDistance, - NULL); - // don't unref settings; it's transfer-none (thanks gregier in irc.gimp.net/#gtk+) - // e->time is guint32 - // e->x and e->y are floating-point; just make them 32-bit integers - // maxTime and maxDistance... are gint, which *should* fit, hopefully... - me.Count = clickCounterClick(a->cc, me.Down, - e->x, e->y, - e->time, maxTime, - maxDistance, maxDistance); - - me.Down = e->button; - me.Up = 0; - - // and set things up for window drags - a->dragevent = e; - finishMouseEvent(a, &me, e->button, e->x, e->y, e->state, e->window); - a->dragevent = NULL; - return GDK_EVENT_PROPAGATE; -} - -static gboolean areaWidget_button_release_event(GtkWidget *w, GdkEventButton *e) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - uiAreaMouseEvent me; - - me.Down = 0; - me.Up = e->button; - me.Count = 0; - finishMouseEvent(a, &me, e->button, e->x, e->y, e->state, e->window); - return GDK_EVENT_PROPAGATE; -} - -static gboolean areaWidget_motion_notify_event(GtkWidget *w, GdkEventMotion *e) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - uiAreaMouseEvent me; - - me.Down = 0; - me.Up = 0; - me.Count = 0; - finishMouseEvent(a, &me, 0, e->x, e->y, e->state, e->window); - return GDK_EVENT_PROPAGATE; -} - -// we want switching away from the control to reset the double-click counter, like with WM_ACTIVATE on Windows -// according to tristan in irc.gimp.net/#gtk+, doing this on both enter-notify-event and leave-notify-event is correct (and it seems to be true in my own tests; plus the events DO get sent when switching programs with the keyboard (just pointing that out)) -static gboolean onCrossing(areaWidget *aw, int left) -{ - uiArea *a = aw->a; - - (*(a->ah->MouseCrossed))(a->ah, a, left); - clickCounterReset(a->cc); - return GDK_EVENT_PROPAGATE; -} - -static gboolean areaWidget_enter_notify_event(GtkWidget *w, GdkEventCrossing *e) -{ - return onCrossing(areaWidget(w), 0); -} - -static gboolean areaWidget_leave_notify_event(GtkWidget *w, GdkEventCrossing *e) -{ - return onCrossing(areaWidget(w), 1); -} - -// note: there is no equivalent to WM_CAPTURECHANGED on GTK+; there literally is no way to break a grab like that (at least not on X11 and Wayland) -// even if I invoke the task switcher and switch processes, the mouse grab will still be held until I let go of all buttons -// therefore, no DragBroken() - -// we use GDK_KEY_Print as a sentinel because libui will never support the print screen key; that key belongs to the user - -static const struct { - guint keyval; - uiExtKey extkey; -} extKeys[] = { - { GDK_KEY_Escape, uiExtKeyEscape }, - { GDK_KEY_Insert, uiExtKeyInsert }, - { GDK_KEY_Delete, uiExtKeyDelete }, - { GDK_KEY_Home, uiExtKeyHome }, - { GDK_KEY_End, uiExtKeyEnd }, - { GDK_KEY_Page_Up, uiExtKeyPageUp }, - { GDK_KEY_Page_Down, uiExtKeyPageDown }, - { GDK_KEY_Up, uiExtKeyUp }, - { GDK_KEY_Down, uiExtKeyDown }, - { GDK_KEY_Left, uiExtKeyLeft }, - { GDK_KEY_Right, uiExtKeyRight }, - { GDK_KEY_F1, uiExtKeyF1 }, - { GDK_KEY_F2, uiExtKeyF2 }, - { GDK_KEY_F3, uiExtKeyF3 }, - { GDK_KEY_F4, uiExtKeyF4 }, - { GDK_KEY_F5, uiExtKeyF5 }, - { GDK_KEY_F6, uiExtKeyF6 }, - { GDK_KEY_F7, uiExtKeyF7 }, - { GDK_KEY_F8, uiExtKeyF8 }, - { GDK_KEY_F9, uiExtKeyF9 }, - { GDK_KEY_F10, uiExtKeyF10 }, - { GDK_KEY_F11, uiExtKeyF11 }, - { GDK_KEY_F12, uiExtKeyF12 }, - // numpad numeric keys and . are handled in events.c - { GDK_KEY_KP_Enter, uiExtKeyNEnter }, - { GDK_KEY_KP_Add, uiExtKeyNAdd }, - { GDK_KEY_KP_Subtract, uiExtKeyNSubtract }, - { GDK_KEY_KP_Multiply, uiExtKeyNMultiply }, - { GDK_KEY_KP_Divide, uiExtKeyNDivide }, - { GDK_KEY_Print, 0 }, -}; - -static const struct { - guint keyval; - uiModifiers mod; -} modKeys[] = { - { GDK_KEY_Control_L, uiModifierCtrl }, - { GDK_KEY_Control_R, uiModifierCtrl }, - { GDK_KEY_Alt_L, uiModifierAlt }, - { GDK_KEY_Alt_R, uiModifierAlt }, - { GDK_KEY_Meta_L, uiModifierAlt }, - { GDK_KEY_Meta_R, uiModifierAlt }, - { GDK_KEY_Shift_L, uiModifierShift }, - { GDK_KEY_Shift_R, uiModifierShift }, - { GDK_KEY_Super_L, uiModifierSuper }, - { GDK_KEY_Super_R, uiModifierSuper }, - { GDK_KEY_Print, 0 }, -}; - -// http://www.comptechdoc.org/os/linux/howlinuxworks/linux_hlkeycodes.html -int scancode_unix2normal(int scan) -{ - scan -= 8; - - // extended keys get weird scancodes. fix 'em up - switch (scan) - { - case 0x60: return 0x11C; - case 0x61: return 0x11D; - case 0x62: return 0x135; - case 0x63: return 0x137; - case 0x64: return 0x138; - case 0x66: return 0x147; - case 0x67: return 0x148; - case 0x68: return 0x149; - case 0x69: return 0x14B; - case 0x6A: return 0x14D; - case 0x6B: return 0x14F; - case 0x6C: return 0x150; - case 0x6D: return 0x151; - case 0x6E: return 0x152; - case 0x6F: return 0x153; - case 0x77: return 0x45; // PAUSE, this one is weird. check it. - case 0x7D: return 0x15B; // Windows key - case 0x7F: return 0x15D; // context menu key - // TODO: there may be more fancy keys - default: return scan; - } -} - -int scancode_normal2unix(int scan) -{ - // extended keys get weird scancodes. fix 'em up - switch (scan) - { - case 0x11C: return 8+0x60; - case 0x11D: return 8+0x61; - case 0x135: return 8+0x62; - case 0x137: return 8+0x63; - case 0x138: return 8+0x64; - case 0x147: return 8+0x66; - case 0x148: return 8+0x67; - case 0x149: return 8+0x68; - case 0x14B: return 8+0x69; - case 0x14D: return 8+0x6A; - case 0x14F: return 8+0x6B; - case 0x150: return 8+0x6C; - case 0x151: return 8+0x6D; - case 0x152: return 8+0x6E; - case 0x153: return 8+0x6F; - case 0x45: return 8+0x77; // PAUSE, this one is weird. check it. - case 0x15B: return 8+0x7D; // Windows key - case 0x15D: return 8+0x7F; // context menu key - // TODO: there may be more fancy keys - default: return scan + 8; - } -} - -static int areaKeyEvent(uiArea *a, int up, GdkEventKey *e) -{ - uiAreaKeyEvent ke; - guint state; - int i; - - ke.Key = 0; - ke.ExtKey = 0; - ke.Modifier = 0; - - state = translateModifiers(e->state, e->window); - ke.Modifiers = toModifiers(state); - - ke.Up = up; - ke.Repeat = 0; // TODO!!!!! - - ke.Scancode = scancode_unix2normal(e->hardware_keycode); - -#if 0 - for (i = 0; extKeys[i].keyval != GDK_KEY_Print; i++) - if (extKeys[i].keyval == e->keyval) { - ke.ExtKey = extKeys[i].extkey; - goto keyFound; - } - - for (i = 0; modKeys[i].keyval != GDK_KEY_Print; i++) - if (modKeys[i].keyval == e->keyval) { - ke.Modifier = modKeys[i].mod; - // don't include the modifier in ke.Modifiers - ke.Modifiers &= ~ke.Modifier; - goto keyFound; - } - - if (fromScancode(e->hardware_keycode - 8, &ke)) - goto keyFound; - - // no supported key found; treat as unhandled - return 0; - -keyFound: -#endif - return (*(a->ah->KeyEvent))(a->ah, a, &ke); -} - -static gboolean areaWidget_key_press_event(GtkWidget *w, GdkEventKey *e) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - - if (areaKeyEvent(a, 0, e)) - return GDK_EVENT_STOP; - return GDK_EVENT_PROPAGATE; -} - -static gboolean areaWidget_key_release_event(GtkWidget *w, GdkEventKey *e) -{ - areaWidget *aw = areaWidget(w); - uiArea *a = aw->a; - - if (areaKeyEvent(a, 1, e)) - return GDK_EVENT_STOP; - return GDK_EVENT_PROPAGATE; -} - -char* uiKeyName(int scancode) -{ - scancode = scancode_normal2unix(scancode); - - char* ret; - guint* keyvals; int num; - GdkKeymap* keymap = gdk_keymap_get_for_display(gdk_display_get_default()); - if (gdk_keymap_get_entries_for_keycode(keymap, scancode, NULL, &keyvals, &num)) - { - // TODO: pick smarter?? - int keyval = keyvals[0]; - - g_free(keyvals); - - ret = gdk_keyval_name(keyval); - } - else - { - char tmp[16]; - sprintf(tmp, "#%03X", scancode); - ret = tmp; - } - - return uiUnixStrdupText(ret); -} - -enum { - pArea = 1, - nProps, -}; - -static GParamSpec *pspecArea; - -static void areaWidget_set_property(GObject *obj, guint prop, const GValue *value, GParamSpec *pspec) -{ - areaWidget *aw = areaWidget(obj); - - switch (prop) { - case pArea: - aw->a = (uiArea *) g_value_get_pointer(value); - aw->a->cc = &(aw->cc); - return; - } - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop, pspec); -} - -static void areaWidget_get_property(GObject *obj, guint prop, GValue *value, GParamSpec *pspec) -{ - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop, pspec); -} - -static void areaWidget_class_init(areaWidgetClass *class) -{ - G_OBJECT_CLASS(class)->dispose = areaWidget_dispose; - G_OBJECT_CLASS(class)->finalize = areaWidget_finalize; - G_OBJECT_CLASS(class)->set_property = areaWidget_set_property; - G_OBJECT_CLASS(class)->get_property = areaWidget_get_property; - - GTK_WIDGET_CLASS(class)->size_allocate = areaWidget_size_allocate; - GTK_WIDGET_CLASS(class)->draw = areaWidget_draw; - GTK_WIDGET_CLASS(class)->get_preferred_height = areaWidget_get_preferred_height; - GTK_WIDGET_CLASS(class)->get_preferred_width = areaWidget_get_preferred_width; - GTK_WIDGET_CLASS(class)->button_press_event = areaWidget_button_press_event; - GTK_WIDGET_CLASS(class)->button_release_event = areaWidget_button_release_event; - GTK_WIDGET_CLASS(class)->motion_notify_event = areaWidget_motion_notify_event; - GTK_WIDGET_CLASS(class)->enter_notify_event = areaWidget_enter_notify_event; - GTK_WIDGET_CLASS(class)->leave_notify_event = areaWidget_leave_notify_event; - GTK_WIDGET_CLASS(class)->key_press_event = areaWidget_key_press_event; - GTK_WIDGET_CLASS(class)->key_release_event = areaWidget_key_release_event; - - pspecArea = g_param_spec_pointer("libui-area", - "libui-area", - "uiArea.", - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - g_object_class_install_property(G_OBJECT_CLASS(class), pArea, pspecArea); -} - -// control implementation - -uiUnixControlAllDefaultsExceptDestroy(uiArea) - -static void uiAreaDestroy(uiControl *c) -{ - uiArea* a = uiArea(c); - if (a->opengl && a->glContext) freeGLContext(a->glContext); - g_object_unref(uiArea(c)->widget); - uiFreeControl(c); -} - -void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b) -{ - a->bgR = r; - a->bgG = g; - a->bgB = b; -} - -void uiAreaSetSize(uiArea *a, int width, int height) -{ - if (!a->scrolling) - userbug("You cannot call uiAreaSetSize() on a non-scrolling uiArea. (area: %p)", a); - a->scrollWidth = width; - a->scrollHeight = height; - gtk_widget_queue_resize(a->areaWidget); -} - -gboolean _threadsaferefresh(gpointer data) -{ - uiArea* a = (uiArea*)data; - gtk_widget_queue_draw(a->areaWidget); - return FALSE; -} - -void uiAreaQueueRedrawAll(uiArea *a) -{ - // TODO: figure out how we could generalize the "thread-safe function call" mechanism - if (g_thread_self() != gtkthread) - g_idle_add(_threadsaferefresh, a); - else - gtk_widget_queue_draw(a->areaWidget); -} - -void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height) -{ - // TODO - // TODO adjust adjustments and find source for that -} - -void uiAreaBeginUserWindowMove(uiArea *a) -{ - GtkWidget *toplevel; - - if (a->dragevent == NULL) - userbug("cannot call uiAreaBeginUserWindowMove() outside of a Mouse() with Down != 0"); - // TODO don't we have a libui function for this? did I scrap it? - // TODO widget or areaWidget? - toplevel = gtk_widget_get_toplevel(a->widget); - if (toplevel == NULL) { - // TODO - return; - } - // the docs say to do this - if (!gtk_widget_is_toplevel(toplevel)) { - // TODO - return; - } - if (!GTK_IS_WINDOW(toplevel)) { - // TODO - return; - } - gtk_window_begin_move_drag(GTK_WINDOW(toplevel), - a->dragevent->button, - a->dragevent->x_root, // TODO are these correct? - a->dragevent->y_root, - a->dragevent->time); -} - -static const GdkWindowEdge edges[] = { - [uiWindowResizeEdgeLeft] = GDK_WINDOW_EDGE_WEST, - [uiWindowResizeEdgeTop] = GDK_WINDOW_EDGE_NORTH, - [uiWindowResizeEdgeRight] = GDK_WINDOW_EDGE_EAST, - [uiWindowResizeEdgeBottom] = GDK_WINDOW_EDGE_SOUTH, - [uiWindowResizeEdgeTopLeft] = GDK_WINDOW_EDGE_NORTH_WEST, - [uiWindowResizeEdgeTopRight] = GDK_WINDOW_EDGE_NORTH_EAST, - [uiWindowResizeEdgeBottomLeft] = GDK_WINDOW_EDGE_SOUTH_WEST, - [uiWindowResizeEdgeBottomRight] = GDK_WINDOW_EDGE_SOUTH_EAST, -}; - -void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge) -{ - GtkWidget *toplevel; - - if (a->dragevent == NULL) - userbug("cannot call uiAreaBeginUserWindowResize() outside of a Mouse() with Down != 0"); - // TODO don't we have a libui function for this? did I scrap it? - // TODO widget or areaWidget? - toplevel = gtk_widget_get_toplevel(a->widget); - if (toplevel == NULL) { - // TODO - return; - } - // the docs say to do this - if (!gtk_widget_is_toplevel(toplevel)) { - // TODO - return; - } - if (!GTK_IS_WINDOW(toplevel)) { - // TODO - return; - } - gtk_window_begin_resize_drag(GTK_WINDOW(toplevel), - edges[edge], - a->dragevent->button, - a->dragevent->x_root, // TODO are these correct? - a->dragevent->y_root, - a->dragevent->time); -} - -uiArea *uiNewArea(uiAreaHandler *ah) -{ - uiArea *a; - - uiUnixNewControl(uiArea, a); - - a->ah = ah; - a->scrolling = FALSE; - a->opengl = FALSE; - - a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType, - "libui-area", a, - NULL)); - a->drawingArea = GTK_DRAWING_AREA(a->areaWidget); - a->area = areaWidget(a->areaWidget); - - a->widget = a->areaWidget; - - uiAreaSetBackgroundColor(a, -1, -1, -1); - - return a; -} - -void _areaCreateGLContext(GtkWidget* widget, gpointer data) -{ - uiArea* a = (uiArea*)data; - - uiGLContext* ctx = NULL; - for (int i = 0; a->req_versions[i] && !ctx; i++) - { - int major = uiGLVerMajor(a->req_versions[i]); - int minor = uiGLVerMinor(a->req_versions[i]); - - // we cannot support any version older than 3.2 via GDK - if ((major < 3) || (major == 3 && minor < 2)) - break; - - ctx = createGLContext(widget, major, minor); - } - - a->glContext = ctx; -} - -uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions) -{ - uiArea *a; - - uiUnixNewControl(uiArea, a); - - a->ah = ah; - a->scrolling = FALSE; - a->opengl = TRUE; - - a->glContext = NULL; - a->req_versions = req_versions; - a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType, - "libui-area", a, - NULL)); - a->area = areaWidget(a->areaWidget); - - a->widget = a->areaWidget; - - g_signal_connect(a->widget, "realize", G_CALLBACK(_areaCreateGLContext), a); - - uiAreaSetBackgroundColor(a, -1, -1, -1); - - return a; -} - -uiGLContext *uiAreaGetGLContext(uiArea* a) -{ - if (!a) return NULL; - return a->glContext; -} - -uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height) -{ - uiArea *a; - - uiUnixNewControl(uiArea, a); - - a->ah = ah; - a->scrolling = TRUE; - a->scrollWidth = width; - a->scrollHeight = height; - a->opengl = FALSE; - - a->swidget = gtk_scrolled_window_new(NULL, NULL); - a->scontainer = GTK_CONTAINER(a->swidget); - a->sw = GTK_SCROLLED_WINDOW(a->swidget); - - a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType, - "libui-area", a, - NULL)); - a->drawingArea = GTK_DRAWING_AREA(a->areaWidget); - a->area = areaWidget(a->areaWidget); - - a->widget = a->swidget; - - uiAreaSetBackgroundColor(a, -1, -1, -1); - - gtk_container_add(a->scontainer, a->areaWidget); - // and make the area visible; only the scrolled window's visibility is controlled by libui - gtk_widget_show(a->areaWidget); - - return a; -} diff --git a/src/libui_sdl/libui/unix/box.c b/src/libui_sdl/libui/unix/box.c deleted file mode 100644 index 23fb7f7c..00000000 --- a/src/libui_sdl/libui/unix/box.c +++ /dev/null @@ -1,159 +0,0 @@ -// 7 april 2015 -#include "uipriv_unix.h" - -struct boxChild { - uiControl *c; - int stretchy; - gboolean oldhexpand; - GtkAlign oldhalign; - gboolean oldvexpand; - GtkAlign oldvalign; -}; - -struct uiBox { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *container; - GtkBox *box; - GArray *controls; - int vertical; - int padded; - GtkSizeGroup *stretchygroup; // ensures all stretchy controls have the same size -}; - -uiUnixControlAllDefaultsExceptDestroy(uiBox) - -#define ctrl(b, i) &g_array_index(b->controls, struct boxChild, i) - -static void uiBoxDestroy(uiControl *c) -{ - uiBox *b = uiBox(c); - struct boxChild *bc; - guint i; - - // kill the size group - g_object_unref(b->stretchygroup); - // free all controls - for (i = 0; i < b->controls->len; i++) { - bc = ctrl(b, i); - uiControlSetParent(bc->c, NULL); - // and make sure the widget itself stays alive - uiUnixControlSetContainer(uiUnixControl(bc->c), b->container, TRUE); - uiControlDestroy(bc->c); - } - g_array_free(b->controls, TRUE); - // and then ourselves - g_object_unref(b->widget); - uiFreeControl(uiControl(b)); -} - -void uiBoxAppend(uiBox *b, uiControl *c, int stretchy) -{ - struct boxChild bc; - GtkWidget *widget; - - bc.c = c; - bc.stretchy = stretchy; - widget = GTK_WIDGET(uiControlHandle(bc.c)); - bc.oldhexpand = gtk_widget_get_hexpand(widget); - bc.oldhalign = gtk_widget_get_halign(widget); - bc.oldvexpand = gtk_widget_get_vexpand(widget); - bc.oldvalign = gtk_widget_get_valign(widget); - - if (bc.stretchy) { - if (b->vertical) { - gtk_widget_set_vexpand(widget, TRUE); - gtk_widget_set_valign(widget, GTK_ALIGN_FILL); - } else { - gtk_widget_set_hexpand(widget, TRUE); - gtk_widget_set_halign(widget, GTK_ALIGN_FILL); - } - gtk_size_group_add_widget(b->stretchygroup, widget); - } else - if (b->vertical) - gtk_widget_set_vexpand(widget, FALSE); - else - gtk_widget_set_hexpand(widget, FALSE); - // and make them fill the opposite direction - if (b->vertical) { - gtk_widget_set_hexpand(widget, TRUE); - gtk_widget_set_halign(widget, GTK_ALIGN_FILL); - } else { - gtk_widget_set_vexpand(widget, TRUE); - gtk_widget_set_valign(widget, GTK_ALIGN_FILL); - } - - uiControlSetParent(bc.c, uiControl(b)); - uiUnixControlSetContainer(uiUnixControl(bc.c), b->container, FALSE); - g_array_append_val(b->controls, bc); -} - -void uiBoxDelete(uiBox *b, int index) -{ - struct boxChild *bc; - GtkWidget *widget; - - bc = ctrl(b, index); - widget = GTK_WIDGET(uiControlHandle(bc->c)); - - uiControlSetParent(bc->c, NULL); - uiUnixControlSetContainer(uiUnixControl(bc->c), b->container, TRUE); - - if (bc->stretchy) - gtk_size_group_remove_widget(b->stretchygroup, widget); - gtk_widget_set_hexpand(widget, bc->oldhexpand); - gtk_widget_set_halign(widget, bc->oldhalign); - gtk_widget_set_vexpand(widget, bc->oldvexpand); - gtk_widget_set_valign(widget, bc->oldvalign); - - g_array_remove_index(b->controls, index); -} - -int uiBoxPadded(uiBox *b) -{ - return b->padded; -} - -void uiBoxSetPadded(uiBox *b, int padded) -{ - b->padded = padded; - if (b->padded) - if (b->vertical) - gtk_box_set_spacing(b->box, gtkYPadding); - else - gtk_box_set_spacing(b->box, gtkXPadding); - else - gtk_box_set_spacing(b->box, 0); -} - -static uiBox *finishNewBox(GtkOrientation orientation) -{ - uiBox *b; - - uiUnixNewControl(uiBox, b); - - b->widget = gtk_box_new(orientation, 0); - b->container = GTK_CONTAINER(b->widget); - b->box = GTK_BOX(b->widget); - - b->vertical = orientation == GTK_ORIENTATION_VERTICAL; - - if (b->vertical) - b->stretchygroup = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL); - else - b->stretchygroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - - b->controls = g_array_new(FALSE, TRUE, sizeof (struct boxChild)); - - return b; -} - -uiBox *uiNewHorizontalBox(void) -{ - return finishNewBox(GTK_ORIENTATION_HORIZONTAL); -} - -uiBox *uiNewVerticalBox(void) -{ - return finishNewBox(GTK_ORIENTATION_VERTICAL); -} diff --git a/src/libui_sdl/libui/unix/button.c b/src/libui_sdl/libui/unix/button.c deleted file mode 100644 index b0500e31..00000000 --- a/src/libui_sdl/libui/unix/button.c +++ /dev/null @@ -1,57 +0,0 @@ -// 10 june 2015 -#include "uipriv_unix.h" - -struct uiButton { - uiUnixControl c; - GtkWidget *widget; - GtkButton *button; - void (*onClicked)(uiButton *, void *); - void *onClickedData; -}; - -uiUnixControlAllDefaults(uiButton) - -static void onClicked(GtkButton *button, gpointer data) -{ - uiButton *b = uiButton(data); - - (*(b->onClicked))(b, b->onClickedData); -} - -static void defaultOnClicked(uiButton *b, void *data) -{ - // do nothing -} - -char *uiButtonText(uiButton *b) -{ - return uiUnixStrdupText(gtk_button_get_label(b->button)); -} - -void uiButtonSetText(uiButton *b, const char *text) -{ - gtk_button_set_label(b->button, text); -} - -void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *, void *), void *data) -{ - b->onClicked = f; - b->onClickedData = data; -} - -uiButton *uiNewButton(const char *text) -{ - uiButton *b; - - uiUnixNewControl(uiButton, b); - - b->widget = gtk_button_new_with_label(text); - b->button = GTK_BUTTON(b->widget); - - g_signal_connect(b->widget, "clicked", G_CALLBACK(onClicked), b); - uiButtonOnClicked(b, defaultOnClicked, NULL); - - gtk_widget_set_size_request(b->widget, 64, 1); - - return b; -} diff --git a/src/libui_sdl/libui/unix/cellrendererbutton.c b/src/libui_sdl/libui/unix/cellrendererbutton.c deleted file mode 100644 index e3bbf48b..00000000 --- a/src/libui_sdl/libui/unix/cellrendererbutton.c +++ /dev/null @@ -1,299 +0,0 @@ -// 28 june 2016 -#include "uipriv_unix.h" - -// TODOs -// - it's a rather tight fit -// - selected row text color is white -// - resizing a column with a button in it crashes the program -// - accessibility -// - right side too big? - -#define cellRendererButtonType (cellRendererButton_get_type()) -#define cellRendererButton(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), cellRendererButtonType, cellRendererButton)) -#define isCellRendererButton(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), cellRendererButtonType)) -#define cellRendererButtonClass(class) (G_TYPE_CHECK_CLASS_CAST((class), cellRendererButtonType, cellRendererButtonClass)) -#define isCellRendererButtonClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), cellRendererButton)) -#define getCellRendererButtonClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), cellRendererButtonType, cellRendererButtonClass)) - -typedef struct cellRendererButton cellRendererButton; -typedef struct cellRendererButtonClass cellRendererButtonClass; - -struct cellRendererButton { - GtkCellRenderer parent_instance; - char *text; -}; - -struct cellRendererButtonClass { - GtkCellRendererClass parent_class; -}; - -G_DEFINE_TYPE(cellRendererButton, cellRendererButton, GTK_TYPE_CELL_RENDERER) - -static void cellRendererButton_init(cellRendererButton *c) -{ - g_object_set(c, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); - // the standard cell renderers all do this - gtk_cell_renderer_set_padding(GTK_CELL_RENDERER(c), 2, 2); -} - -static void cellRendererButton_dispose(GObject *obj) -{ - G_OBJECT_CLASS(cellRendererButton_parent_class)->dispose(obj); -} - -static void cellRendererButton_finalize(GObject *obj) -{ - cellRendererButton *c = cellRendererButton(obj); - - if (c->text != NULL) { - g_free(c->text); - c->text = NULL; - } - G_OBJECT_CLASS(cellRendererButton_parent_class)->finalize(obj); -} - -static GtkSizeRequestMode cellRendererButton_get_request_mode(GtkCellRenderer *r) -{ - return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; -} - -// this is basically what GtkCellRendererToggle did in 3.10 and does in 3.20, as well as what the Foreign Drawing gtk3-demo demo does -static GtkStyleContext *setButtonStyle(GtkWidget *widget) -{ - GtkStyleContext *base, *context; - GtkWidgetPath *path; - - base = gtk_widget_get_style_context(widget); - context = gtk_style_context_new(); - - path = gtk_widget_path_copy(gtk_style_context_get_path(base)); - gtk_widget_path_append_type(path, G_TYPE_NONE); - if (!FUTURE_gtk_widget_path_iter_set_object_name(path, -1, "button")) - // not on 3.20; try the type - gtk_widget_path_iter_set_object_type(path, -1, GTK_TYPE_BUTTON); - - gtk_style_context_set_path(context, path); - gtk_style_context_set_parent(context, base); - // the gtk3-demo example (which says we need to do this) uses gtk_widget_path_iter_get_state(path, -1) but that's not available until 3.14 - // TODO make a future for that too - gtk_style_context_set_state(context, gtk_style_context_get_state(base)); - gtk_widget_path_unref(path); - - // and if the above widget path screwery stil doesn't work, this will - gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON); - - return context; -} - -void unsetButtonStyle(GtkStyleContext *context) -{ - g_object_unref(context); -} - -// this is based on what GtkCellRendererText does -static void cellRendererButton_get_preferred_width(GtkCellRenderer *r, GtkWidget *widget, gint *minimum, gint *natural) -{ - cellRendererButton *c = cellRendererButton(r); - gint xpad; - PangoLayout *layout; - PangoRectangle rect; - gint out; - - gtk_cell_renderer_get_padding(GTK_CELL_RENDERER(c), &xpad, NULL); - - layout = gtk_widget_create_pango_layout(widget, c->text); - pango_layout_set_width(layout, -1); - pango_layout_get_extents(layout, NULL, &rect); - g_object_unref(layout); - - out = 2 * xpad + PANGO_PIXELS_CEIL(rect.width); - if (minimum != NULL) - *minimum = out; - if (natural != NULL) - *natural = out; -} - -// this is based on what GtkCellRendererText does -static void cellRendererButton_get_preferred_height_for_width(GtkCellRenderer *r, GtkWidget *widget, gint width, gint *minimum, gint *natural) -{ - cellRendererButton *c = cellRendererButton(r); - gint xpad, ypad; - PangoLayout *layout; - gint height; - gint out; - - gtk_cell_renderer_get_padding(GTK_CELL_RENDERER(c), &xpad, &ypad); - - layout = gtk_widget_create_pango_layout(widget, c->text); - pango_layout_set_width(layout, ((2 * xpad + width) * PANGO_SCALE)); - pango_layout_get_pixel_size(layout, NULL, &height); - g_object_unref(layout); - - out = 2 * ypad + height; - if (minimum != NULL) - *minimum = out; - if (natural != NULL) - *natural = out; -} - -// this is basically what GtkCellRendererText does -static void cellRendererButton_get_preferred_height(GtkCellRenderer *r, GtkWidget *widget, gint *minimum, gint *natural) -{ - gint width; - - gtk_cell_renderer_get_preferred_width(r, widget, &width, NULL); - gtk_cell_renderer_get_preferred_height_for_width(r, widget, width, minimum, natural); -} - -// this is based on what GtkCellRendererText does -static void cellRendererButton_get_aligned_area(GtkCellRenderer *r, GtkWidget *widget, GtkCellRendererState flags, const GdkRectangle *cell_area, GdkRectangle *aligned_area) -{ - cellRendererButton *c = cellRendererButton(r); - gint xpad, ypad; - PangoLayout *layout; - PangoRectangle rect; - gfloat xalign, yalign; - gint xoffset, yoffset; - - gtk_cell_renderer_get_padding(GTK_CELL_RENDERER(c), &xpad, &ypad); - - layout = gtk_widget_create_pango_layout(widget, c->text); - pango_layout_set_width(layout, -1); - pango_layout_get_pixel_extents(layout, NULL, &rect); - - xoffset = 0; - yoffset = 0; - if (cell_area != NULL) { - gtk_cell_renderer_get_alignment(GTK_CELL_RENDERER(c), &xalign, &yalign); - xoffset = cell_area->width - (2 * xpad + rect.width); - // use explicit casts just to be safe - if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) - xoffset = ((gdouble) xoffset) * (1.0 - xalign); - else - xoffset *= ((gdouble) xoffset) * xalign; - yoffset = yalign * (cell_area->height - (2 * ypad + rect.height)); - yoffset = MAX(yoffset, 0); - } - - aligned_area->x = cell_area->x + xoffset; - aligned_area->y = cell_area->y + yoffset; - aligned_area->width = 2 * xpad + rect.width; - aligned_area->height = 2 * ypad + rect.height; - - g_object_unref(layout); -} - -// this is based on both what GtkCellRendererText does and what GtkCellRendererToggle does -static void cellRendererButton_render(GtkCellRenderer *r, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) -{ - cellRendererButton *c = cellRendererButton(r); - gint xpad, ypad; - GdkRectangle alignedArea; - gint xoffset, yoffset; - GtkStyleContext *context; - PangoLayout *layout; - PangoRectangle rect; - - gtk_cell_renderer_get_padding(GTK_CELL_RENDERER(c), &xpad, &ypad); - gtk_cell_renderer_get_aligned_area(GTK_CELL_RENDERER(c), widget, flags, cell_area, &alignedArea); - xoffset = alignedArea.x - cell_area->x; - yoffset = alignedArea.y - cell_area->y; - - context = setButtonStyle(widget); - layout = gtk_widget_create_pango_layout(widget, c->text); - - gtk_render_background(context, cr, - background_area->x + xoffset + xpad, - background_area->y + yoffset + ypad, - background_area->width - 2 * xpad, - background_area->height - 2 * ypad); - gtk_render_frame(context, cr, - background_area->x + xoffset + xpad, - background_area->y + yoffset + ypad, - background_area->width - 2 * xpad, - background_area->height - 2 * ypad); - - pango_layout_set_width(layout, -1); - pango_layout_get_pixel_extents(layout, NULL, &rect); - xoffset -= rect.x; - gtk_render_layout(context, cr, - cell_area->x + xoffset + xpad, - cell_area->y + yoffset + ypad, - layout); - - g_object_unref(layout); - unsetButtonStyle(context); -} - -static guint clickedSignal; - -static gboolean cellRendererButton_activate(GtkCellRenderer *r, GdkEvent *e, GtkWidget *widget, const gchar *path, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) -{ - g_signal_emit(r, clickedSignal, 0, path); - return TRUE; -} - -static GParamSpec *props[2] = { NULL, NULL }; - -static void cellRendererButton_set_property(GObject *object, guint prop, const GValue *value, GParamSpec *pspec) -{ - cellRendererButton *c = cellRendererButton(object); - - if (prop != 1) { - G_OBJECT_WARN_INVALID_PROPERTY_ID(c, prop, pspec); - return; - } - if (c->text != NULL) - g_free(c->text); - c->text = g_value_dup_string(value); - // GtkCellRendererText doesn't queue a redraw; we won't either -} - -static void cellRendererButton_get_property(GObject *object, guint prop, GValue *value, GParamSpec *pspec) -{ - cellRendererButton *c = cellRendererButton(object); - - if (prop != 1) { - G_OBJECT_WARN_INVALID_PROPERTY_ID(c, prop, pspec); - return; - } - g_value_set_string(value, c->text); -} - -static void cellRendererButton_class_init(cellRendererButtonClass *class) -{ - G_OBJECT_CLASS(class)->dispose = cellRendererButton_dispose; - G_OBJECT_CLASS(class)->finalize = cellRendererButton_finalize; - G_OBJECT_CLASS(class)->set_property = cellRendererButton_set_property; - G_OBJECT_CLASS(class)->get_property = cellRendererButton_get_property; - GTK_CELL_RENDERER_CLASS(class)->get_request_mode = cellRendererButton_get_request_mode; - GTK_CELL_RENDERER_CLASS(class)->get_preferred_width = cellRendererButton_get_preferred_width; - GTK_CELL_RENDERER_CLASS(class)->get_preferred_height_for_width = cellRendererButton_get_preferred_height_for_width; - GTK_CELL_RENDERER_CLASS(class)->get_preferred_height = cellRendererButton_get_preferred_height; - // don't provide a get_preferred_width_for_height() - GTK_CELL_RENDERER_CLASS(class)->get_aligned_area = cellRendererButton_get_aligned_area; - // don't provide a get_size() - GTK_CELL_RENDERER_CLASS(class)->render = cellRendererButton_render; - GTK_CELL_RENDERER_CLASS(class)->activate = cellRendererButton_activate; - // don't provide a start_editing() - - props[1] = g_param_spec_string("text", - "Text", - "Button text", - "", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties(G_OBJECT_CLASS(class), 2, props); - - clickedSignal = g_signal_new("clicked", - G_TYPE_FROM_CLASS(class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 1, G_TYPE_STRING); -} - -GtkCellRenderer *newCellRendererButton(void) -{ - return GTK_CELL_RENDERER(g_object_new(cellRendererButtonType, NULL)); -} diff --git a/src/libui_sdl/libui/unix/checkbox.c b/src/libui_sdl/libui/unix/checkbox.c deleted file mode 100644 index 47f85145..00000000 --- a/src/libui_sdl/libui/unix/checkbox.c +++ /dev/null @@ -1,78 +0,0 @@ -// 10 june 2015 -#include "uipriv_unix.h" - -struct uiCheckbox { - uiUnixControl c; - GtkWidget *widget; - GtkButton *button; - GtkToggleButton *toggleButton; - GtkCheckButton *checkButton; - void (*onToggled)(uiCheckbox *, void *); - void *onToggledData; - gulong onToggledSignal; -}; - -uiUnixControlAllDefaults(uiCheckbox) - -static void onToggled(GtkToggleButton *b, gpointer data) -{ - uiCheckbox *c = uiCheckbox(data); - - (*(c->onToggled))(c, c->onToggledData); -} - -static void defaultOnToggled(uiCheckbox *c, void *data) -{ - // do nothing -} - -char *uiCheckboxText(uiCheckbox *c) -{ - return uiUnixStrdupText(gtk_button_get_label(c->button)); -} - -void uiCheckboxSetText(uiCheckbox *c, const char *text) -{ - gtk_button_set_label(GTK_BUTTON(c->button), text); -} - -void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *, void *), void *data) -{ - c->onToggled = f; - c->onToggledData = data; -} - -int uiCheckboxChecked(uiCheckbox *c) -{ - return gtk_toggle_button_get_active(c->toggleButton) != FALSE; -} - -void uiCheckboxSetChecked(uiCheckbox *c, int checked) -{ - gboolean active; - - active = FALSE; - if (checked) - active = TRUE; - // we need to inhibit sending of ::toggled because this WILL send a ::toggled otherwise - g_signal_handler_block(c->toggleButton, c->onToggledSignal); - gtk_toggle_button_set_active(c->toggleButton, active); - g_signal_handler_unblock(c->toggleButton, c->onToggledSignal); -} - -uiCheckbox *uiNewCheckbox(const char *text) -{ - uiCheckbox *c; - - uiUnixNewControl(uiCheckbox, c); - - c->widget = gtk_check_button_new_with_label(text); - c->button = GTK_BUTTON(c->widget); - c->toggleButton = GTK_TOGGLE_BUTTON(c->widget); - c->checkButton = GTK_CHECK_BUTTON(c->widget); - - c->onToggledSignal = g_signal_connect(c->widget, "toggled", G_CALLBACK(onToggled), c); - uiCheckboxOnToggled(c, defaultOnToggled, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/unix/child.c b/src/libui_sdl/libui/unix/child.c deleted file mode 100644 index b4a09677..00000000 --- a/src/libui_sdl/libui/unix/child.c +++ /dev/null @@ -1,120 +0,0 @@ -// 28 august 2015 -#include "uipriv_unix.h" - -// This file contains helpers for managing child controls. - -struct child { - uiControl *c; - GtkWidget *widget; - - gboolean oldhexpand; - GtkAlign oldhalign; - gboolean oldvexpand; - GtkAlign oldvalign; - - // Some children can be boxed; that is, they can have an optionally-margined box around them. - // uiGroup, uiTab, and uiWindow all do this. - GtkWidget *box; - - // If the child is not boxed, this is its parent. - // If the child is boxed, this is the box. - GtkContainer *parent; - - // This flag is for users of these functions. - // For uiBox, this is "spaced". - // For uiTab, this is "margined". (uiGroup and uiWindow have to maintain their margined state themselves, since the margined state is independent of whether there is a child for those two.) - int flag; -}; - -struct child *newChild(uiControl *child, uiControl *parent, GtkContainer *parentContainer) -{ - struct child *c; - - if (child == NULL) - return NULL; - - c = uiNew(struct child); - c->c = child; - c->widget = GTK_WIDGET(uiControlHandle(c->c)); - - c->oldhexpand = gtk_widget_get_hexpand(c->widget); - c->oldhalign = gtk_widget_get_halign(c->widget); - c->oldvexpand = gtk_widget_get_vexpand(c->widget); - c->oldvalign = gtk_widget_get_valign(c->widget); - - uiControlSetParent(c->c, parent); - uiUnixControlSetContainer(uiUnixControl(c->c), parentContainer, FALSE); - c->parent = parentContainer; - - return c; -} - -struct child *newChildWithBox(uiControl *child, uiControl *parent, GtkContainer *parentContainer, int margined) -{ - struct child *c; - GtkWidget *box; - - if (child == NULL) - return NULL; - box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show(box); - c = newChild(child, parent, GTK_CONTAINER(box)); - gtk_widget_set_hexpand(c->widget, TRUE); - gtk_widget_set_halign(c->widget, GTK_ALIGN_FILL); - gtk_widget_set_vexpand(c->widget, TRUE); - gtk_widget_set_valign(c->widget, GTK_ALIGN_FILL); - c->box = box; - gtk_container_add(parentContainer, c->box); - childSetMargined(c, margined); - return c; -} - -void childRemove(struct child *c) -{ - uiControlSetParent(c->c, NULL); - uiUnixControlSetContainer(uiUnixControl(c->c), c->parent, TRUE); - - gtk_widget_set_hexpand(c->widget, c->oldhexpand); - gtk_widget_set_halign(c->widget, c->oldhalign); - gtk_widget_set_vexpand(c->widget, c->oldvexpand); - gtk_widget_set_valign(c->widget, c->oldvalign); - - if (c->box != NULL) - gtk_widget_destroy(c->box); - - uiFree(c); -} - -void childDestroy(struct child *c) -{ - uiControl *child; - - child = c->c; - childRemove(c); - uiControlDestroy(child); -} - -GtkWidget *childWidget(struct child *c) -{ - return c->widget; -} - -int childFlag(struct child *c) -{ - return c->flag; -} - -void childSetFlag(struct child *c, int flag) -{ - c->flag = flag; -} - -GtkWidget *childBox(struct child *c) -{ - return c->box; -} - -void childSetMargined(struct child *c, int margined) -{ - setMargined(GTK_CONTAINER(c->box), margined); -} diff --git a/src/libui_sdl/libui/unix/colorbutton.c b/src/libui_sdl/libui/unix/colorbutton.c deleted file mode 100644 index 393b16f1..00000000 --- a/src/libui_sdl/libui/unix/colorbutton.c +++ /dev/null @@ -1,80 +0,0 @@ -// 15 may 2016 -#include "uipriv_unix.h" - -struct uiColorButton { - uiUnixControl c; - GtkWidget *widget; - GtkButton *button; - GtkColorButton *cb; - GtkColorChooser *cc; - void (*onChanged)(uiColorButton *, void *); - void *onChangedData; -}; - -uiUnixControlAllDefaults(uiColorButton) - -static void onColorSet(GtkColorButton *button, gpointer data) -{ - uiColorButton *b = uiColorButton(data); - - (*(b->onChanged))(b, b->onChangedData); -} - -static void defaultOnChanged(uiColorButton *b, void *data) -{ - // do nothing -} - -void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a) -{ - GdkRGBA rgba; - - gtk_color_chooser_get_rgba(b->cc, &rgba); - *r = rgba.red; - *g = rgba.green; - *bl = rgba.blue; - *a = rgba.alpha; -} - -void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a) -{ - GdkRGBA rgba; - - rgba.red = r; - rgba.green = g; - rgba.blue = bl; - rgba.alpha = a; - // no need to inhibit the signal; color-set is documented as only being sent when the user changes the color - gtk_color_chooser_set_rgba(b->cc, &rgba); -} - -void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data) -{ - b->onChanged = f; - b->onChangedData = data; -} - -uiColorButton *uiNewColorButton(void) -{ - uiColorButton *b; - GdkRGBA black; - - uiUnixNewControl(uiColorButton, b); - - // I'm not sure what the initial color is; set up a real one - black.red = 0.0; - black.green = 0.0; - black.blue = 0.0; - black.alpha = 1.0; - b->widget = gtk_color_button_new_with_rgba(&black); - b->button = GTK_BUTTON(b->widget); - b->cb = GTK_COLOR_BUTTON(b->widget); - b->cc = GTK_COLOR_CHOOSER(b->widget); - - gtk_color_chooser_set_use_alpha(b->cc, TRUE); - - g_signal_connect(b->widget, "color-set", G_CALLBACK(onColorSet), b); - uiColorButtonOnChanged(b, defaultOnChanged, NULL); - - return b; -} diff --git a/src/libui_sdl/libui/unix/combobox.c b/src/libui_sdl/libui/unix/combobox.c deleted file mode 100644 index 6fed804b..00000000 --- a/src/libui_sdl/libui/unix/combobox.c +++ /dev/null @@ -1,66 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiCombobox { - uiUnixControl c; - GtkWidget *widget; - GtkComboBox *combobox; - GtkComboBoxText *comboboxText; - void (*onSelected)(uiCombobox *, void *); - void *onSelectedData; - gulong onSelectedSignal; -}; - -uiUnixControlAllDefaults(uiCombobox) - -static void onChanged(GtkComboBox *cbox, gpointer data) -{ - uiCombobox *c = uiCombobox(data); - - (*(c->onSelected))(c, c->onSelectedData); -} - -static void defaultOnSelected(uiCombobox *c, void *data) -{ - // do nothing -} - -void uiComboboxAppend(uiCombobox *c, const char *text) -{ - gtk_combo_box_text_append(c->comboboxText, NULL, text); -} - -int uiComboboxSelected(uiCombobox *c) -{ - return gtk_combo_box_get_active(c->combobox); -} - -void uiComboboxSetSelected(uiCombobox *c, int n) -{ - // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise - g_signal_handler_block(c->combobox, c->onSelectedSignal); - gtk_combo_box_set_active(c->combobox, n); - g_signal_handler_unblock(c->combobox, c->onSelectedSignal); -} - -void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data) -{ - c->onSelected = f; - c->onSelectedData = data; -} - -uiCombobox *uiNewCombobox(void) -{ - uiCombobox *c; - - uiUnixNewControl(uiCombobox, c); - - c->widget = gtk_combo_box_text_new(); - c->combobox = GTK_COMBO_BOX(c->widget); - c->comboboxText = GTK_COMBO_BOX_TEXT(c->widget); - - c->onSelectedSignal = g_signal_connect(c->widget, "changed", G_CALLBACK(onChanged), c); - uiComboboxOnSelected(c, defaultOnSelected, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/unix/control.c b/src/libui_sdl/libui/unix/control.c deleted file mode 100644 index f6fdcea2..00000000 --- a/src/libui_sdl/libui/unix/control.c +++ /dev/null @@ -1,14 +0,0 @@ -// 16 august 2015 -#include "uipriv_unix.h" - -void uiUnixControlSetContainer(uiUnixControl *c, GtkContainer *container, gboolean remove) -{ - (*(c->SetContainer))(c, container, remove); -} - -#define uiUnixControlSignature 0x556E6978 - -uiUnixControl *uiUnixAllocControl(size_t n, uint32_t typesig, const char *typenamestr) -{ - return uiUnixControl(uiAllocControl(n, uiUnixControlSignature, typesig, typenamestr)); -} diff --git a/src/libui_sdl/libui/unix/datetimepicker.c b/src/libui_sdl/libui/unix/datetimepicker.c deleted file mode 100644 index 19689a22..00000000 --- a/src/libui_sdl/libui/unix/datetimepicker.c +++ /dev/null @@ -1,599 +0,0 @@ -// 4 september 2015 -#include "uipriv_unix.h" - -// LONGTERM imitate gnome-calendar's day/month/year entries above the calendar -// LONGTERM allow entering a 24-hour hour in the hour spinbutton and adjust accordingly - -#define dateTimePickerWidgetType (dateTimePickerWidget_get_type()) -#define dateTimePickerWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), dateTimePickerWidgetType, dateTimePickerWidget)) -#define isDateTimePickerWidget(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), dateTimePickerWidgetType)) -#define dateTimePickerWidgetClass(class) (G_TYPE_CHECK_CLASS_CAST((class), dateTimePickerWidgetType, dateTimePickerWidgetClass)) -#define isDateTimePickerWidgetClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), dateTimePickerWidget)) -#define getDateTimePickerWidgetClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), dateTimePickerWidgetType, dateTimePickerWidgetClass)) - -typedef struct dateTimePickerWidget dateTimePickerWidget; -typedef struct dateTimePickerWidgetClass dateTimePickerWidgetClass; - -struct dateTimePickerWidget { - GtkToggleButton parent_instance; - - gulong toggledSignal; - - gboolean hasTime; - gboolean hasDate; - - GtkWidget *window; - GtkWidget *box; - GtkWidget *calendar; - GtkWidget *timebox; - GtkWidget *hours; - GtkWidget *minutes; - GtkWidget *seconds; - GtkWidget *ampm; - - gulong hoursBlock; - gulong minutesBlock; - gulong secondsBlock; - gulong ampmBlock; - - GdkDevice *keyboard; - GdkDevice *mouse; -}; - -struct dateTimePickerWidgetClass { - GtkToggleButtonClass parent_class; -}; - -G_DEFINE_TYPE(dateTimePickerWidget, dateTimePickerWidget, GTK_TYPE_TOGGLE_BUTTON) - -static int realSpinValue(GtkSpinButton *spinButton) -{ - GtkAdjustment *adj; - - adj = gtk_spin_button_get_adjustment(spinButton); - return (int) gtk_adjustment_get_value(adj); -} - -static void setRealSpinValue(GtkSpinButton *spinButton, int value, gulong block) -{ - GtkAdjustment *adj; - - g_signal_handler_block(spinButton, block); - adj = gtk_spin_button_get_adjustment(spinButton); - gtk_adjustment_set_value(adj, value); - g_signal_handler_unblock(spinButton, block); -} - -static GDateTime *selected(dateTimePickerWidget *d) -{ - // choose a day for which all times are likely to be valid for the default date in case we're only dealing with time - guint year = 1970, month = 1, day = 1; - guint hour = 0, minute = 0, second = 0; - - if (d->hasDate) { - gtk_calendar_get_date(GTK_CALENDAR(d->calendar), &year, &month, &day); - month++; // GtkCalendar/GDateTime differences - } - if (d->hasTime) { - hour = realSpinValue(GTK_SPIN_BUTTON(d->hours)); - if (realSpinValue(GTK_SPIN_BUTTON(d->ampm)) != 0) - hour += 12; - minute = realSpinValue(GTK_SPIN_BUTTON(d->minutes)); - second = realSpinValue(GTK_SPIN_BUTTON(d->seconds)); - } - return g_date_time_new_local(year, month, day, hour, minute, second); -} - -static void setLabel(dateTimePickerWidget *d) -{ - GDateTime *dt; - char *fmt; - char *msg; - gboolean free; - - dt = selected(d); - free = FALSE; - if (d->hasDate && d->hasTime) { - // don't use D_T_FMT; that's too verbose - fmt = g_strdup_printf("%s %s", nl_langinfo(D_FMT), nl_langinfo(T_FMT)); - free = TRUE; - } else if (d->hasDate) - fmt = nl_langinfo(D_FMT); - else - fmt = nl_langinfo(T_FMT); - msg = g_date_time_format(dt, fmt); - gtk_button_set_label(GTK_BUTTON(d), msg); - g_free(msg); - if (free) - g_free(fmt); - g_date_time_unref(dt); -} - -static void dateTimeChanged(dateTimePickerWidget *d) -{ - setLabel(d); - // TODO fire event here -} - -// we don't want ::toggled to be sent again -static void setActive(dateTimePickerWidget *d, gboolean active) -{ - g_signal_handler_block(d, d->toggledSignal); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(d), active); - g_signal_handler_unblock(d, d->toggledSignal); -} - -// like startGrab() below, a lot of this is in the order that GtkComboBox does it -static void endGrab(dateTimePickerWidget *d) -{ - if (d->keyboard != NULL) - gdk_device_ungrab(d->keyboard, GDK_CURRENT_TIME); - gdk_device_ungrab(d->mouse, GDK_CURRENT_TIME); - gtk_device_grab_remove(d->window, d->mouse); - d->keyboard = NULL; - d->mouse = NULL; -} - -static void hidePopup(dateTimePickerWidget *d) -{ - endGrab(d); - gtk_widget_hide(d->window); - setActive(d, FALSE); -} - -// this consolidates a good chunk of what GtkComboBox does -static gboolean startGrab(dateTimePickerWidget *d) -{ - GdkDevice *dev; - guint32 time; - GdkWindow *window; - GdkDevice *keyboard, *mouse; - - dev = gtk_get_current_event_device(); - if (dev == NULL) { - // this is what GtkComboBox does - // since no device was set, just use the first available "master device" - GdkDisplay *disp; - GdkDeviceManager *dm; - GList *list; - - disp = gtk_widget_get_display(GTK_WIDGET(d)); - dm = gdk_display_get_device_manager(disp); - list = gdk_device_manager_list_devices(dm, GDK_DEVICE_TYPE_MASTER); - dev = (GdkDevice *) (list->data); - g_list_free(list); - } - - time = gtk_get_current_event_time(); - keyboard = dev; - mouse = gdk_device_get_associated_device(dev); - if (gdk_device_get_source(dev) != GDK_SOURCE_KEYBOARD) { - dev = mouse; - mouse = keyboard; - keyboard = dev; - } - - window = gtk_widget_get_window(d->window); - if (keyboard != NULL) - if (gdk_device_grab(keyboard, window, - GDK_OWNERSHIP_WINDOW, TRUE, - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, - NULL, time) != GDK_GRAB_SUCCESS) - return FALSE; - if (mouse != NULL) - if (gdk_device_grab(mouse, window, - GDK_OWNERSHIP_WINDOW, TRUE, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, - NULL, time) != GDK_GRAB_SUCCESS) { - if (keyboard != NULL) - gdk_device_ungrab(keyboard, time); - return FALSE; - } - - gtk_device_grab_add(d->window, mouse, TRUE); - d->keyboard = keyboard; - d->mouse = mouse; - return TRUE; -} - -// based on gtk_combo_box_list_position() in the GTK+ source code -static void allocationToScreen(dateTimePickerWidget *d, gint *x, gint *y) -{ - GdkWindow *window; - GtkAllocation a; - GtkRequisition aWin; - GdkScreen *screen; - GdkRectangle workarea; - int otherY; - - gtk_widget_get_allocation(GTK_WIDGET(d), &a); - gtk_widget_get_preferred_size(d->window, &aWin, NULL); - *x = 0; - *y = 0; - if (!gtk_widget_get_has_window(GTK_WIDGET(d))) { - *x = a.x; - *y = a.y; - } - window = gtk_widget_get_window(GTK_WIDGET(d)); - gdk_window_get_root_coords(window, *x, *y, x, y); - if (gtk_widget_get_direction(GTK_WIDGET(d)) == GTK_TEXT_DIR_RTL) - *x += a.width - aWin.width; - - // now adjust to prevent the box from going offscreen - screen = gtk_widget_get_screen(GTK_WIDGET(d)); - gdk_screen_get_monitor_workarea(screen, - gdk_screen_get_monitor_at_window(screen, window), - &workarea); - if (*x < workarea.x) // too far to the left? - *x = workarea.x; - else if (*x + aWin.width > (workarea.x + workarea.width)) // too far to the right? - *x = (workarea.x + workarea.width) - aWin.width; - // this isn't the same algorithm used by GtkComboBox - // first, get our two choices; *y for down and otherY for up - otherY = *y - aWin.height; - *y += a.height; - // and use otherY if we're too low - if (*y + aWin.height >= workarea.y + workarea.height) - *y = otherY; -} - -static void showPopup(dateTimePickerWidget *d) -{ - GtkWidget *toplevel; - gint x, y; - - // GtkComboBox does it - toplevel = gtk_widget_get_toplevel(GTK_WIDGET(d)); - if (GTK_IS_WINDOW(toplevel)) - gtk_window_group_add_window(gtk_window_get_group(GTK_WINDOW(toplevel)), GTK_WINDOW(d->window)); - - allocationToScreen(d, &x, &y); - gtk_window_move(GTK_WINDOW(d->window), x, y); - - gtk_widget_show(d->window); - setActive(d, TRUE); - - if (!startGrab(d)) - hidePopup(d); -} - -static void onToggled(GtkToggleButton *b, gpointer data) -{ - dateTimePickerWidget *d = dateTimePickerWidget(b); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(d))) - showPopup(d); - else - hidePopup(d); -} - -static gboolean grabBroken(GtkWidget *w, GdkEventGrabBroken *e, gpointer data) -{ - dateTimePickerWidget *d = dateTimePickerWidget(data); - - hidePopup(d); - return TRUE; // this is what GtkComboBox does -} - -static gboolean buttonReleased(GtkWidget *w, GdkEventButton *e, gpointer data) -{ - dateTimePickerWidget *d = dateTimePickerWidget(data); - int winx, winy; - GtkAllocation wina; - gboolean in; - - gtk_widget_get_allocation(d->window, &wina); - winx = 0; - winy = 0; - if (!gtk_widget_get_has_window(d->window)) { - winx = wina.x; - winy = wina.y; - } - gdk_window_get_root_coords(gtk_widget_get_window(d->window), winx, winy, &winx, &winy); - in = TRUE; - if (e->x_root < winx) - in = FALSE; - if (e->x_root >= (winx + wina.width)) - in = FALSE; - if (e->y_root < winy) - in = FALSE; - if (e->y_root >= (winy + wina.height)) - in = FALSE; - if (!in) - hidePopup(d); - return TRUE; // this is what GtkComboBox does -} - -static gint hoursSpinboxInput(GtkSpinButton *sb, gpointer ptr, gpointer data) -{ - double *out = (double *) ptr; - const gchar *text; - int value; - - text = gtk_entry_get_text(GTK_ENTRY(sb)); - value = (int) g_strtod(text, NULL); - if (value < 0 || value > 12) - return GTK_INPUT_ERROR; - if (value == 12) // 12 to the user is 0 internally - value = 0; - *out = (double) value; - return TRUE; -} - -static gboolean hoursSpinboxOutput(GtkSpinButton *sb, gpointer data) -{ - gchar *text; - int value; - - value = realSpinValue(sb); - if (value == 0) // 0 internally is 12 to the user - value = 12; - text = g_strdup_printf("%d", value); - gtk_entry_set_text(GTK_ENTRY(sb), text); - g_free(text); - return TRUE; -} - -static gboolean zeroPadSpinbox(GtkSpinButton *sb, gpointer data) -{ - gchar *text; - int value; - - value = realSpinValue(sb); - text = g_strdup_printf("%02d", value); - gtk_entry_set_text(GTK_ENTRY(sb), text); - g_free(text); - return TRUE; -} - -// this is really hacky but we can't use GtkCombobox here :( -static gint ampmSpinboxInput(GtkSpinButton *sb, gpointer ptr, gpointer data) -{ - double *out = (double *) ptr; - const gchar *text; - char firstAM, firstPM; - - text = gtk_entry_get_text(GTK_ENTRY(sb)); - // LONGTERM don't use ASCII here for case insensitivity - firstAM = g_ascii_tolower(nl_langinfo(AM_STR)[0]); - firstPM = g_ascii_tolower(nl_langinfo(PM_STR)[0]); - for (; *text != '\0'; text++) - if (g_ascii_tolower(*text) == firstAM) { - *out = 0; - return TRUE; - } else if (g_ascii_tolower(*text) == firstPM) { - *out = 1; - return TRUE; - } - return GTK_INPUT_ERROR; -} - -static gboolean ampmSpinboxOutput(GtkSpinButton *sb, gpointer data) -{ - int value; - - value = gtk_spin_button_get_value_as_int(sb); - if (value == 0) - gtk_entry_set_text(GTK_ENTRY(sb), nl_langinfo(AM_STR)); - else - gtk_entry_set_text(GTK_ENTRY(sb), nl_langinfo(PM_STR)); - return TRUE; -} - -static void spinboxChanged(GtkSpinButton *sb, gpointer data) -{ - dateTimePickerWidget *d = dateTimePickerWidget(data); - - dateTimeChanged(d); -} - -static GtkWidget *newSpinbox(dateTimePickerWidget *d, int min, int max, gint (*input)(GtkSpinButton *, gpointer, gpointer), gboolean (*output)(GtkSpinButton *, gpointer), gulong *block) -{ - GtkWidget *sb; - - sb = gtk_spin_button_new_with_range(min, max, 1); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(sb), 0); - gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(sb), TRUE); - gtk_orientable_set_orientation(GTK_ORIENTABLE(sb), GTK_ORIENTATION_VERTICAL); - *block = g_signal_connect(sb, "value-changed", G_CALLBACK(spinboxChanged), d); - if (input != NULL) - g_signal_connect(sb, "input", G_CALLBACK(input), NULL); - if (output != NULL) - g_signal_connect(sb, "output", G_CALLBACK(output), NULL); - return sb; -} - -static void dateChanged(GtkCalendar *c, gpointer data) -{ - dateTimePickerWidget *d = dateTimePickerWidget(data); - - dateTimeChanged(d); -} - -static void setDateOnly(dateTimePickerWidget *d) -{ - d->hasTime = FALSE; - gtk_container_remove(GTK_CONTAINER(d->box), d->timebox); -} - -static void setTimeOnly(dateTimePickerWidget *d) -{ - d->hasDate = FALSE; - gtk_container_remove(GTK_CONTAINER(d->box), d->calendar); -} - -static void dateTimePickerWidget_init(dateTimePickerWidget *d) -{ - GDateTime *dt; - gint year, month, day; - gint hour; - gulong calendarBlock; - - d->window = gtk_window_new(GTK_WINDOW_POPUP); - gtk_window_set_resizable(GTK_WINDOW(d->window), FALSE); - gtk_window_set_attached_to(GTK_WINDOW(d->window), GTK_WIDGET(d)); - gtk_window_set_decorated(GTK_WINDOW(d->window), FALSE); - gtk_window_set_deletable(GTK_WINDOW(d->window), FALSE); - gtk_window_set_type_hint(GTK_WINDOW(d->window), GDK_WINDOW_TYPE_HINT_COMBO); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(d->window), TRUE); - gtk_window_set_skip_pager_hint(GTK_WINDOW(d->window), TRUE); - gtk_window_set_has_resize_grip(GTK_WINDOW(d->window), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(d->window), 12); - // and make it stand out a bit - gtk_style_context_add_class(gtk_widget_get_style_context(d->window), "frame"); - - d->box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); - gtk_container_add(GTK_CONTAINER(d->window), d->box); - - d->calendar = gtk_calendar_new(); - calendarBlock = g_signal_connect(d->calendar, "day-selected", G_CALLBACK(dateChanged), d); - gtk_container_add(GTK_CONTAINER(d->box), d->calendar); - - d->timebox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); - gtk_widget_set_valign(d->timebox, GTK_ALIGN_CENTER); - gtk_container_add(GTK_CONTAINER(d->box), d->timebox); - - d->hours = newSpinbox(d, 0, 11, hoursSpinboxInput, hoursSpinboxOutput, &(d->hoursBlock)); - gtk_container_add(GTK_CONTAINER(d->timebox), d->hours); - - gtk_container_add(GTK_CONTAINER(d->timebox), - gtk_label_new(":")); - - d->minutes = newSpinbox(d, 0, 59, NULL, zeroPadSpinbox, &(d->minutesBlock)); - gtk_container_add(GTK_CONTAINER(d->timebox), d->minutes); - - gtk_container_add(GTK_CONTAINER(d->timebox), - gtk_label_new(":")); - - d->seconds = newSpinbox(d, 0, 59, NULL, zeroPadSpinbox, &(d->secondsBlock)); - gtk_container_add(GTK_CONTAINER(d->timebox), d->seconds); - - // LONGTERM this should be the case, but that interferes with grabs - // switch to it when we can drop GTK+ 3.10 and use popovers -#if 0 - d->ampm = gtk_combo_box_text_new(); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(d->ampm), NULL, "AM"); - gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(d->ampm), NULL, "PM"); -#endif - d->ampm = newSpinbox(d, 0, 1, ampmSpinboxInput, ampmSpinboxOutput, &(d->ampmBlock)); - gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(d->ampm), FALSE); - gtk_widget_set_valign(d->ampm, GTK_ALIGN_CENTER); - gtk_container_add(GTK_CONTAINER(d->timebox), d->ampm); - - gtk_widget_show_all(d->box); - - g_signal_connect(d->window, "grab-broken-event", G_CALLBACK(grabBroken), d); - g_signal_connect(d->window, "button-release-event", G_CALLBACK(buttonReleased), d); - - d->toggledSignal = g_signal_connect(d, "toggled", G_CALLBACK(onToggled), NULL); - d->keyboard = NULL; - d->mouse = NULL; - - d->hasTime = TRUE; - d->hasDate = TRUE; - - // set the current date/time - // notice how we block signals from firing - dt = g_date_time_new_now_local(); - g_date_time_get_ymd(dt, &year, &month, &day); - month--; // GDateTime/GtkCalendar differences - g_signal_handler_block(d->calendar, calendarBlock); - gtk_calendar_select_month(GTK_CALENDAR(d->calendar), month, year); - gtk_calendar_select_day(GTK_CALENDAR(d->calendar), day); - g_signal_handler_unblock(d->calendar, calendarBlock); - hour = g_date_time_get_hour(dt); - if (hour >= 12) { - hour -= 12; - setRealSpinValue(GTK_SPIN_BUTTON(d->ampm), 1, d->ampmBlock); - } - setRealSpinValue(GTK_SPIN_BUTTON(d->hours), hour, d->hoursBlock); - setRealSpinValue(GTK_SPIN_BUTTON(d->minutes), g_date_time_get_minute(dt), d->minutesBlock); - setRealSpinValue(GTK_SPIN_BUTTON(d->seconds), g_date_time_get_seconds(dt), d->secondsBlock); - g_date_time_unref(dt); -} - -static void dateTimePickerWidget_dispose(GObject *obj) -{ - dateTimePickerWidget *d = dateTimePickerWidget(obj); - - if (d->window != NULL) { - gtk_widget_destroy(d->window); - d->window = NULL; - } - G_OBJECT_CLASS(dateTimePickerWidget_parent_class)->dispose(obj); -} - -static void dateTimePickerWidget_finalize(GObject *obj) -{ - G_OBJECT_CLASS(dateTimePickerWidget_parent_class)->finalize(obj); -} - -static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) -{ - G_OBJECT_CLASS(class)->dispose = dateTimePickerWidget_dispose; - G_OBJECT_CLASS(class)->finalize = dateTimePickerWidget_finalize; -} - -static GtkWidget *newDTP(void) -{ - GtkWidget *w; - - w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL)); - setLabel(dateTimePickerWidget(w)); - return w; -} - -static GtkWidget *newDP(void) -{ - GtkWidget *w; - - w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL)); - setDateOnly(dateTimePickerWidget(w)); - setLabel(dateTimePickerWidget(w)); - return w; -} - -static GtkWidget *newTP(void) -{ - GtkWidget *w; - - w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL)); - setTimeOnly(dateTimePickerWidget(w)); - setLabel(dateTimePickerWidget(w)); - return w; -} - -struct uiDateTimePicker { - uiUnixControl c; - GtkWidget *widget; - dateTimePickerWidget *d; -}; - -uiUnixControlAllDefaults(uiDateTimePicker) - -uiDateTimePicker *finishNewDateTimePicker(GtkWidget *(*fn)(void)) -{ - uiDateTimePicker *d; - - uiUnixNewControl(uiDateTimePicker, d); - - d->widget = (*fn)(); - d->d = dateTimePickerWidget(d->widget); - - return d; -} - -uiDateTimePicker *uiNewDateTimePicker(void) -{ - return finishNewDateTimePicker(newDTP); -} - -uiDateTimePicker *uiNewDatePicker(void) -{ - return finishNewDateTimePicker(newDP); -} - -uiDateTimePicker *uiNewTimePicker(void) -{ - return finishNewDateTimePicker(newTP); -} diff --git a/src/libui_sdl/libui/unix/debug.c b/src/libui_sdl/libui/unix/debug.c deleted file mode 100644 index c948db62..00000000 --- a/src/libui_sdl/libui/unix/debug.c +++ /dev/null @@ -1,14 +0,0 @@ -// 13 may 2016 -#include "uipriv_unix.h" - -// LONGTERM don't halt on release builds - -void realbug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap) -{ - char *a, *b; - - a = g_strdup_printf("[libui] %s:%s:%s() %s", file, line, func, prefix); - b = g_strdup_vprintf(format, ap); - g_critical("%s%s", a, b); - G_BREAKPOINT(); -} diff --git a/src/libui_sdl/libui/unix/draw.c b/src/libui_sdl/libui/unix/draw.c deleted file mode 100644 index 5befcd37..00000000 --- a/src/libui_sdl/libui/unix/draw.c +++ /dev/null @@ -1,214 +0,0 @@ -// 6 september 2015 -#include "uipriv_unix.h" -#include "draw.h" - -uiDrawContext *newContext(cairo_t *cr) -{ - uiDrawContext *c; - - c = uiNew(uiDrawContext); - c->cr = cr; - return c; -} - -void freeContext(uiDrawContext *c) -{ - uiFree(c); -} - -static cairo_pattern_t *mkbrush(uiDrawBrush *b) -{ - cairo_pattern_t *pat; - size_t i; - - switch (b->Type) { - case uiDrawBrushTypeSolid: - pat = cairo_pattern_create_rgba(b->R, b->G, b->B, b->A); - break; - case uiDrawBrushTypeLinearGradient: - pat = cairo_pattern_create_linear(b->X0, b->Y0, b->X1, b->Y1); - break; - case uiDrawBrushTypeRadialGradient: - // make the start circle radius 0 to make it a point - pat = cairo_pattern_create_radial( - b->X0, b->Y0, 0, - b->X1, b->Y1, b->OuterRadius); - break; -// case uiDrawBrushTypeImage: - } - if (cairo_pattern_status(pat) != CAIRO_STATUS_SUCCESS) - implbug("error creating pattern in mkbrush(): %s", - cairo_status_to_string(cairo_pattern_status(pat))); - switch (b->Type) { - case uiDrawBrushTypeLinearGradient: - case uiDrawBrushTypeRadialGradient: - for (i = 0; i < b->NumStops; i++) - cairo_pattern_add_color_stop_rgba(pat, - b->Stops[i].Pos, - b->Stops[i].R, - b->Stops[i].G, - b->Stops[i].B, - b->Stops[i].A); - } - return pat; -} - -void uiDrawStroke(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b, uiDrawStrokeParams *p) -{ - cairo_pattern_t *pat; - - runPath(path, c->cr); - pat = mkbrush(b); - cairo_set_source(c->cr, pat); - switch (p->Cap) { - case uiDrawLineCapFlat: - cairo_set_line_cap(c->cr, CAIRO_LINE_CAP_BUTT); - break; - case uiDrawLineCapRound: - cairo_set_line_cap(c->cr, CAIRO_LINE_CAP_ROUND); - break; - case uiDrawLineCapSquare: - cairo_set_line_cap(c->cr, CAIRO_LINE_CAP_SQUARE); - break; - } - switch (p->Join) { - case uiDrawLineJoinMiter: - cairo_set_line_join(c->cr, CAIRO_LINE_JOIN_MITER); - cairo_set_miter_limit(c->cr, p->MiterLimit); - break; - case uiDrawLineJoinRound: - cairo_set_line_join(c->cr, CAIRO_LINE_JOIN_ROUND); - break; - case uiDrawLineJoinBevel: - cairo_set_line_join(c->cr, CAIRO_LINE_JOIN_BEVEL); - break; - } - cairo_set_line_width(c->cr, p->Thickness); - cairo_set_dash(c->cr, p->Dashes, p->NumDashes, p->DashPhase); - cairo_stroke(c->cr); - cairo_pattern_destroy(pat); -} - -void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b) -{ - cairo_pattern_t *pat; - - runPath(path, c->cr); - pat = mkbrush(b); - cairo_set_source(c->cr, pat); - switch (pathFillMode(path)) { - case uiDrawFillModeWinding: - cairo_set_fill_rule(c->cr, CAIRO_FILL_RULE_WINDING); - break; - case uiDrawFillModeAlternate: - cairo_set_fill_rule(c->cr, CAIRO_FILL_RULE_EVEN_ODD); - break; - } - cairo_fill(c->cr); - cairo_pattern_destroy(pat); -} - -void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m) -{ - cairo_matrix_t cm; - - m2c(m, &cm); - cairo_transform(c->cr, &cm); -} - -void uiDrawClip(uiDrawContext *c, uiDrawPath *path) -{ - runPath(path, c->cr); - switch (pathFillMode(path)) { - case uiDrawFillModeWinding: - cairo_set_fill_rule(c->cr, CAIRO_FILL_RULE_WINDING); - break; - case uiDrawFillModeAlternate: - cairo_set_fill_rule(c->cr, CAIRO_FILL_RULE_EVEN_ODD); - break; - } - cairo_clip(c->cr); -} - -void uiDrawSave(uiDrawContext *c) -{ - cairo_save(c->cr); -} - -void uiDrawRestore(uiDrawContext *c) -{ - cairo_restore(c->cr); -} - - -// bitmap API - -uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha) -{ - uiDrawBitmap* bmp; - - bmp = uiNew(uiDrawBitmap); - - bmp->bmp = cairo_image_surface_create(alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, width, height); - if (cairo_surface_status(bmp->bmp) != CAIRO_STATUS_SUCCESS) - implbug("error creating bitmap: %s", - cairo_status_to_string(cairo_surface_status(bmp->bmp))); - - bmp->Width = width; - bmp->Height = height; - bmp->Stride = cairo_image_surface_get_stride(bmp->bmp); - - return bmp; -} - -void uiDrawBitmapUpdate(uiDrawBitmap* bmp, const void* data) -{ - const unsigned char* src = data; - unsigned char* dst = cairo_image_surface_get_data(bmp->bmp); - - if (bmp->Stride == bmp->Width*4) - { - // stride 'good', can just directly copy all the shit - memcpy(dst, src, bmp->Stride*bmp->Height); - } - else - { - int y; - for (y = 0; y < bmp->Height; y++) - { - memcpy(dst, src, bmp->Width*4); - src += bmp->Width*4; - dst += bmp->Stride; - } - } - - cairo_surface_mark_dirty(bmp->bmp); -} - -void uiDrawBitmapDraw(uiDrawContext* c, uiDrawBitmap* bmp, uiRect* srcrect, uiRect* dstrect, int filter) -{ - cairo_save(c->cr); - cairo_rectangle(c->cr, dstrect->X, dstrect->Y, dstrect->Width, dstrect->Height); - - cairo_translate(c->cr, dstrect->X, dstrect->Y); - if ((dstrect->Width != srcrect->Width) || (dstrect->Height != srcrect->Height)) - { - // scale shit if needed - double sx = dstrect->Width / (double)srcrect->Width; - double sy = dstrect->Height / (double)srcrect->Height; - cairo_scale(c->cr, sx, sy); - } - - cairo_set_source_surface(c->cr, bmp->bmp, -srcrect->X, -srcrect->Y); - cairo_pattern_set_filter(cairo_get_source(c->cr), filter ? CAIRO_FILTER_BILINEAR : CAIRO_FILTER_NEAREST); - cairo_clip(c->cr); - cairo_paint(c->cr); - - cairo_restore(c->cr); -} - -void uiDrawFreeBitmap(uiDrawBitmap* bmp) -{ - cairo_surface_destroy(bmp->bmp); - uiFree(bmp); -} diff --git a/src/libui_sdl/libui/unix/draw.h b/src/libui_sdl/libui/unix/draw.h deleted file mode 100644 index 869acd18..00000000 --- a/src/libui_sdl/libui/unix/draw.h +++ /dev/null @@ -1,21 +0,0 @@ -// 5 may 2016 - -// draw.c -struct uiDrawContext { - cairo_t *cr; -}; - -struct uiDrawBitmap { - int Width; - int Height; - int Stride; - - cairo_surface_t* bmp; -}; - -// drawpath.c -extern void runPath(uiDrawPath *p, cairo_t *cr); -extern uiDrawFillMode pathFillMode(uiDrawPath *path); - -// drawmatrix.c -extern void m2c(uiDrawMatrix *m, cairo_matrix_t *c); diff --git a/src/libui_sdl/libui/unix/drawmatrix.c b/src/libui_sdl/libui/unix/drawmatrix.c deleted file mode 100644 index f12b3036..00000000 --- a/src/libui_sdl/libui/unix/drawmatrix.c +++ /dev/null @@ -1,115 +0,0 @@ -// 6 september 2015 -#include "uipriv_unix.h" -#include "draw.h" - -void m2c(uiDrawMatrix *m, cairo_matrix_t *c) -{ - c->xx = m->M11; - c->yx = m->M12; - c->xy = m->M21; - c->yy = m->M22; - c->x0 = m->M31; - c->y0 = m->M32; -} - -static void c2m(cairo_matrix_t *c, uiDrawMatrix *m) -{ - m->M11 = c->xx; - m->M12 = c->yx; - m->M21 = c->xy; - m->M22 = c->yy; - m->M31 = c->x0; - m->M32 = c->y0; -} - -void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y) -{ - cairo_matrix_t c; - cairo_matrix_t tmp; - - m2c(m, &c); - cairo_matrix_init_translate(&tmp, x, y); - cairo_matrix_multiply(&c, &c, &tmp); - c2m(&c, m); -} - -void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) -{ - cairo_matrix_t c; - cairo_matrix_t tmp; - double xt, yt; - - m2c(m, &c); - xt = x; - yt = y; - scaleCenter(xCenter, yCenter, &xt, &yt); - cairo_matrix_init_translate(&tmp, xt, yt); - cairo_matrix_scale(&tmp, x, y); - cairo_matrix_translate(&tmp, -xt, -yt); - cairo_matrix_multiply(&c, &c, &tmp); - c2m(&c, m); -} - -void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount) -{ - cairo_matrix_t c; - cairo_matrix_t tmp; - - m2c(m, &c); - cairo_matrix_init_translate(&tmp, x, y); - cairo_matrix_rotate(&tmp, amount); - cairo_matrix_translate(&tmp, -x, -y); - cairo_matrix_multiply(&c, &c, &tmp); - c2m(&c, m); -} - -void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount) -{ - fallbackSkew(m, x, y, xamount, yamount); -} - -void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src) -{ - cairo_matrix_t c; - cairo_matrix_t d; - - m2c(dest, &c); - m2c(src, &d); - cairo_matrix_multiply(&c, &c, &d); - c2m(&c, dest); -} - -int uiDrawMatrixInvertible(uiDrawMatrix *m) -{ - cairo_matrix_t c; - - m2c(m, &c); - return cairo_matrix_invert(&c) == CAIRO_STATUS_SUCCESS; -} - -int uiDrawMatrixInvert(uiDrawMatrix *m) -{ - cairo_matrix_t c; - - m2c(m, &c); - if (cairo_matrix_invert(&c) != CAIRO_STATUS_SUCCESS) - return 0; - c2m(&c, m); - return 1; -} - -void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y) -{ - cairo_matrix_t c; - - m2c(m, &c); - cairo_matrix_transform_point(&c, x, y); -} - -void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y) -{ - cairo_matrix_t c; - - m2c(m, &c); - cairo_matrix_transform_distance(&c, x, y); -} diff --git a/src/libui_sdl/libui/unix/drawpath.c b/src/libui_sdl/libui/unix/drawpath.c deleted file mode 100644 index a0165fb8..00000000 --- a/src/libui_sdl/libui/unix/drawpath.c +++ /dev/null @@ -1,199 +0,0 @@ -// 6 september 2015 -#include "uipriv_unix.h" -#include "draw.h" - -struct uiDrawPath { - GArray *pieces; - uiDrawFillMode fillMode; - gboolean ended; -}; - -struct piece { - int type; - double d[8]; - int b; -}; - -enum { - newFigure, - newFigureArc, - lineTo, - arcTo, - bezierTo, - closeFigure, - addRect, -}; - -uiDrawPath *uiDrawNewPath(uiDrawFillMode mode) -{ - uiDrawPath *p; - - p = uiNew(uiDrawPath); - p->pieces = g_array_new(FALSE, TRUE, sizeof (struct piece)); - p->fillMode = mode; - return p; -} - -void uiDrawFreePath(uiDrawPath *p) -{ - g_array_free(p->pieces, TRUE); - uiFree(p); -} - -static void add(uiDrawPath *p, struct piece *piece) -{ - if (p->ended) - userbug("You cannot modify a uiDrawPath that has been ended. (path: %p)", p); - g_array_append_vals(p->pieces, piece, 1); -} - -void uiDrawPathNewFigure(uiDrawPath *p, double x, double y) -{ - struct piece piece; - - piece.type = newFigure; - piece.d[0] = x; - piece.d[1] = y; - add(p, &piece); -} - -void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) -{ - struct piece piece; - - if (sweep > 2 * uiPi) - sweep = 2 * uiPi; - piece.type = newFigureArc; - piece.d[0] = xCenter; - piece.d[1] = yCenter; - piece.d[2] = radius; - piece.d[3] = startAngle; - piece.d[4] = sweep; - piece.b = negative; - add(p, &piece); -} - -void uiDrawPathLineTo(uiDrawPath *p, double x, double y) -{ - struct piece piece; - - piece.type = lineTo; - piece.d[0] = x; - piece.d[1] = y; - add(p, &piece); -} - -void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) -{ - struct piece piece; - - if (sweep > 2 * uiPi) - sweep = 2 * uiPi; - piece.type = arcTo; - piece.d[0] = xCenter; - piece.d[1] = yCenter; - piece.d[2] = radius; - piece.d[3] = startAngle; - piece.d[4] = sweep; - piece.b = negative; - add(p, &piece); -} - -void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY) -{ - struct piece piece; - - piece.type = bezierTo; - piece.d[0] = c1x; - piece.d[1] = c1y; - piece.d[2] = c2x; - piece.d[3] = c2y; - piece.d[4] = endX; - piece.d[5] = endY; - add(p, &piece); -} - -void uiDrawPathCloseFigure(uiDrawPath *p) -{ - struct piece piece; - - piece.type = closeFigure; - add(p, &piece); -} - -void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height) -{ - struct piece piece; - - piece.type = addRect; - piece.d[0] = x; - piece.d[1] = y; - piece.d[2] = width; - piece.d[3] = height; - add(p, &piece); -} - -void uiDrawPathEnd(uiDrawPath *p) -{ - p->ended = TRUE; -} - -void runPath(uiDrawPath *p, cairo_t *cr) -{ - guint i; - struct piece *piece; - void (*arc)(cairo_t *, double, double, double, double, double); - - if (!p->ended) - userbug("You cannot draw with a uiDrawPath that has not been ended. (path: %p)", p); - cairo_new_path(cr); - for (i = 0; i < p->pieces->len; i++) { - piece = &g_array_index(p->pieces, struct piece, i); - switch (piece->type) { - case newFigure: - cairo_move_to(cr, piece->d[0], piece->d[1]); - break; - case newFigureArc: - cairo_new_sub_path(cr); - // fall through - case arcTo: - arc = cairo_arc; - if (piece->b) - arc = cairo_arc_negative; - (*arc)(cr, - piece->d[0], - piece->d[1], - piece->d[2], - piece->d[3], - piece->d[3] + piece->d[4]); - break; - case lineTo: - cairo_line_to(cr, piece->d[0], piece->d[1]); - break; - case bezierTo: - cairo_curve_to(cr, - piece->d[0], - piece->d[1], - piece->d[2], - piece->d[3], - piece->d[4], - piece->d[5]); - break; - case closeFigure: - cairo_close_path(cr); - break; - case addRect: - cairo_rectangle(cr, - piece->d[0], - piece->d[1], - piece->d[2], - piece->d[3]); - break; - } - } -} - -uiDrawFillMode pathFillMode(uiDrawPath *path) -{ - return path->fillMode; -} diff --git a/src/libui_sdl/libui/unix/drawtext.c b/src/libui_sdl/libui/unix/drawtext.c deleted file mode 100644 index 7078e1ac..00000000 --- a/src/libui_sdl/libui/unix/drawtext.c +++ /dev/null @@ -1,293 +0,0 @@ -// 6 september 2015 -#include "uipriv_unix.h" -#include "draw.h" - -struct uiDrawFontFamilies { - PangoFontFamily **f; - int n; -}; - -uiDrawFontFamilies *uiDrawListFontFamilies(void) -{ - uiDrawFontFamilies *ff; - PangoFontMap *map; - - ff = uiNew(uiDrawFontFamilies); - map = pango_cairo_font_map_get_default(); - pango_font_map_list_families(map, &(ff->f), &(ff->n)); - // do not free map; it's a shared resource - return ff; -} - -int uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff) -{ - return ff->n; -} - -char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, int n) -{ - PangoFontFamily *f; - - f = ff->f[n]; - return uiUnixStrdupText(pango_font_family_get_name(f)); -} - -void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff) -{ - g_free(ff->f); - uiFree(ff); -} - -struct uiDrawTextFont { - PangoFont *f; -}; - -uiDrawTextFont *mkTextFont(PangoFont *f, gboolean ref) -{ - uiDrawTextFont *font; - - font = uiNew(uiDrawTextFont); - font->f = f; - if (ref) - g_object_ref(font->f); - return font; -} - -static const PangoWeight pangoWeights[] = { - [uiDrawTextWeightThin] = PANGO_WEIGHT_THIN, - [uiDrawTextWeightUltraLight] = PANGO_WEIGHT_ULTRALIGHT, - [uiDrawTextWeightLight] = PANGO_WEIGHT_LIGHT, - [uiDrawTextWeightBook] = PANGO_WEIGHT_BOOK, - [uiDrawTextWeightNormal] = PANGO_WEIGHT_NORMAL, - [uiDrawTextWeightMedium] = PANGO_WEIGHT_MEDIUM, - [uiDrawTextWeightSemiBold] = PANGO_WEIGHT_SEMIBOLD, - [uiDrawTextWeightBold] = PANGO_WEIGHT_BOLD, - [uiDrawTextWeightUltraBold] = PANGO_WEIGHT_ULTRABOLD, - [uiDrawTextWeightHeavy] = PANGO_WEIGHT_HEAVY, - [uiDrawTextWeightUltraHeavy] = PANGO_WEIGHT_ULTRAHEAVY, -}; - -static const PangoStyle pangoItalics[] = { - [uiDrawTextItalicNormal] = PANGO_STYLE_NORMAL, - [uiDrawTextItalicOblique] = PANGO_STYLE_OBLIQUE, - [uiDrawTextItalicItalic] = PANGO_STYLE_ITALIC, -}; - -static const PangoStretch pangoStretches[] = { - [uiDrawTextStretchUltraCondensed] = PANGO_STRETCH_ULTRA_CONDENSED, - [uiDrawTextStretchExtraCondensed] = PANGO_STRETCH_EXTRA_CONDENSED, - [uiDrawTextStretchCondensed] = PANGO_STRETCH_CONDENSED, - [uiDrawTextStretchSemiCondensed] = PANGO_STRETCH_SEMI_CONDENSED, - [uiDrawTextStretchNormal] = PANGO_STRETCH_NORMAL, - [uiDrawTextStretchSemiExpanded] = PANGO_STRETCH_SEMI_EXPANDED, - [uiDrawTextStretchExpanded] = PANGO_STRETCH_EXPANDED, - [uiDrawTextStretchExtraExpanded] = PANGO_STRETCH_EXTRA_EXPANDED, - [uiDrawTextStretchUltraExpanded] = PANGO_STRETCH_ULTRA_EXPANDED, -}; - -// we need a context for a few things -// the documentation suggests creating cairo_t-specific, GdkScreen-specific, or even GtkWidget-specific contexts, but we can't really do that because we want our uiDrawTextFonts and uiDrawTextLayouts to be context-independent -// we could use pango_font_map_create_context(pango_cairo_font_map_get_default()) but that will ignore GDK-specific settings -// so let's use gdk_pango_context_get() instead; even though it's for the default screen only, it's good enough for us -#define mkGenericPangoCairoContext() (gdk_pango_context_get()) - -PangoFont *pangoDescToPangoFont(PangoFontDescription *pdesc) -{ - PangoFont *f; - PangoContext *context; - - // in this case, the context is necessary for the metrics to be correct - context = mkGenericPangoCairoContext(); - f = pango_font_map_load_font(pango_cairo_font_map_get_default(), context, pdesc); - if (f == NULL) { - // LONGTERM - g_error("[libui] no match in pangoDescToPangoFont(); report to andlabs"); - } - g_object_unref(context); - return f; -} - -uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc) -{ - PangoFont *f; - PangoFontDescription *pdesc; - - pdesc = pango_font_description_new(); - pango_font_description_set_family(pdesc, - desc->Family); - pango_font_description_set_size(pdesc, - (gint) (desc->Size * PANGO_SCALE)); - pango_font_description_set_weight(pdesc, - pangoWeights[desc->Weight]); - pango_font_description_set_style(pdesc, - pangoItalics[desc->Italic]); - pango_font_description_set_stretch(pdesc, - pangoStretches[desc->Stretch]); - f = pangoDescToPangoFont(pdesc); - pango_font_description_free(pdesc); - return mkTextFont(f, FALSE); // we hold the initial reference; no need to ref -} - -void uiDrawFreeTextFont(uiDrawTextFont *font) -{ - g_object_unref(font->f); - uiFree(font); -} - -uintptr_t uiDrawTextFontHandle(uiDrawTextFont *font) -{ - return (uintptr_t) (font->f); -} - -void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc) -{ - PangoFontDescription *pdesc; - - // this creates a copy; we free it later - pdesc = pango_font_describe(font->f); - - // TODO - - pango_font_description_free(pdesc); -} - -// See https://developer.gnome.org/pango/1.30/pango-Cairo-Rendering.html#pango-Cairo-Rendering.description -// Note that we convert to double before dividing to make sure the floating-point stuff is right -#define pangoToCairo(pango) (((double) (pango)) / PANGO_SCALE) -#define cairoToPango(cairo) ((gint) ((cairo) * PANGO_SCALE)) - -void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics) -{ - PangoFontMetrics *pm; - - pm = pango_font_get_metrics(font->f, NULL); - metrics->Ascent = pangoToCairo(pango_font_metrics_get_ascent(pm)); - metrics->Descent = pangoToCairo(pango_font_metrics_get_descent(pm)); - // Pango doesn't seem to expose this :( Use 0 and hope for the best. - metrics->Leading = 0; - metrics->UnderlinePos = pangoToCairo(pango_font_metrics_get_underline_position(pm)); - metrics->UnderlineThickness = pangoToCairo(pango_font_metrics_get_underline_thickness(pm)); - pango_font_metrics_unref(pm); -} - -// note: PangoCairoLayouts are tied to a given cairo_t, so we can't store one in this device-independent structure -struct uiDrawTextLayout { - char *s; - ptrdiff_t *graphemes; - PangoFont *defaultFont; - double width; - PangoAttrList *attrs; -}; - -uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width) -{ - uiDrawTextLayout *layout; - PangoContext *context; - - layout = uiNew(uiDrawTextLayout); - layout->s = g_strdup(text); - context = mkGenericPangoCairoContext(); - layout->graphemes = graphemes(layout->s, context); - g_object_unref(context); - layout->defaultFont = defaultFont->f; - g_object_ref(layout->defaultFont); // retain a copy - uiDrawTextLayoutSetWidth(layout, width); - layout->attrs = pango_attr_list_new(); - return layout; -} - -void uiDrawFreeTextLayout(uiDrawTextLayout *layout) -{ - pango_attr_list_unref(layout->attrs); - g_object_unref(layout->defaultFont); - uiFree(layout->graphemes); - g_free(layout->s); - uiFree(layout); -} - -void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width) -{ - layout->width = width; -} - -static void prepareLayout(uiDrawTextLayout *layout, PangoLayout *pl) -{ - PangoFontDescription *desc; - int width; - - pango_layout_set_text(pl, layout->s, -1); - - // again, this makes a copy - desc = pango_font_describe(layout->defaultFont); - // this is safe; the description is copied - pango_layout_set_font_description(pl, desc); - pango_font_description_free(desc); - - width = cairoToPango(layout->width); - if (layout->width < 0) - width = -1; - pango_layout_set_width(pl, width); - - pango_layout_set_attributes(pl, layout->attrs); -} - -void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height) -{ - PangoContext *context; - PangoLayout *pl; - PangoRectangle logical; - - // in this case, the context is necessary to create the layout - // the layout takes a ref on the context so we can unref it afterward - context = mkGenericPangoCairoContext(); - pl = pango_layout_new(context); - g_object_unref(context); - prepareLayout(layout, pl); - - pango_layout_get_extents(pl, NULL, &logical); - - g_object_unref(pl); - - *width = pangoToCairo(logical.width); - *height = pangoToCairo(logical.height); -} - -void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout) -{ - PangoLayout *pl; - - pl = pango_cairo_create_layout(c->cr); - prepareLayout(layout, pl); - - cairo_move_to(c->cr, x, y); - pango_cairo_show_layout(c->cr, pl); - - g_object_unref(pl); -} - -static void addAttr(uiDrawTextLayout *layout, PangoAttribute *attr, int startChar, int endChar) -{ - attr->start_index = layout->graphemes[startChar]; - attr->end_index = layout->graphemes[endChar]; - pango_attr_list_insert(layout->attrs, attr); - // pango_attr_list_insert() takes attr; we don't free it -} - -void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar, int endChar, double r, double g, double b, double a) -{ - PangoAttribute *attr; - guint16 rr, gg, bb, aa; - - rr = (guint16) (r * 65535); - gg = (guint16) (g * 65535); - bb = (guint16) (b * 65535); - aa = (guint16) (a * 65535); - - attr = pango_attr_foreground_new(rr, gg, bb); - addAttr(layout, attr, startChar, endChar); - - // TODO what if aa == 0? - attr = FUTURE_pango_attr_foreground_alpha_new(aa); - if (attr != NULL) - addAttr(layout, attr, startChar, endChar); -} diff --git a/src/libui_sdl/libui/unix/editablecombo.c b/src/libui_sdl/libui/unix/editablecombo.c deleted file mode 100644 index 7ee3829e..00000000 --- a/src/libui_sdl/libui/unix/editablecombo.c +++ /dev/null @@ -1,79 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiEditableCombobox { - uiUnixControl c; - GtkWidget *widget; - GtkBin *bin; - GtkComboBox *combobox; - GtkComboBoxText *comboboxText; - void (*onChanged)(uiEditableCombobox *, void *); - void *onChangedData; - gulong onChangedSignal; -}; - -uiUnixControlAllDefaults(uiEditableCombobox) - -static void onChanged(GtkComboBox *cbox, gpointer data) -{ - uiEditableCombobox *c = uiEditableCombobox(data); - - (*(c->onChanged))(c, c->onChangedData); -} - -static void defaultOnChanged(uiEditableCombobox *c, void *data) -{ - // do nothing -} - -void uiEditableComboboxAppend(uiEditableCombobox *c, const char *text) -{ - gtk_combo_box_text_append(c->comboboxText, NULL, text); -} - -char *uiEditableComboboxText(uiEditableCombobox *c) -{ - char *s; - char *out; - - s = gtk_combo_box_text_get_active_text(c->comboboxText); - // s will always be non-NULL in the case of a combobox with an entry (according to the source code) - out = uiUnixStrdupText(s); - g_free(s); - return out; -} - -void uiEditableComboboxSetText(uiEditableCombobox *c, const char *text) -{ - GtkEntry *e; - - // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise - g_signal_handler_block(c->combobox, c->onChangedSignal); - // since there isn't a gtk_combo_box_text_set_active_text()... - e = GTK_ENTRY(gtk_bin_get_child(c->bin)); - gtk_entry_set_text(e, text); - g_signal_handler_unblock(c->combobox, c->onChangedSignal); -} - -void uiEditableComboboxOnChanged(uiEditableCombobox *c, void (*f)(uiEditableCombobox *c, void *data), void *data) -{ - c->onChanged = f; - c->onChangedData = data; -} - -uiEditableCombobox *uiNewEditableCombobox(void) -{ - uiEditableCombobox *c; - - uiUnixNewControl(uiEditableCombobox, c); - - c->widget = gtk_combo_box_text_new_with_entry(); - c->bin = GTK_BIN(c->widget); - c->combobox = GTK_COMBO_BOX(c->widget); - c->comboboxText = GTK_COMBO_BOX_TEXT(c->widget); - - c->onChangedSignal = g_signal_connect(c->widget, "changed", G_CALLBACK(onChanged), c); - uiEditableComboboxOnChanged(c, defaultOnChanged, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/unix/entry.c b/src/libui_sdl/libui/unix/entry.c deleted file mode 100644 index 4a9a1d04..00000000 --- a/src/libui_sdl/libui/unix/entry.c +++ /dev/null @@ -1,97 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiEntry { - uiUnixControl c; - GtkWidget *widget; - GtkEntry *entry; - GtkEditable *editable; - void (*onChanged)(uiEntry *, void *); - void *onChangedData; - gulong onChangedSignal; -}; - -uiUnixControlAllDefaults(uiEntry) - -static void onChanged(GtkEditable *editable, gpointer data) -{ - uiEntry *e = uiEntry(data); - - (*(e->onChanged))(e, e->onChangedData); -} - -static void defaultOnChanged(uiEntry *e, void *data) -{ - // do nothing -} - -char *uiEntryText(uiEntry *e) -{ - return uiUnixStrdupText(gtk_entry_get_text(e->entry)); -} - -void uiEntrySetText(uiEntry *e, const char *text) -{ - // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise - g_signal_handler_block(e->editable, e->onChangedSignal); - gtk_entry_set_text(e->entry, text); - g_signal_handler_unblock(e->editable, e->onChangedSignal); - // don't queue the control for resize; entry sizes are independent of their contents -} - -void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) -{ - e->onChanged = f; - e->onChangedData = data; -} - -int uiEntryReadOnly(uiEntry *e) -{ - return gtk_editable_get_editable(e->editable) == FALSE; -} - -void uiEntrySetReadOnly(uiEntry *e, int readonly) -{ - gboolean editable; - - editable = TRUE; - if (readonly) - editable = FALSE; - gtk_editable_set_editable(e->editable, editable); -} - -static uiEntry *finishNewEntry(GtkWidget *w, const gchar *signal) -{ - uiEntry *e; - - uiUnixNewControl(uiEntry, e); - - e->widget = w; - e->entry = GTK_ENTRY(e->widget); - e->editable = GTK_EDITABLE(e->widget); - - e->onChangedSignal = g_signal_connect(e->widget, signal, G_CALLBACK(onChanged), e); - uiEntryOnChanged(e, defaultOnChanged, NULL); - - return e; -} - -uiEntry *uiNewEntry(void) -{ - return finishNewEntry(gtk_entry_new(), "changed"); -} - -uiEntry *uiNewPasswordEntry(void) -{ - GtkWidget *e; - - e = gtk_entry_new(); - gtk_entry_set_visibility(GTK_ENTRY(e), FALSE); - return finishNewEntry(e, "changed"); -} - -// TODO make it use a separate function to be type-safe -uiEntry *uiNewSearchEntry(void) -{ - return finishNewEntry(gtk_search_entry_new(), "search-changed"); -} diff --git a/src/libui_sdl/libui/unix/fontbutton.c b/src/libui_sdl/libui/unix/fontbutton.c deleted file mode 100644 index f8047e08..00000000 --- a/src/libui_sdl/libui/unix/fontbutton.c +++ /dev/null @@ -1,70 +0,0 @@ -// 14 april 2016 -#include "uipriv_unix.h" - -struct uiFontButton { - uiUnixControl c; - GtkWidget *widget; - GtkButton *button; - GtkFontButton *fb; - GtkFontChooser *fc; - void (*onChanged)(uiFontButton *, void *); - void *onChangedData; -}; - -uiUnixControlAllDefaults(uiFontButton) - -// TODO NOTE no need to inhibit the signal; font-set is documented as only being sent when the user changes the font -static void onFontSet(GtkFontButton *button, gpointer data) -{ - uiFontButton *b = uiFontButton(data); - - (*(b->onChanged))(b, b->onChangedData); -} - -static void defaultOnChanged(uiFontButton *b, void *data) -{ - // do nothing -} - -uiDrawTextFont *uiFontButtonFont(uiFontButton *b) -{ - PangoFont *f; - PangoFontDescription *desc; - - desc = gtk_font_chooser_get_font_desc(b->fc); - f = pangoDescToPangoFont(desc); - // desc is transfer-full and thus is a copy - pango_font_description_free(desc); - return mkTextFont(f, FALSE); // we hold the initial reference; no need to ref -} - -void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data) -{ - b->onChanged = f; - b->onChangedData = data; -} - -uiFontButton *uiNewFontButton(void) -{ - uiFontButton *b; - - uiUnixNewControl(uiFontButton, b); - - b->widget = gtk_font_button_new(); - b->button = GTK_BUTTON(b->widget); - b->fb = GTK_FONT_BUTTON(b->widget); - b->fc = GTK_FONT_CHOOSER(b->widget); - - // match behavior on other platforms - gtk_font_button_set_show_style(b->fb, TRUE); - gtk_font_button_set_show_size(b->fb, TRUE); - gtk_font_button_set_use_font(b->fb, FALSE); - gtk_font_button_set_use_size(b->fb, FALSE); - // other customizations - gtk_font_chooser_set_show_preview_entry(b->fc, TRUE); - - g_signal_connect(b->widget, "font-set", G_CALLBACK(onFontSet), b); - uiFontButtonOnChanged(b, defaultOnChanged, NULL); - - return b; -} diff --git a/src/libui_sdl/libui/unix/form.c b/src/libui_sdl/libui/unix/form.c deleted file mode 100644 index 54422b3d..00000000 --- a/src/libui_sdl/libui/unix/form.c +++ /dev/null @@ -1,159 +0,0 @@ -// 8 june 2016 -#include "uipriv_unix.h" - -struct formChild { - uiControl *c; - int stretchy; - GtkWidget *label; - gboolean oldhexpand; - GtkAlign oldhalign; - gboolean oldvexpand; - GtkAlign oldvalign; - GBinding *labelBinding; -}; - -struct uiForm { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *container; - GtkGrid *grid; - GArray *children; - int padded; - GtkSizeGroup *stretchygroup; // ensures all stretchy controls have the same size -}; - -uiUnixControlAllDefaultsExceptDestroy(uiForm) - -#define ctrl(f, i) &g_array_index(f->children, struct formChild, i) - -static void uiFormDestroy(uiControl *c) -{ - uiForm *f = uiForm(c); - struct formChild *fc; - guint i; - - // kill the size group - g_object_unref(f->stretchygroup); - // free all controls - for (i = 0; i < f->children->len; i++) { - fc = ctrl(f, i); - uiControlSetParent(fc->c, NULL); - uiUnixControlSetContainer(uiUnixControl(fc->c), f->container, TRUE); - uiControlDestroy(fc->c); - gtk_widget_destroy(fc->label); - } - g_array_free(f->children, TRUE); - // and then ourselves - g_object_unref(f->widget); - uiFreeControl(uiControl(f)); -} - -void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy) -{ - struct formChild fc; - GtkWidget *widget; - guint row; - - fc.c = c; - widget = GTK_WIDGET(uiControlHandle(fc.c)); - fc.stretchy = stretchy; - fc.oldhexpand = gtk_widget_get_hexpand(widget); - fc.oldhalign = gtk_widget_get_halign(widget); - fc.oldvexpand = gtk_widget_get_vexpand(widget); - fc.oldvalign = gtk_widget_get_valign(widget); - - if (stretchy) { - gtk_widget_set_vexpand(widget, TRUE); - gtk_widget_set_valign(widget, GTK_ALIGN_FILL); - gtk_size_group_add_widget(f->stretchygroup, widget); - } else - gtk_widget_set_vexpand(widget, FALSE); - // and make them fill horizontally - gtk_widget_set_hexpand(widget, TRUE); - gtk_widget_set_halign(widget, GTK_ALIGN_FILL); - - fc.label = gtk_label_new(label); - gtk_widget_set_hexpand(fc.label, FALSE); - gtk_widget_set_halign(fc.label, GTK_ALIGN_END); - gtk_widget_set_vexpand(fc.label, FALSE); - if (GTK_IS_SCROLLED_WINDOW(widget)) - gtk_widget_set_valign(fc.label, GTK_ALIGN_START); - else - gtk_widget_set_valign(fc.label, GTK_ALIGN_CENTER); - gtk_style_context_add_class(gtk_widget_get_style_context(fc.label), "dim-label"); - row = f->children->len; - gtk_grid_attach(f->grid, fc.label, - 0, row, - 1, 1); - // and make them share visibility so if the control is hidden, so is its label - fc.labelBinding = g_object_bind_property(GTK_WIDGET(uiControlHandle(fc.c)), "visible", - fc.label, "visible", - G_BINDING_SYNC_CREATE); - - uiControlSetParent(fc.c, uiControl(f)); - uiUnixControlSetContainer(uiUnixControl(fc.c), f->container, FALSE); - g_array_append_val(f->children, fc); - - // move the widget to the correct place - gtk_container_child_set(f->container, widget, - "left-attach", 1, - "top-attach", row, - NULL); -} - -void uiFormDelete(uiForm *f, int index) -{ - struct formChild *fc; - GtkWidget *widget; - - fc = ctrl(f, index); - widget = GTK_WIDGET(uiControlHandle(fc->c)); - - gtk_widget_destroy(fc->label); - - uiControlSetParent(fc->c, NULL); - uiUnixControlSetContainer(uiUnixControl(fc->c), f->container, TRUE); - - if (fc->stretchy) - gtk_size_group_remove_widget(f->stretchygroup, widget); - gtk_widget_set_hexpand(widget, fc->oldhexpand); - gtk_widget_set_halign(widget, fc->oldhalign); - gtk_widget_set_vexpand(widget, fc->oldvexpand); - gtk_widget_set_valign(widget, fc->oldvalign); - - g_array_remove_index(f->children, index); -} - -int uiFormPadded(uiForm *f) -{ - return f->padded; -} - -void uiFormSetPadded(uiForm *f, int padded) -{ - f->padded = padded; - if (f->padded) { - gtk_grid_set_row_spacing(f->grid, gtkYPadding); - gtk_grid_set_column_spacing(f->grid, gtkXPadding); - } else { - gtk_grid_set_row_spacing(f->grid, 0); - gtk_grid_set_column_spacing(f->grid, 0); - } -} - -uiForm *uiNewForm(void) -{ - uiForm *f; - - uiUnixNewControl(uiForm, f); - - f->widget = gtk_grid_new(); - f->container = GTK_CONTAINER(f->widget); - f->grid = GTK_GRID(f->widget); - - f->stretchygroup = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL); - - f->children = g_array_new(FALSE, TRUE, sizeof (struct formChild)); - - return f; -} diff --git a/src/libui_sdl/libui/unix/future.c b/src/libui_sdl/libui/unix/future.c deleted file mode 100644 index 1f9f532b..00000000 --- a/src/libui_sdl/libui/unix/future.c +++ /dev/null @@ -1,42 +0,0 @@ -// 29 june 2016 -#include "uipriv_unix.h" - -// functions FROM THE FUTURE! -// in some cases, because being held back by LTS releases sucks :/ -// in others, because parts of GTK+ being unstable until recently also sucks :/ - -// added in pango 1.38; we need 1.36 -static PangoAttribute *(*newFGAlphaAttr)(guint16 alpha) = NULL; - -// added in GTK+ 3.20; we need 3.10 -static void (*gwpIterSetObjectName)(GtkWidgetPath *path, gint pos, const char *name) = NULL; - -// note that we treat any error as "the symbols aren't there" (and don't care if dlclose() failed) -void loadFutures(void) -{ - void *handle; - - // dlsym() walks the dependency chain, so opening the current process should be sufficient - handle = dlopen(NULL, RTLD_LAZY); - if (handle == NULL) - return; -#define GET(var, fn) *((void **) (&var)) = dlsym(handle, #fn) - GET(newFGAlphaAttr, pango_attr_foreground_alpha_new); - GET(gwpIterSetObjectName, gtk_widget_path_iter_set_object_name); - dlclose(handle); -} - -PangoAttribute *FUTURE_pango_attr_foreground_alpha_new(guint16 alpha) -{ - if (newFGAlphaAttr == NULL) - return NULL; - return (*newFGAlphaAttr)(alpha); -} - -gboolean FUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, gint pos, const char *name) -{ - if (gwpIterSetObjectName == NULL) - return FALSE; - (*gwpIterSetObjectName)(path, pos, name); - return TRUE; -} diff --git a/src/libui_sdl/libui/unix/gl.c b/src/libui_sdl/libui/unix/gl.c deleted file mode 100644 index e15cf4f3..00000000 --- a/src/libui_sdl/libui/unix/gl.c +++ /dev/null @@ -1,251 +0,0 @@ -// 26 may 2019 -#include "uipriv_unix.h" - -#include -#include -#include - -extern GThread* gtkthread; -extern GMutex glmutex; - -struct uiGLContext -{ - GtkWidget* widget; - GdkWindow* window; - - GdkGLContext *gctx; - int vermaj, vermin; - - int width, height; - int scale; - GLuint renderbuffer[2][2]; - GLuint framebuffer[2]; - int backbuffer; -}; - -static void areaAllocRenderbuffer(uiGLContext* glctx); - -static PFNGLGENRENDERBUFFERSPROC _glGenRenderbuffers; -static PFNGLDELETERENDERBUFFERSPROC _glDeleteRenderbuffers; -static PFNGLBINDRENDERBUFFERPROC _glBindRenderbuffer; -static PFNGLRENDERBUFFERSTORAGEPROC _glRenderbufferStorage; -static PFNGLGETRENDERBUFFERPARAMETERIVPROC _glGetRenderbufferParameteriv; - -static PFNGLGENRENDERBUFFERSPROC _glGenFramebuffers; -static PFNGLDELETERENDERBUFFERSPROC _glDeleteFramebuffers; -static PFNGLBINDRENDERBUFFERPROC _glBindFramebuffer; -static PFNGLFRAMEBUFFERTEXTUREPROC _glFramebufferTexture; -static PFNGLFRAMEBUFFERRENDERBUFFERPROC _glFramebufferRenderbuffer; -static PFNGLCHECKFRAMEBUFFERSTATUSPROC _glCheckFramebufferStatus; - -static int _procsLoaded = 0; - -static void _loadGLProcs(GdkGLContext* glctx) -{ - if (_procsLoaded) return; - - _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)uiGLGetProcAddress("glGenRenderbuffers"); - _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)uiGLGetProcAddress("glDeleteRenderbuffers"); - _glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)uiGLGetProcAddress("glBindRenderbuffer"); - _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)uiGLGetProcAddress("glRenderbufferStorage"); - _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)uiGLGetProcAddress("glGetRenderbufferParameteriv"); - - _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)uiGLGetProcAddress("glGenFramebuffers"); - _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)uiGLGetProcAddress("glDeleteFramebuffers"); - _glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)uiGLGetProcAddress("glBindFramebuffer"); - _glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)uiGLGetProcAddress("glFramebufferTexture"); - _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)uiGLGetProcAddress("glFramebufferRenderbuffer"); - _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)uiGLGetProcAddress("glCheckFramebufferStatus"); - - _procsLoaded = 1; -} - -uiGLContext *createGLContext(GtkWidget* widget, int maj, int min) -{ - GdkWindow* gdkwin = gtk_widget_get_window(widget); - - GError* err = NULL; - GdkGLContext* gctx = gdk_window_create_gl_context(gdkwin, &err); - if (err != NULL || gctx == NULL) - { - return NULL; - } - - // TODO: make the set_use_es call conditional (#ifdef or smth) for older versions of gdk? - gdk_gl_context_set_use_es(gctx, FALSE); - gdk_gl_context_set_required_version(gctx, maj, min); - - gboolean res = gdk_gl_context_realize(gctx, &err); - if (err != NULL || res == FALSE) - { - return NULL; - } - - uiGLContext* ctx = uiNew(uiGLContext); - - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - int window_scale = gdk_window_get_scale_factor(gdkwin); - ctx->width = allocation.width; - ctx->height = allocation.height; - ctx->scale = window_scale; - - gdk_gl_context_make_current(gctx); - _loadGLProcs(gctx); - areaAllocRenderbuffer(ctx); - ctx->backbuffer = 0; - - ctx->widget = widget; - ctx->window = gdkwin; - ctx->gctx = gctx; - - return ctx; -} - -void freeGLContext(uiGLContext* glctx) -{ - if (glctx == NULL) return; - - gdk_gl_context_make_current(glctx->gctx); - _glDeleteRenderbuffers(4, &glctx->renderbuffer[0][0]); - _glDeleteFramebuffers(2, &glctx->framebuffer[0]); - - gdk_gl_context_clear_current(); - g_object_unref(glctx->gctx); - uiFree(glctx); -} - -static void areaAllocRenderbuffer(uiGLContext* glctx) -{ - // TODO: create textures as a fallback if GL_RGB renderbuffer isn't supported? - // they say GL implementations aren't required to support a GL_RGB renderbuffer - // however, a GL_RGBA one would cause gdk_cairo_draw_from_gl() to fall back to glReadPixels() - - _glGenRenderbuffers(4, &glctx->renderbuffer[0][0]); - _glGenFramebuffers(2, &glctx->framebuffer[0]); - - _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][0]); - _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale); - //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][1]); - //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale); - - _glBindFramebuffer(GL_FRAMEBUFFER, glctx->framebuffer[0]); - _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glctx->renderbuffer[0][0]); - _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, glctx->renderbuffer[0][1]); - - _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][0]); - _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale); - //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][1]); - //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale); - - _glBindFramebuffer(GL_FRAMEBUFFER, glctx->framebuffer[1]); - _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glctx->renderbuffer[1][0]); - _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, glctx->renderbuffer[1][1]); - - //if (_glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - // printf("FRAMEBUFFER IS BAD!! %04X\n", _glCheckFramebufferStatus(GL_FRAMEBUFFER)); -} - -static void areaReallocRenderbuffer(uiGLContext* glctx) -{ - _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][0]); - _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale); - //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][1]); - //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale); - - _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][0]); - _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale); - //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][1]); - //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale); -} - -void areaDrawGL(GtkWidget* widget, uiAreaDrawParams* dp, cairo_t* cr, uiGLContext* glctx) -{ - int window_scale = gdk_window_get_scale_factor(glctx->window); - - if (glctx->width != dp->AreaWidth || glctx->height != dp->AreaHeight || glctx->scale != window_scale) - { - glctx->width = dp->AreaWidth; - glctx->height = dp->AreaHeight; - glctx->scale = window_scale; - areaReallocRenderbuffer(glctx); - } - else - { - gdk_cairo_draw_from_gl(cr, gtk_widget_get_window(widget), - glctx->renderbuffer[glctx->backbuffer][0], GL_RENDERBUFFER, - 1, 0, 0, glctx->width*glctx->scale, glctx->height*glctx->scale); - } -} - -int uiGLGetFramebuffer(uiGLContext* ctx) -{ - return ctx->framebuffer[ctx->backbuffer]; -} - -float uiGLGetFramebufferScale(uiGLContext* ctx) -{ - return (float)ctx->scale; -} - -void uiGLSwapBuffers(uiGLContext* ctx) -{ - ctx->backbuffer = ctx->backbuffer ? 0 : 1; -} - -void uiGLSetVSync(int sync) -{ - // TODO -} - -void uiGLMakeContextCurrent(uiGLContext* ctx) -{ - if (!ctx) - { - gdk_gl_context_clear_current(); - return; - } - - if (ctx->gctx == gdk_gl_context_get_current()) return; - gdk_gl_context_make_current(ctx->gctx); -} - -void uiGLBegin(uiGLContext* ctx) -{ - if (g_thread_self() != gtkthread) - { - g_mutex_lock(&glmutex); - } -} - -void uiGLEnd(uiGLContext* ctx) -{ - if (g_thread_self() != gtkthread) - { - g_mutex_unlock(&glmutex); - } -} - -void *uiGLGetProcAddress(const char* proc) -{ - // TODO: consider using epoxy or something funny - - void* ptr; - - ptr = glXGetProcAddressARB((const GLubyte*)proc); - if (ptr) return ptr; - - ptr = eglGetProcAddress(proc); - if (ptr) return ptr; - - ptr = dlsym(NULL /* RTLD_DEFAULT */, proc); - if (ptr) return ptr; - - return NULL; -} -unsigned int uiGLGetVersion(uiGLContext* ctx) -{ - if (!ctx) return 0; - return uiGLVersion(ctx->vermaj, ctx->vermin); -} - diff --git a/src/libui_sdl/libui/unix/graphemes.c b/src/libui_sdl/libui/unix/graphemes.c deleted file mode 100644 index a2c47b72..00000000 --- a/src/libui_sdl/libui/unix/graphemes.c +++ /dev/null @@ -1,31 +0,0 @@ -// 25 may 2016 -#include "uipriv_unix.h" - -ptrdiff_t *graphemes(const char *text, PangoContext *context) -{ - size_t len, lenchars; - PangoLogAttr *logattrs; - ptrdiff_t *out; - ptrdiff_t *op; - size_t i; - - len = strlen(text); - lenchars = g_utf8_strlen(text, -1); - logattrs = (PangoLogAttr *) uiAlloc((lenchars + 1) * sizeof (PangoLogAttr), "PangoLogAttr[]"); - pango_get_log_attrs(text, len, - -1, NULL, - logattrs, lenchars + 1); - - // should be more than enough - out = (ptrdiff_t *) uiAlloc((lenchars + 2) * sizeof (ptrdiff_t), "ptrdiff_t[]"); - op = out; - for (i = 0; i < lenchars; i++) - if (logattrs[i].is_cursor_position != 0) - // TODO optimize this - *op++ = g_utf8_offset_to_pointer(text, i) - text; - // and do the last one - *op++ = len; - - uiFree(logattrs); - return out; -} diff --git a/src/libui_sdl/libui/unix/grid.c b/src/libui_sdl/libui/unix/grid.c deleted file mode 100644 index 6d9813b3..00000000 --- a/src/libui_sdl/libui/unix/grid.c +++ /dev/null @@ -1,141 +0,0 @@ -// 9 june 2016 -#include "uipriv_unix.h" - -struct gridChild { - uiControl *c; - GtkWidget *label; - gboolean oldhexpand; - GtkAlign oldhalign; - gboolean oldvexpand; - GtkAlign oldvalign; -}; - -struct uiGrid { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *container; - GtkGrid *grid; - GArray *children; - int padded; -}; - -uiUnixControlAllDefaultsExceptDestroy(uiGrid) - -#define ctrl(g, i) &g_array_index(g->children, struct gridChild, i) - -static void uiGridDestroy(uiControl *c) -{ - uiGrid *g = uiGrid(c); - struct gridChild *gc; - guint i; - - // free all controls - for (i = 0; i < g->children->len; i++) { - gc = ctrl(g, i); - uiControlSetParent(gc->c, NULL); - uiUnixControlSetContainer(uiUnixControl(gc->c), g->container, TRUE); - uiControlDestroy(gc->c); - } - g_array_free(g->children, TRUE); - // and then ourselves - g_object_unref(g->widget); - uiFreeControl(uiControl(g)); -} - -#define TODO_MASSIVE_HACK(c) \ - if (!uiUnixControl(c)->addedBefore) { \ - g_object_ref_sink(GTK_WIDGET(uiControlHandle(uiControl(c)))); \ - gtk_widget_show(GTK_WIDGET(uiControlHandle(uiControl(c)))); \ - uiUnixControl(c)->addedBefore = TRUE; \ - } - -static const GtkAlign gtkAligns[] = { - [uiAlignFill] = GTK_ALIGN_FILL, - [uiAlignStart] = GTK_ALIGN_START, - [uiAlignCenter] = GTK_ALIGN_CENTER, - [uiAlignEnd] = GTK_ALIGN_END, -}; - -static const GtkPositionType gtkPositions[] = { - [uiAtLeading] = GTK_POS_LEFT, - [uiAtTop] = GTK_POS_TOP, - [uiAtTrailing] = GTK_POS_RIGHT, - [uiAtBottom] = GTK_POS_BOTTOM, -}; - -static GtkWidget *prepare(struct gridChild *gc, uiControl *c, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - GtkWidget *widget; - - gc->c = c; - widget = GTK_WIDGET(uiControlHandle(gc->c)); - gc->oldhexpand = gtk_widget_get_hexpand(widget); - gc->oldhalign = gtk_widget_get_halign(widget); - gc->oldvexpand = gtk_widget_get_vexpand(widget); - gc->oldvalign = gtk_widget_get_valign(widget); - gtk_widget_set_hexpand(widget, hexpand != 0); - gtk_widget_set_halign(widget, gtkAligns[halign]); - gtk_widget_set_vexpand(widget, vexpand != 0); - gtk_widget_set_valign(widget, gtkAligns[valign]); - return widget; -} - -void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - struct gridChild gc; - GtkWidget *widget; - - widget = prepare(&gc, c, hexpand, halign, vexpand, valign); - uiControlSetParent(gc.c, uiControl(g)); - TODO_MASSIVE_HACK(uiUnixControl(gc.c)); - gtk_grid_attach(g->grid, widget, - left, top, - xspan, yspan); - g_array_append_val(g->children, gc); -} - -void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - struct gridChild gc; - GtkWidget *widget; - - widget = prepare(&gc, c, hexpand, halign, vexpand, valign); - uiControlSetParent(gc.c, uiControl(g)); - TODO_MASSIVE_HACK(uiUnixControl(gc.c)); - gtk_grid_attach_next_to(g->grid, widget, - GTK_WIDGET(uiControlHandle(existing)), gtkPositions[at], - xspan, yspan); - g_array_append_val(g->children, gc); -} - -int uiGridPadded(uiGrid *g) -{ - return g->padded; -} - -void uiGridSetPadded(uiGrid *g, int padded) -{ - g->padded = padded; - if (g->padded) { - gtk_grid_set_row_spacing(g->grid, gtkYPadding); - gtk_grid_set_column_spacing(g->grid, gtkXPadding); - } else { - gtk_grid_set_row_spacing(g->grid, 0); - gtk_grid_set_column_spacing(g->grid, 0); - } -} - -uiGrid *uiNewGrid(void) -{ - uiGrid *g; - - uiUnixNewControl(uiGrid, g); - - g->widget = gtk_grid_new(); - g->container = GTK_CONTAINER(g->widget); - g->grid = GTK_GRID(g->widget); - - g->children = g_array_new(FALSE, TRUE, sizeof (struct gridChild)); - - return g; -} diff --git a/src/libui_sdl/libui/unix/group.c b/src/libui_sdl/libui/unix/group.c deleted file mode 100644 index 6238a1b6..00000000 --- a/src/libui_sdl/libui/unix/group.c +++ /dev/null @@ -1,89 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiGroup { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *container; - GtkBin *bin; - GtkFrame *frame; - - // unfortunately, even though a GtkFrame is a GtkBin, calling gtk_container_set_border_width() on it /includes/ the GtkFrame's label; we don't want tht - struct child *child; - - int margined; -}; - -uiUnixControlAllDefaultsExceptDestroy(uiGroup) - -static void uiGroupDestroy(uiControl *c) -{ - uiGroup *g = uiGroup(c); - - if (g->child != NULL) - childDestroy(g->child); - g_object_unref(g->widget); - uiFreeControl(uiControl(g)); -} - -char *uiGroupTitle(uiGroup *g) -{ - return uiUnixStrdupText(gtk_frame_get_label(g->frame)); -} - -void uiGroupSetTitle(uiGroup *g, const char *text) -{ - gtk_frame_set_label(g->frame, text); -} - -void uiGroupSetChild(uiGroup *g, uiControl *child) -{ - if (g->child != NULL) - childRemove(g->child); - g->child = newChildWithBox(child, uiControl(g), g->container, g->margined); -} - -int uiGroupMargined(uiGroup *g) -{ - return g->margined; -} - -void uiGroupSetMargined(uiGroup *g, int margined) -{ - g->margined = margined; - if (g->child != NULL) - childSetMargined(g->child, g->margined); -} - -uiGroup *uiNewGroup(const char *text) -{ - uiGroup *g; - gfloat yalign; - GtkLabel *label; - PangoAttribute *bold; - PangoAttrList *boldlist; - - uiUnixNewControl(uiGroup, g); - - g->widget = gtk_frame_new(text); - g->container = GTK_CONTAINER(g->widget); - g->bin = GTK_BIN(g->widget); - g->frame = GTK_FRAME(g->widget); - - // with GTK+, groupboxes by default have frames and slightly x-offset regular text - // they should have no frame and fully left-justified, bold text - // preserve default y-alignment - gtk_frame_get_label_align(g->frame, NULL, &yalign); - gtk_frame_set_label_align(g->frame, 0, yalign); - gtk_frame_set_shadow_type(g->frame, GTK_SHADOW_NONE); - label = GTK_LABEL(gtk_frame_get_label_widget(g->frame)); - // this is the boldness level used by GtkPrintUnixDialog - // (it technically uses "bold" but see pango's pango-enum-types.c for the name conversion; GType is weird) - bold = pango_attr_weight_new(PANGO_WEIGHT_BOLD); - boldlist = pango_attr_list_new(); - pango_attr_list_insert(boldlist, bold); - gtk_label_set_attributes(label, boldlist); - pango_attr_list_unref(boldlist); // thanks baedert in irc.gimp.net/#gtk+ - - return g; -} diff --git a/src/libui_sdl/libui/unix/image.c b/src/libui_sdl/libui/unix/image.c deleted file mode 100644 index a79e550f..00000000 --- a/src/libui_sdl/libui/unix/image.c +++ /dev/null @@ -1,120 +0,0 @@ -// 27 june 2016 -#include "uipriv_unix.h" - -struct uiImage { - double width; - double height; - GPtrArray *images; -}; - -static void freeImageRep(gpointer item) -{ - cairo_surface_t *cs = (cairo_surface_t *) item; - unsigned char *buf; - - buf = cairo_image_surface_get_data(cs); - cairo_surface_destroy(cs); - uiFree(buf); -} - -uiImage *uiNewImage(double width, double height) -{ - uiImage *i; - - i = uiNew(uiImage); - i->width = width; - i->height = height; - i->images = g_ptr_array_new_with_free_func(freeImageRep); - return i; -} - -void uiFreeImage(uiImage *i) -{ - g_ptr_array_free(i->images, TRUE); - uiFree(i); -} - -void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, int pixelStride) -{ - cairo_surface_t *cs; - unsigned char *buf, *p; - uint8_t *src = (uint8_t *) pixels; - int cstride; - int y; - - cstride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixelWidth); - buf = (unsigned char *) uiAlloc((cstride * pixelHeight * 4) * sizeof (unsigned char), "unsigned char[]"); - p = buf; - for (y = 0; y < pixelStride * pixelHeight; y += pixelStride) { - memmove(p, src + y, cstride); - p += cstride; - } - cs = cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, - pixelWidth, pixelHeight, - cstride); - if (cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) - /* TODO */; - cairo_surface_flush(cs); - g_ptr_array_add(i->images, cs); -} - -struct matcher { - cairo_surface_t *best; - int distX; - int distY; - int targetX; - int targetY; - gboolean foundLarger; -}; - -// TODO is this the right algorithm? -static void match(gpointer surface, gpointer data) -{ - cairo_surface_t *cs = (cairo_surface_t *) surface; - struct matcher *m = (struct matcher *) data; - int x, y; - int x2, y2; - - x = cairo_image_surface_get_width(cs); - y = cairo_image_surface_get_height(cs); - if (m->best == NULL) - goto writeMatch; - - if (x < m->targetX && y < m->targetY) - if (m->foundLarger) - // always prefer larger ones - return; - if (x >= m->targetX && y >= m->targetY && !m->foundLarger) - // we set foundLarger below - goto writeMatch; - - x2 = abs(m->targetX - x); - y2 = abs(m->targetY - y); - if (x2 < m->distX && y2 < m->distY) - goto writeMatch; - - // TODO weight one dimension? threshhold? - return; - -writeMatch: - // must set this here too; otherwise the first image will never have ths set - if (x >= m->targetX && y >= m->targetY && !m->foundLarger) - m->foundLarger = TRUE; - m->best = cs; - m->distX = abs(m->targetX - x); - m->distY = abs(m->targetY - y); -} - -cairo_surface_t *imageAppropriateSurface(uiImage *i, GtkWidget *w) -{ - struct matcher m; - - m.best = NULL; - m.distX = G_MAXINT; - m.distY = G_MAXINT; - m.targetX = i->width * gtk_widget_get_scale_factor(w); - m.targetY = i->height * gtk_widget_get_scale_factor(w); - m.foundLarger = FALSE; - g_ptr_array_foreach(i->images, match, &m); - return m.best; -} diff --git a/src/libui_sdl/libui/unix/label.c b/src/libui_sdl/libui/unix/label.c deleted file mode 100644 index b39fc7cc..00000000 --- a/src/libui_sdl/libui/unix/label.c +++ /dev/null @@ -1,36 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiLabel { - uiUnixControl c; - GtkWidget *widget; - GtkMisc *misc; - GtkLabel *label; -}; - -uiUnixControlAllDefaults(uiLabel) - -char *uiLabelText(uiLabel *l) -{ - return uiUnixStrdupText(gtk_label_get_text(l->label)); -} - -void uiLabelSetText(uiLabel *l, const char *text) -{ - gtk_label_set_text(l->label, text); -} - -uiLabel *uiNewLabel(const char *text) -{ - uiLabel *l; - - uiUnixNewControl(uiLabel, l); - - l->widget = gtk_label_new(text); - l->misc = GTK_MISC(l->widget); - l->label = GTK_LABEL(l->widget); - - gtk_misc_set_alignment(l->misc, 0, 0); - - return l; -} diff --git a/src/libui_sdl/libui/unix/main.c b/src/libui_sdl/libui/unix/main.c deleted file mode 100644 index 516bd766..00000000 --- a/src/libui_sdl/libui/unix/main.c +++ /dev/null @@ -1,147 +0,0 @@ -// 6 april 2015 -#include "uipriv_unix.h" - -uiInitOptions options; - -// kind of a hack -GThread* gtkthread; -GMutex glmutex; - -static void _eventfilter(GdkEvent* evt, gpointer data) -{ - if (evt->type == GDK_EXPOSE) - { - g_mutex_lock(&glmutex); - gtk_main_do_event(evt); - g_mutex_unlock(&glmutex); - return; - } - - gtk_main_do_event(evt); -} - -static void _eventfilterdestroy(gpointer data) -{ - printf("DELET\n"); -} - -const char *uiInit(uiInitOptions *o) -{ - GError *err = NULL; - const char *msg; - - options = *o; - if (gtk_init_with_args(NULL, NULL, NULL, NULL, NULL, &err) == FALSE) { - msg = g_strdup(err->message); - g_error_free(err); - return msg; - } - initAlloc(); - loadFutures(); - - gtkthread = g_thread_self(); - g_mutex_init(&glmutex); - - GList* iconlist = NULL; - iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_16x16.png", NULL)); - iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_32x32.png", NULL)); - iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_48x48.png", NULL)); - iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_64x64.png", NULL)); - iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_128x128.png", NULL)); - - gtk_window_set_default_icon_list(iconlist); - - g_mutex_init(&glmutex); - - gdk_event_handler_set(_eventfilter, NULL, _eventfilterdestroy); - - return NULL; -} - -void uiUninit(void) -{ - uninitMenus(); - uninitAlloc(); -} - -void uiFreeInitError(const char *err) -{ - g_free((gpointer) err); -} - -static gboolean (*iteration)(gboolean) = NULL; - -void uiMain(void) -{ - iteration = gtk_main_iteration_do; - gtk_main(); -} - -static gboolean stepsQuit = FALSE; - -// the only difference is we ignore the return value from gtk_main_iteration_do(), since it will always be TRUE if gtk_main() was never called -// gtk_main_iteration_do() will still run the main loop regardless -static gboolean stepsIteration(gboolean block) -{ - gtk_main_iteration_do(block); - return stepsQuit; -} - -void uiMainSteps(void) -{ - iteration = stepsIteration; -} - -int uiMainStep(int wait) -{ - gboolean block; - - block = FALSE; - if (wait) - block = TRUE; - return (*iteration)(block) == FALSE; -} - -// gtk_main_quit() may run immediately, or it may wait for other pending events; "it depends" (thanks mclasen in irc.gimp.net/#gtk+) -// PostQuitMessage() on Windows always waits, so we must do so too -// we'll do it by using an idle callback -static gboolean quit(gpointer data) -{ - if (iteration == stepsIteration) - stepsQuit = TRUE; - // TODO run a gtk_main() here just to do the cleanup steps of syncing the clipboard and other stuff gtk_main() does before it returns - else - gtk_main_quit(); - return FALSE; -} - -void uiQuit(void) -{ - gdk_threads_add_idle(quit, NULL); -} - -struct queued { - void (*f)(void *); - void *data; -}; - -static gboolean doqueued(gpointer data) -{ - struct queued *q = (struct queued *) data; - - (*(q->f))(q->data); - g_free(q); - return FALSE; -} - -void uiQueueMain(void (*f)(void *data), void *data) -{ - struct queued *q; - - // we have to use g_new0()/g_free() because uiAlloc() is only safe to call on the main thread - // for some reason it didn't affect me, but it did affect krakjoe - q = g_new0(struct queued, 1); - q->f = f; - q->data = data; - gdk_threads_add_idle(doqueued, q); -} diff --git a/src/libui_sdl/libui/unix/menu.c b/src/libui_sdl/libui/unix/menu.c deleted file mode 100644 index d6414269..00000000 --- a/src/libui_sdl/libui/unix/menu.c +++ /dev/null @@ -1,432 +0,0 @@ -// 23 april 2015 -#include "uipriv_unix.h" - -static GArray *menus = NULL; -static guint nmenus = 0; -static gboolean menusFinalized = FALSE; -static gboolean hasQuit = FALSE; -static gboolean hasPreferences = FALSE; -static gboolean hasAbout = FALSE; - -struct uiMenu { - char *name; - GArray *items; // []*uiMenuItem - gboolean ischild; - guint id; -}; - -struct uiMenuItem { - char *name; - int type; - void (*onClicked)(uiMenuItem *, uiWindow *, void *); - void *onClickedData; - GType gtype; // template for new instances; kept in sync with everything else - gboolean disabled; - gboolean checked; - GHashTable *windows; // map[GtkMenuItem]*menuItemWindow - uiMenu *popupchild; -}; - -struct menuItemWindow { - uiWindow *w; - gulong signal; -}; - -enum { - typeRegular, - typeCheckbox, - typeQuit, - typePreferences, - typeAbout, - typeSeparator, - typeSubmenu, -}; - -// we do NOT want programmatic updates to raise an ::activated signal -static void singleSetChecked(GtkCheckMenuItem *menuitem, gboolean checked, gulong signal) -{ - g_signal_handler_block(menuitem, signal); - gtk_check_menu_item_set_active(menuitem, checked); - g_signal_handler_unblock(menuitem, signal); -} - -static void setChecked(uiMenuItem *item, gboolean checked) -{ - GHashTableIter iter; - gpointer widget; - gpointer ww; - struct menuItemWindow *w; - - item->checked = checked; - g_hash_table_iter_init(&iter, item->windows); - while (g_hash_table_iter_next(&iter, &widget, &ww)) { - w = (struct menuItemWindow *) ww; - singleSetChecked(GTK_CHECK_MENU_ITEM(widget), item->checked, w->signal); - } -} - -static void onClicked(GtkMenuItem *menuitem, gpointer data) -{ - uiMenuItem *item = uiMenuItem(data); - struct menuItemWindow *w; - - // we need to manually update the checked states of all menu items if one changes - // notice that this is getting the checked state of the menu item that this signal is sent from - if (item->type == typeCheckbox) - setChecked(item, gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))); - - w = (struct menuItemWindow *) g_hash_table_lookup(item->windows, menuitem); - (*(item->onClicked))(item, w->w, item->onClickedData); -} - -static void defaultOnClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - // do nothing -} - -static void onQuitClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - if (shouldQuit()) - uiQuit(); -} - -static void menuItemEnableDisable(uiMenuItem *item, gboolean enabled) -{ - GHashTableIter iter; - gpointer widget; - - item->disabled = !enabled; - g_hash_table_iter_init(&iter, item->windows); - while (g_hash_table_iter_next(&iter, &widget, NULL)) - gtk_widget_set_sensitive(GTK_WIDGET(widget), enabled); -} - -void uiMenuItemEnable(uiMenuItem *item) -{ - menuItemEnableDisable(item, TRUE); -} - -void uiMenuItemDisable(uiMenuItem *item) -{ - menuItemEnableDisable(item, FALSE); -} - -void uiMenuItemOnClicked(uiMenuItem *item, void (*f)(uiMenuItem *, uiWindow *, void *), void *data) -{ - if (item->type == typeQuit) - userbug("You cannot call uiMenuItemOnClicked() on a Quit item; use uiOnShouldQuit() instead."); - item->onClicked = f; - item->onClickedData = data; -} - -int uiMenuItemChecked(uiMenuItem *item) -{ - return item->checked != FALSE; -} - -void uiMenuItemSetChecked(uiMenuItem *item, int checked) -{ - gboolean c; - - // use explicit values - c = FALSE; - if (checked) - c = TRUE; - setChecked(item, c); -} - -static uiMenuItem *newItem(uiMenu *m, int type, const char *name) -{ - uiMenuItem *item; - - if (menusFinalized) - userbug("You cannot create a new menu item after menus have been finalized."); - - item = uiNew(uiMenuItem); - - g_array_append_val(m->items, item); - - item->type = type; - switch (item->type) { - case typeQuit: - item->name = g_strdup("Quit"); - break; - case typePreferences: - item->name = g_strdup("Preferences..."); - break; - case typeAbout: - item->name = g_strdup("About"); - break; - case typeSeparator: - break; - default: - item->name = g_strdup(name); - break; - } - - if (item->type == typeQuit) { - // can't call uiMenuItemOnClicked() here - item->onClicked = onQuitClicked; - item->onClickedData = NULL; - } else - uiMenuItemOnClicked(item, defaultOnClicked, NULL); - - switch (item->type) { - case typeCheckbox: - item->gtype = GTK_TYPE_CHECK_MENU_ITEM; - break; - case typeSeparator: - item->gtype = GTK_TYPE_SEPARATOR_MENU_ITEM; - break; - default: - item->gtype = GTK_TYPE_MENU_ITEM; - break; - } - - item->windows = g_hash_table_new(g_direct_hash, g_direct_equal); - item->popupchild = NULL; - - return item; -} - -uiMenuItem *uiMenuAppendSubmenu(uiMenu *m, uiMenu* child) -{ - uiMenuItem *item; - - if (menusFinalized) - userbug("You cannot create a new menu item after menus have been finalized."); - - item = uiNew(uiMenuItem); - - g_array_append_val(m->items, item); - - item->type = typeSubmenu; - item->name = child->name; - - uiMenuItemOnClicked(item, defaultOnClicked, NULL); - - // checkme - item->gtype = GTK_TYPE_MENU_ITEM; - - item->windows = g_hash_table_new(g_direct_hash, g_direct_equal); - item->popupchild = child; - child->ischild = TRUE; - - return item; -} - -uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name) -{ - return newItem(m, typeRegular, name); -} - -uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name) -{ - return newItem(m, typeCheckbox, name); -} - -uiMenuItem *uiMenuAppendQuitItem(uiMenu *m) -{ - if (hasQuit) - userbug("You cannot have multiple Quit menu items in the same program."); - hasQuit = TRUE; - newItem(m, typeSeparator, NULL); - return newItem(m, typeQuit, NULL); -} - -uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m) -{ - if (hasPreferences) - userbug("You cannot have multiple Preferences menu items in the same program."); - hasPreferences = TRUE; - newItem(m, typeSeparator, NULL); - return newItem(m, typePreferences, NULL); -} - -uiMenuItem *uiMenuAppendAboutItem(uiMenu *m) -{ - if (hasAbout) - userbug("You cannot have multiple About menu items in the same program."); - hasAbout = TRUE; - newItem(m, typeSeparator, NULL); - return newItem(m, typeAbout, NULL); -} - -void uiMenuAppendSeparator(uiMenu *m) -{ - newItem(m, typeSeparator, NULL); -} - -uiMenu *uiNewMenu(const char *name) -{ - uiMenu *m; - - if (menusFinalized) - userbug("You cannot create a new menu after menus have been finalized."); - if (menus == NULL) - menus = g_array_new(FALSE, TRUE, sizeof (uiMenu *)); - - m = uiNew(uiMenu); - - g_array_append_val(menus, m); - m->id = nmenus; - nmenus++; - - m->name = g_strdup(name); - m->items = g_array_new(FALSE, TRUE, sizeof (uiMenuItem *)); - m->ischild = FALSE; - - return m; -} - -static void appendMenuItem(GtkMenuShell *submenu, uiMenuItem *item, uiWindow *w) -{ - GtkWidget *menuitem; - gulong signal; - struct menuItemWindow *ww; - - menuitem = g_object_new(item->gtype, NULL); - if (item->name != NULL) - gtk_menu_item_set_label(GTK_MENU_ITEM(menuitem), item->name); - if (item->type != typeSeparator) { - signal = g_signal_connect(menuitem, "activate", G_CALLBACK(onClicked), item); - gtk_widget_set_sensitive(menuitem, !item->disabled); - if (item->type == typeCheckbox) - singleSetChecked(GTK_CHECK_MENU_ITEM(menuitem), item->checked, signal); - } - gtk_menu_shell_append(submenu, menuitem); - - ww = uiNew(struct menuItemWindow); - ww->w = w; - ww->signal = signal; - g_hash_table_insert(item->windows, menuitem, ww); - - if (item->popupchild != NULL) - { - int j; - uiMenu* m; - GtkWidget *c_submenu; - - m = item->popupchild; - c_submenu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), c_submenu); - for (j = 0; j < m->items->len; j++) - appendMenuItem(GTK_MENU_SHELL(c_submenu), g_array_index(m->items, uiMenuItem *, j), w); - } -} - -GtkWidget *makeMenubar(uiWindow *w) -{ - GtkWidget *menubar; - guint i, j; - uiMenu *m; - GtkWidget *menuitem; - GtkWidget *submenu; - - menusFinalized = TRUE; - - menubar = gtk_menu_bar_new(); - - if (menus != NULL) - for (i = 0; i < menus->len; i++) { - m = g_array_index(menus, uiMenu *, i); - if (m->ischild) continue; - menuitem = gtk_menu_item_new_with_label(m->name); - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - for (j = 0; j < m->items->len; j++) - appendMenuItem(GTK_MENU_SHELL(submenu), g_array_index(m->items, uiMenuItem *, j), w); - gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem); - } - - gtk_widget_set_hexpand(menubar, TRUE); - gtk_widget_set_halign(menubar, GTK_ALIGN_FILL); - return menubar; -} - -struct freeMenuItemData { - GArray *items; - guint i; - guint* parent_i; -}; - -static void freeMenu(GtkWidget *widget, gpointer data); - -static void freeMenuItem(GtkWidget *widget, gpointer data) -{ - struct freeMenuItemData *fmi = (struct freeMenuItemData *) data; - uiMenuItem *item; - struct menuItemWindow *w; - - item = g_array_index(fmi->items, uiMenuItem *, fmi->i); - if (item->popupchild != NULL) - freeMenu(widget, fmi->parent_i);//&item->popupchild->id); - w = (struct menuItemWindow *) g_hash_table_lookup(item->windows, widget); - if (g_hash_table_remove(item->windows, widget) == FALSE) - implbug("GtkMenuItem %p not in menu item's item/window map", widget); - uiFree(w); - fmi->i++; -} - -static void freeMenu(GtkWidget *widget, gpointer data) -{ - guint *i = (guint *) data; - uiMenu *m; - GtkMenuItem *item; - GtkWidget *submenu; - struct freeMenuItemData fmi; - - m = g_array_index(menus, uiMenu *, *i); - item = GTK_MENU_ITEM(widget); - submenu = gtk_menu_item_get_submenu(item); - fmi.items = m->items; - fmi.i = 0; - (*i)++; - fmi.parent_i = i; - gtk_container_foreach(GTK_CONTAINER(submenu), freeMenuItem, &fmi); - //(*i)++; -} - -void freeMenubar(GtkWidget *mb) -{ - guint i; - - i = 0; - gtk_container_foreach(GTK_CONTAINER(mb), freeMenu, &i); - // no need to worry about destroying any widgets; destruction of the window they're in will do it for us -} - -void _freeMenu(uiMenu* m) -{ - uiMenuItem *item; - guint j; - - g_free(m->name); - for (j = 0; j < m->items->len; j++) { - item = g_array_index(m->items, uiMenuItem *, j); - if (item->popupchild != NULL) _freeMenu(item->popupchild); - if (g_hash_table_size(item->windows) != 0) - // TODO is this really a userbug()? - implbug("menu item %p (%s) still has uiWindows attached; did you forget to destroy some windows?", item, item->name); - if (item->type != typeSubmenu) g_free(item->name); - g_hash_table_destroy(item->windows); - uiFree(item); - } - g_array_free(m->items, TRUE); - uiFree(m); -} - -void uninitMenus(void) -{ - uiMenu *m; - guint i; - - if (menus == NULL) - return; - for (i = 0; i < menus->len; i++) { - m = g_array_index(menus, uiMenu *, i); - if (m->ischild) continue; - _freeMenu(m); - } - g_array_free(menus, TRUE); -} diff --git a/src/libui_sdl/libui/unix/multilineentry.c b/src/libui_sdl/libui/unix/multilineentry.c deleted file mode 100644 index 09ffd460..00000000 --- a/src/libui_sdl/libui/unix/multilineentry.c +++ /dev/null @@ -1,124 +0,0 @@ -// 6 december 2015 -#include "uipriv_unix.h" - -struct uiMultilineEntry { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *scontainer; - GtkScrolledWindow *sw; - GtkWidget *textviewWidget; - GtkTextView *textview; - GtkTextBuffer *textbuf; - void (*onChanged)(uiMultilineEntry *, void *); - void *onChangedData; - gulong onChangedSignal; -}; - -uiUnixControlAllDefaults(uiMultilineEntry) - -static void onChanged(GtkTextBuffer *textbuf, gpointer data) -{ - uiMultilineEntry *e = uiMultilineEntry(data); - - (*(e->onChanged))(e, e->onChangedData); -} - -static void defaultOnChanged(uiMultilineEntry *e, void *data) -{ - // do nothing -} - -char *uiMultilineEntryText(uiMultilineEntry *e) -{ - GtkTextIter start, end; - char *tret, *out; - - gtk_text_buffer_get_start_iter(e->textbuf, &start); - gtk_text_buffer_get_end_iter(e->textbuf, &end); - tret = gtk_text_buffer_get_text(e->textbuf, &start, &end, TRUE); - // theoretically we could just return tret because uiUnixStrdupText() is just g_strdup(), but if that ever changes we can't, so let's do it this way to be safe - out = uiUnixStrdupText(tret); - g_free(tret); - return out; -} - -void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text) -{ - // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise - g_signal_handler_block(e->textbuf, e->onChangedSignal); - gtk_text_buffer_set_text(e->textbuf, text, -1); - g_signal_handler_unblock(e->textbuf, e->onChangedSignal); -} - -// TODO scroll to end? -void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text) -{ - GtkTextIter end; - - gtk_text_buffer_get_end_iter(e->textbuf, &end); - // we need to inhibit sending of ::changed because this WILL send a ::changed otherwise - g_signal_handler_block(e->textbuf, e->onChangedSignal); - gtk_text_buffer_insert(e->textbuf, &end, text, -1); - g_signal_handler_unblock(e->textbuf, e->onChangedSignal); -} - -void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *e, void *data), void *data) -{ - e->onChanged = f; - e->onChangedData = data; -} - -int uiMultilineEntryReadOnly(uiMultilineEntry *e) -{ - return gtk_text_view_get_editable(e->textview) == FALSE; -} - -void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly) -{ - gboolean editable; - - editable = TRUE; - if (readonly) - editable = FALSE; - gtk_text_view_set_editable(e->textview, editable); -} - -static uiMultilineEntry *finishMultilineEntry(GtkPolicyType hpolicy, GtkWrapMode wrapMode) -{ - uiMultilineEntry *e; - - uiUnixNewControl(uiMultilineEntry, e); - - e->widget = gtk_scrolled_window_new(NULL, NULL); - e->scontainer = GTK_CONTAINER(e->widget); - e->sw = GTK_SCROLLED_WINDOW(e->widget); - gtk_scrolled_window_set_policy(e->sw, - hpolicy, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(e->sw, GTK_SHADOW_IN); - - e->textviewWidget = gtk_text_view_new(); - e->textview = GTK_TEXT_VIEW(e->textviewWidget); - gtk_text_view_set_wrap_mode(e->textview, wrapMode); - - gtk_container_add(e->scontainer, e->textviewWidget); - // and make the text view visible; only the scrolled window's visibility is controlled by libui - gtk_widget_show(e->textviewWidget); - - e->textbuf = gtk_text_view_get_buffer(e->textview); - - e->onChangedSignal = g_signal_connect(e->textbuf, "changed", G_CALLBACK(onChanged), e); - uiMultilineEntryOnChanged(e, defaultOnChanged, NULL); - - return e; -} - -uiMultilineEntry *uiNewMultilineEntry(void) -{ - return finishMultilineEntry(GTK_POLICY_NEVER, GTK_WRAP_WORD); -} - -uiMultilineEntry *uiNewNonWrappingMultilineEntry(void) -{ - return finishMultilineEntry(GTK_POLICY_AUTOMATIC, GTK_WRAP_NONE); -} diff --git a/src/libui_sdl/libui/unix/progressbar.c b/src/libui_sdl/libui/unix/progressbar.c deleted file mode 100644 index 9b543b04..00000000 --- a/src/libui_sdl/libui/unix/progressbar.c +++ /dev/null @@ -1,71 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiProgressBar { - uiUnixControl c; - GtkWidget *widget; - GtkProgressBar *pbar; - gboolean indeterminate; - guint pulser; -}; - -uiUnixControlAllDefaultsExceptDestroy(uiProgressBar) - -static void uiProgressBarDestroy(uiControl *c) -{ - uiProgressBar *p = uiProgressBar(c); - - // be sure to stop the timeout now - if (p->indeterminate) - g_source_remove(p->pulser); - g_object_unref(p->widget); - uiFreeControl(uiControl(p)); -} - -int uiProgressBarValue(uiProgressBar *p) -{ - if (p->indeterminate) - return -1; - return (int) (gtk_progress_bar_get_fraction(p->pbar) * 100); -} - -static gboolean pulse(void* data) -{ - uiProgressBar *p = uiProgressBar(data); - - gtk_progress_bar_pulse(p->pbar); - return TRUE; -} - -void uiProgressBarSetValue(uiProgressBar *p, int value) -{ - if (value == -1) { - if (!p->indeterminate) { - p->indeterminate = TRUE; - // TODO verify the timeout - p->pulser = g_timeout_add(100, pulse, p); - } - return; - } - if (p->indeterminate) { - p->indeterminate = FALSE; - g_source_remove(p->pulser); - } - - if (value < 0 || value > 100) - userbug("Value %d is out of range for a uiProgressBar.", value); - - gtk_progress_bar_set_fraction(p->pbar, ((gdouble) value) / 100); -} - -uiProgressBar *uiNewProgressBar(void) -{ - uiProgressBar *p; - - uiUnixNewControl(uiProgressBar, p); - - p->widget = gtk_progress_bar_new(); - p->pbar = GTK_PROGRESS_BAR(p->widget); - - return p; -} diff --git a/src/libui_sdl/libui/unix/radiobuttons.c b/src/libui_sdl/libui/unix/radiobuttons.c deleted file mode 100644 index da41107e..00000000 --- a/src/libui_sdl/libui/unix/radiobuttons.c +++ /dev/null @@ -1,121 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -// on GTK+ a uiRadioButtons is a GtkBox with each of the GtkRadioButtons as children - -struct uiRadioButtons { - uiUnixControl c; - GtkWidget *widget; - GtkContainer *container; - GtkBox *box; - GPtrArray *buttons; - void (*onSelected)(uiRadioButtons *, void *); - void *onSelectedData; - gboolean changing; -}; - -uiUnixControlAllDefaultsExceptDestroy(uiRadioButtons) - -static void defaultOnSelected(uiRadioButtons *r, void *data) -{ - // do nothing -} - -static void onToggled(GtkToggleButton *tb, gpointer data) -{ - uiRadioButtons *r = uiRadioButtons(data); - - // only care if a button is selected - if (!gtk_toggle_button_get_active(tb)) - return; - // ignore programmatic changes - if (r->changing) - return; - (*(r->onSelected))(r, r->onSelectedData); -} - -static void uiRadioButtonsDestroy(uiControl *c) -{ - uiRadioButtons *r = uiRadioButtons(c); - GtkWidget *b; - - while (r->buttons->len != 0) { - b = GTK_WIDGET(g_ptr_array_remove_index(r->buttons, 0)); - gtk_widget_destroy(b); - } - g_ptr_array_free(r->buttons, TRUE); - // and free ourselves - g_object_unref(r->widget); - uiFreeControl(uiControl(r)); -} - -void uiRadioButtonsAppend(uiRadioButtons *r, const char *text) -{ - GtkWidget *rb; - GtkRadioButton *previous; - - previous = NULL; - if (r->buttons->len > 0) - previous = GTK_RADIO_BUTTON(g_ptr_array_index(r->buttons, 0)); - rb = gtk_radio_button_new_with_label_from_widget(previous, text); - g_signal_connect(rb, "toggled", G_CALLBACK(onToggled), r); - gtk_container_add(r->container, rb); - g_ptr_array_add(r->buttons, rb); - gtk_widget_show(rb); -} - -int uiRadioButtonsSelected(uiRadioButtons *r) -{ - GtkToggleButton *tb; - guint i; - - for (i = 0; i < r->buttons->len; i++) { - tb = GTK_TOGGLE_BUTTON(g_ptr_array_index(r->buttons, i)); - if (gtk_toggle_button_get_active(tb)) - return i; - } - return -1; -} - -void uiRadioButtonsSetSelected(uiRadioButtons *r, int n) -{ - GtkToggleButton *tb; - gboolean active; - - active = TRUE; - // TODO this doesn't work - if (n == -1) { - n = uiRadioButtonsSelected(r); - if (n == -1) // no selection; keep it that way - return; - active = FALSE; - } - tb = GTK_TOGGLE_BUTTON(g_ptr_array_index(r->buttons, n)); - // this is easier than remembering all the signals - r->changing = TRUE; - gtk_toggle_button_set_active(tb, active); - r->changing = FALSE; -} - -void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data) -{ - r->onSelected = f; - r->onSelectedData = data; -} - -uiRadioButtons *uiNewRadioButtons(void) -{ - uiRadioButtons *r; - - uiUnixNewControl(uiRadioButtons, r); - - r->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - r->container = GTK_CONTAINER(r->widget); - r->box = GTK_BOX(r->widget); - - r->buttons = g_ptr_array_new(); - - uiRadioButtonsOnSelected(r, defaultOnSelected, NULL); - - return r; -} diff --git a/src/libui_sdl/libui/unix/separator.c b/src/libui_sdl/libui/unix/separator.c deleted file mode 100644 index 02c75da5..00000000 --- a/src/libui_sdl/libui/unix/separator.c +++ /dev/null @@ -1,34 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiSeparator { - uiUnixControl c; - GtkWidget *widget; - GtkSeparator *separator; -}; - -uiUnixControlAllDefaults(uiSeparator) - -uiSeparator *uiNewHorizontalSeparator(void) -{ - uiSeparator *s; - - uiUnixNewControl(uiSeparator, s); - - s->widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); - s->separator = GTK_SEPARATOR(s->widget); - - return s; -} - -uiSeparator *uiNewVerticalSeparator(void) -{ - uiSeparator *s; - - uiUnixNewControl(uiSeparator, s); - - s->widget = gtk_separator_new(GTK_ORIENTATION_VERTICAL); - s->separator = GTK_SEPARATOR(s->widget); - - return s; -} diff --git a/src/libui_sdl/libui/unix/slider.c b/src/libui_sdl/libui/unix/slider.c deleted file mode 100644 index 7f0cc24a..00000000 --- a/src/libui_sdl/libui/unix/slider.c +++ /dev/null @@ -1,71 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiSlider { - uiUnixControl c; - GtkWidget *widget; - GtkRange *range; - GtkScale *scale; - void (*onChanged)(uiSlider *, void *); - void *onChangedData; - gulong onChangedSignal; -}; - -uiUnixControlAllDefaults(uiSlider) - -static void onChanged(GtkRange *range, gpointer data) -{ - uiSlider *s = uiSlider(data); - - (*(s->onChanged))(s, s->onChangedData); -} - -static void defaultOnChanged(uiSlider *s, void *data) -{ - // do nothing -} - -int uiSliderValue(uiSlider *s) -{ - return gtk_range_get_value(s->range); -} - -void uiSliderSetValue(uiSlider *s, int value) -{ - // we need to inhibit sending of ::value-changed because this WILL send a ::value-changed otherwise - g_signal_handler_block(s->range, s->onChangedSignal); - gtk_range_set_value(s->range, value); - g_signal_handler_unblock(s->range, s->onChangedSignal); -} - -void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *, void *), void *data) -{ - s->onChanged = f; - s->onChangedData = data; -} - -uiSlider *uiNewSlider(int min, int max) -{ - uiSlider *s; - int temp; - - if (min >= max) { - temp = min; - min = max; - max = temp; - } - - uiUnixNewControl(uiSlider, s); - - s->widget = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, min, max, 1); - s->range = GTK_RANGE(s->widget); - s->scale = GTK_SCALE(s->widget); - - // ensure integers, just to be safe - gtk_scale_set_digits(s->scale, 0); - - s->onChangedSignal = g_signal_connect(s->scale, "value-changed", G_CALLBACK(onChanged), s); - uiSliderOnChanged(s, defaultOnChanged, NULL); - - return s; -} diff --git a/src/libui_sdl/libui/unix/spinbox.c b/src/libui_sdl/libui/unix/spinbox.c deleted file mode 100644 index 90a5d3c1..00000000 --- a/src/libui_sdl/libui/unix/spinbox.c +++ /dev/null @@ -1,72 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiSpinbox { - uiUnixControl c; - GtkWidget *widget; - GtkEntry *entry; - GtkSpinButton *spinButton; - void (*onChanged)(uiSpinbox *, void *); - void *onChangedData; - gulong onChangedSignal; -}; - -uiUnixControlAllDefaults(uiSpinbox) - -static void onChanged(GtkSpinButton *sb, gpointer data) -{ - uiSpinbox *s = uiSpinbox(data); - - (*(s->onChanged))(s, s->onChangedData); -} - -static void defaultOnChanged(uiSpinbox *s, void *data) -{ - // do nothing -} - -int uiSpinboxValue(uiSpinbox *s) -{ - return gtk_spin_button_get_value(s->spinButton); -} - -void uiSpinboxSetValue(uiSpinbox *s, int value) -{ - // we need to inhibit sending of ::value-changed because this WILL send a ::value-changed otherwise - g_signal_handler_block(s->spinButton, s->onChangedSignal); - // this clamps for us - gtk_spin_button_set_value(s->spinButton, (gdouble) value); - g_signal_handler_unblock(s->spinButton, s->onChangedSignal); -} - -void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *, void *), void *data) -{ - s->onChanged = f; - s->onChangedData = data; -} - -uiSpinbox *uiNewSpinbox(int min, int max) -{ - uiSpinbox *s; - int temp; - - if (min >= max) { - temp = min; - min = max; - max = temp; - } - - uiUnixNewControl(uiSpinbox, s); - - s->widget = gtk_spin_button_new_with_range(min, max, 1); - s->entry = GTK_ENTRY(s->widget); - s->spinButton = GTK_SPIN_BUTTON(s->widget); - - // ensure integers, just to be safe - gtk_spin_button_set_digits(s->spinButton, 0); - - s->onChangedSignal = g_signal_connect(s->spinButton, "value-changed", G_CALLBACK(onChanged), s); - uiSpinboxOnChanged(s, defaultOnChanged, NULL); - - return s; -} diff --git a/src/libui_sdl/libui/unix/stddialogs.c b/src/libui_sdl/libui/unix/stddialogs.c deleted file mode 100644 index 3daeffac..00000000 --- a/src/libui_sdl/libui/unix/stddialogs.c +++ /dev/null @@ -1,116 +0,0 @@ -// 26 june 2015 -#include "uipriv_unix.h" - -// LONGTERM figure out why, and describe, that this is the desired behavior -// LONGTERM also point out that font and color buttons also work like this - -#define windowWindow(w) ((w)?(GTK_WINDOW(uiControlHandle(uiControl(w)))):NULL) - -static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gchar *confirm, const char* filter, const char* initpath) -{ - GtkWidget *fcd; - GtkFileChooser *fc; - gint response; - char *filename; - - fcd = gtk_file_chooser_dialog_new(NULL, parent, mode, - "_Cancel", GTK_RESPONSE_CANCEL, - confirm, GTK_RESPONSE_ACCEPT, - NULL); - fc = GTK_FILE_CHOOSER(fcd); - - // filters - { - gchar _filter[256]; - gchar* fp = &_filter[0]; int s = 0; - gchar* fname; - for (int i = 0; i < 255; i++) - { - if (filter[i] == '|' || filter[i] == '\0') - { - _filter[i] = '\0'; - if (s & 1) - { - GtkFileFilter* filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, fname); - - for (gchar* j = fp; ; j++) - { - if (*j == ';') - { - *j = '\0'; - gtk_file_filter_add_pattern(filter, fp); - fp = j+1; - } - else if (*j == '\0') - { - gtk_file_filter_add_pattern(filter, fp); - break; - } - } - - gtk_file_chooser_add_filter(fc, filter); - } - else - { - fname = fp; - } - fp = &_filter[i+1]; - s++; - if (s >= 8) break; - if (filter[i] == '\0') break; - } - else - _filter[i] = filter[i]; - } - } - - gtk_file_chooser_set_local_only(fc, FALSE); - gtk_file_chooser_set_select_multiple(fc, FALSE); - gtk_file_chooser_set_show_hidden(fc, TRUE); - gtk_file_chooser_set_do_overwrite_confirmation(fc, TRUE); - gtk_file_chooser_set_create_folders(fc, TRUE); - if (initpath && strlen(initpath)>0) - gtk_file_chooser_set_current_folder(fc, initpath); - - response = gtk_dialog_run(GTK_DIALOG(fcd)); - if (response != GTK_RESPONSE_ACCEPT) { - gtk_widget_destroy(fcd); - return NULL; - } - filename = uiUnixStrdupText(gtk_file_chooser_get_filename(fc)); - gtk_widget_destroy(fcd); - return filename; -} - -char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath) -{ - return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", filter, initpath); -} - -char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath) -{ - return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", filter, initpath); -} - -static void msgbox(GtkWindow *parent, const char *title, const char *description, GtkMessageType type, GtkButtonsType buttons) -{ - GtkWidget *md; - - md = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, - type, buttons, - "%s", title); - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(md), "%s", description); - gtk_dialog_run(GTK_DIALOG(md)); - gtk_widget_destroy(md); -} - -void uiMsgBox(uiWindow *parent, const char *title, const char *description) -{ - msgbox(windowWindow(parent), title, description, GTK_MESSAGE_OTHER, GTK_BUTTONS_OK); -} - -void uiMsgBoxError(uiWindow *parent, const char *title, const char *description) -{ - msgbox(windowWindow(parent), title, description, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK); -} diff --git a/src/libui_sdl/libui/unix/tab.c b/src/libui_sdl/libui/unix/tab.c deleted file mode 100644 index 552e0e31..00000000 --- a/src/libui_sdl/libui/unix/tab.c +++ /dev/null @@ -1,97 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiTab { - uiUnixControl c; - - GtkWidget *widget; - GtkContainer *container; - GtkNotebook *notebook; - - GArray *pages; // []*struct child -}; - -uiUnixControlAllDefaultsExceptDestroy(uiTab) - -static void uiTabDestroy(uiControl *c) -{ - uiTab *t = uiTab(c); - guint i; - struct child *page; - - for (i = 0; i < t->pages->len; i++) { - page = g_array_index(t->pages, struct child *, i); - childDestroy(page); - } - g_array_free(t->pages, TRUE); - // and free ourselves - g_object_unref(t->widget); - uiFreeControl(uiControl(t)); -} - -void uiTabAppend(uiTab *t, const char *name, uiControl *child) -{ - uiTabInsertAt(t, name, t->pages->len, child); -} - -void uiTabInsertAt(uiTab *t, const char *name, int n, uiControl *child) -{ - struct child *page; - - // this will create a tab, because of gtk_container_add() - page = newChildWithBox(child, uiControl(t), t->container, 0); - - gtk_notebook_set_tab_label_text(t->notebook, childBox(page), name); - gtk_notebook_reorder_child(t->notebook, childBox(page), n); - - g_array_insert_val(t->pages, n, page); -} - -void uiTabDelete(uiTab *t, int n) -{ - struct child *page; - - page = g_array_index(t->pages, struct child *, n); - // this will remove the tab, because gtk_widget_destroy() calls gtk_container_remove() - childRemove(page); - g_array_remove_index(t->pages, n); -} - -int uiTabNumPages(uiTab *t) -{ - return t->pages->len; -} - -int uiTabMargined(uiTab *t, int n) -{ - struct child *page; - - page = g_array_index(t->pages, struct child *, n); - return childFlag(page); -} - -void uiTabSetMargined(uiTab *t, int n, int margined) -{ - struct child *page; - - page = g_array_index(t->pages, struct child *, n); - childSetFlag(page, margined); - childSetMargined(page, childFlag(page)); -} - -uiTab *uiNewTab(void) -{ - uiTab *t; - - uiUnixNewControl(uiTab, t); - - t->widget = gtk_notebook_new(); - t->container = GTK_CONTAINER(t->widget); - t->notebook = GTK_NOTEBOOK(t->widget); - - gtk_notebook_set_scrollable(t->notebook, TRUE); - - t->pages = g_array_new(FALSE, TRUE, sizeof (struct child *)); - - return t; -} diff --git a/src/libui_sdl/libui/unix/text.c b/src/libui_sdl/libui/unix/text.c deleted file mode 100644 index ad92738d..00000000 --- a/src/libui_sdl/libui/unix/text.c +++ /dev/null @@ -1,12 +0,0 @@ -// 9 april 2015 -#include "uipriv_unix.h" - -char *uiUnixStrdupText(const char *t) -{ - return g_strdup(t); -} - -void uiFreeText(char *t) -{ - g_free(t); -} diff --git a/src/libui_sdl/libui/unix/uipriv_unix.h b/src/libui_sdl/libui/unix/uipriv_unix.h deleted file mode 100644 index 9b771887..00000000 --- a/src/libui_sdl/libui/unix/uipriv_unix.h +++ /dev/null @@ -1,71 +0,0 @@ -// 22 april 2015 -#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_40 -#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_40 -#define GDK_VERSION_MIN_REQUIRED GDK_VERSION_3_10 -#define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_10 -#include -#include -#include // see drawtext.c, gl.c -#include -#include -#include -#include "../ui.h" -#include "../ui_unix.h" -#include "../common/uipriv.h" - -#define gtkXMargin 12 -#define gtkYMargin 12 -#define gtkXPadding 12 -#define gtkYPadding 6 - -// menu.c -extern GtkWidget *makeMenubar(uiWindow *); -extern void freeMenubar(GtkWidget *); -extern void uninitMenus(void); - -// alloc.c -extern void initAlloc(void); -extern void uninitAlloc(void); - -// util.c -extern void setMargined(GtkContainer *, int); - -// child.c -extern struct child *newChild(uiControl *child, uiControl *parent, GtkContainer *parentContainer); -extern struct child *newChildWithBox(uiControl *child, uiControl *parent, GtkContainer *parentContainer, int margined); -extern void childRemove(struct child *c); -extern void childDestroy(struct child *c); -extern GtkWidget *childWidget(struct child *c); -extern int childFlag(struct child *c); -extern void childSetFlag(struct child *c, int flag); -extern GtkWidget *childBox(struct child *c); -extern void childSetMargined(struct child *c, int margined); - -// draw.c -extern uiDrawContext *newContext(cairo_t *); -extern void freeContext(uiDrawContext *); - -// drawtext.c -extern uiDrawTextFont *mkTextFont(PangoFont *f, gboolean add); -extern PangoFont *pangoDescToPangoFont(PangoFontDescription *pdesc); - -// graphemes.c -extern ptrdiff_t *graphemes(const char *text, PangoContext *context); - -// image.c -/*TODO remove this*/typedef struct uiImage uiImage; -extern cairo_surface_t *imageAppropriateSurface(uiImage *i, GtkWidget *w); - -// cellrendererbutton.c -extern GtkCellRenderer *newCellRendererButton(void); - -// future.c -extern void loadFutures(void); -extern PangoAttribute *FUTURE_pango_attr_foreground_alpha_new(guint16 alpha); -extern gboolean FUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, gint pos, const char *name); - -// gl.c -extern uiGLContext *createGLContext(GtkWidget* widget, int maj, int min); -extern void freeGLContext(uiGLContext* glctx); -extern void areaDrawGL(GtkWidget* widget, uiAreaDrawParams* dp, cairo_t* cr, uiGLContext* glctx); - diff --git a/src/libui_sdl/libui/unix/util.c b/src/libui_sdl/libui/unix/util.c deleted file mode 100644 index 7f4f43fb..00000000 --- a/src/libui_sdl/libui/unix/util.c +++ /dev/null @@ -1,10 +0,0 @@ -// 18 april 2015 -#include "uipriv_unix.h" - -void setMargined(GtkContainer *c, int margined) -{ - if (margined) - gtk_container_set_border_width(c, gtkXMargin); - else - gtk_container_set_border_width(c, 0); -} diff --git a/src/libui_sdl/libui/unix/window.c b/src/libui_sdl/libui/unix/window.c deleted file mode 100644 index 6d5e2de2..00000000 --- a/src/libui_sdl/libui/unix/window.c +++ /dev/null @@ -1,462 +0,0 @@ -// 11 june 2015 -#include "uipriv_unix.h" - -struct uiWindow { - uiUnixControl c; - - GtkWidget *widget; - GtkContainer *container; - GtkWindow *window; - - GtkWidget *vboxWidget; - GtkContainer *vboxContainer; - GtkBox *vbox; - - GtkWidget *childHolderWidget; - GtkContainer *childHolderContainer; - - GtkWidget *menubar; - - uiControl *child; - int margined; - - int width, height; - - int (*onClosing)(uiWindow *, void *); - void *onClosingData; - void (*onContentSizeChanged)(uiWindow *, void *); - void *onContentSizeChangedData; - void (*onDropFile)(uiWindow *, char *, void *); - void *onDropFileData; - void (*onGetFocus)(uiWindow *, void *); - void *onGetFocusData; - void (*onLoseFocus)(uiWindow *, void *); - void *onLoseFocusData; - - gboolean fullscreen; -}; - -static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data) -{ - uiWindow *w = uiWindow(data); - - // manually destroy the window ourselves; don't let the delete-event handler do it - if ((*(w->onClosing))(w, w->onClosingData)) - uiControlDestroy(uiControl(w)); - // don't continue to the default delete-event handler; we destroyed the window by now - return TRUE; -} - -static void onSizeAllocate(GtkWidget *widget, GdkRectangle *allocation, gpointer data) -{ - uiWindow *w = uiWindow(data); - - // TODO deal with spurious size-allocates - (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); -} - -static gboolean onGetFocus(GtkWidget *win, GdkEvent *e, gpointer data) -{ - uiWindow *w = uiWindow(data); - if (w->onGetFocus) - w->onGetFocus(w, w->onGetFocusData); -} - -static gboolean onLoseFocus(GtkWidget *win, GdkEvent *e, gpointer data) -{ - uiWindow *w = uiWindow(data); - if (w->onLoseFocus) - w->onLoseFocus(w, w->onLoseFocusData); -} - -static int defaultOnClosing(uiWindow *w, void *data) -{ - return 0; -} - -static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) -{ - // do nothing -} - -static void uiWindowDestroy(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - // first hide ourselves - gtk_widget_hide(w->widget); - // now destroy the child - if (w->child != NULL) { - uiControlSetParent(w->child, NULL); - uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE); - uiControlDestroy(w->child); - } - // now destroy the menus, if any - if (w->menubar != NULL) - freeMenubar(w->menubar); - gtk_widget_destroy(w->childHolderWidget); - gtk_widget_destroy(w->vboxWidget); - // and finally free ourselves - // use gtk_widget_destroy() instead of g_object_unref() because GTK+ has internal references (see #165) - gtk_widget_destroy(w->widget); - uiFreeControl(uiControl(w)); -} - -void uiWindowSetPosition(uiWindow *w, int x, int y) -{ - if (!w) return; - - gtk_window_move(w->window, x, y); -} - -void uiWindowPosition(uiWindow *w, int *x, int *y) -{ - if (!w) return; - - int xx, yy; - gtk_window_get_position(w->window, &xx, &yy); - if (x) *x = xx; - if (y) *y = yy; -} - -uiUnixControlDefaultHandle(uiWindow) - -uiControl *uiWindowParent(uiControl *c) -{ - return NULL; -} - -void uiWindowSetParent(uiControl *c, uiControl *parent) -{ - uiUserBugCannotSetParentOnToplevel("uiWindow"); -} - -static int uiWindowToplevel(uiControl *c) -{ - return 1; -} - -uiUnixControlDefaultVisible(uiWindow) - -static void uiWindowShow(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - // don't use gtk_widget_show_all() as that will show all children, regardless of user settings - // don't use gtk_widget_show(); that doesn't bring to front or give keyboard focus - // (gtk_window_present() does call gtk_widget_show() though) - gtk_window_present(w->window); - - // set the size properly - int width = w->width; - int height = w->height; - if (w->menubar) - { - GtkRequisition min, nat; - int menuheight; - gtk_widget_get_preferred_size(w->menubar, &min, &nat); - menuheight = min.height; - if (nat.height > menuheight) menuheight = nat.height; - height += menuheight; - } - gtk_window_resize(w->window, width, height); -} - -static void uiWindowSetFocus(uiControl* c) -{ - gtk_window_present(GTK_WINDOW(uiWindow(c)->widget)); -} - -uiUnixControlDefaultHide(uiWindow) -uiUnixControlDefaultEnabled(uiWindow) -uiUnixControlDefaultEnable(uiWindow) -uiUnixControlDefaultDisable(uiWindow) -//uiUnixControlDefaultSetFocus(uiWindow) -uiUnixControlDefaultSetMinSize(uiWindow) -// TODO? -uiUnixControlDefaultSetContainer(uiWindow) - -char *uiWindowTitle(uiWindow *w) -{ - return uiUnixStrdupText(gtk_window_get_title(w->window)); -} - -void uiWindowSetTitle(uiWindow *w, const char *title) -{ - gtk_window_set_title(w->window, title); -} - -void uiWindowContentSize(uiWindow *w, int *width, int *height) -{ - GtkAllocation allocation; - - gtk_widget_get_allocation(w->childHolderWidget, &allocation); - *width = allocation.width; - *height = allocation.height; -} - -void uiWindowSetContentSize(uiWindow *w, int width, int height) -{ - GtkAllocation childAlloc; - gint winWidth, winHeight; - - // we need to resize the child holder widget to the given size - // we can't resize that without running the event loop - // but we can do gtk_window_set_size() - // so how do we deal with the differences in sizes? - // simple arithmetic, of course! - - // from what I can tell, the return from gtk_widget_get_allocation(w->window) and gtk_window_get_size(w->window) will be the same - // this is not affected by Wayland and not affected by GTK+ builtin CSD - // so we can safely juse use them to get the real window size! - // since we're using gtk_window_resize(), use the latter - gtk_window_get_size(w->window, &winWidth, &winHeight); - - // now get the child holder widget's current allocation - gtk_widget_get_allocation(w->childHolderWidget, &childAlloc); - // and punch that out of the window size - winWidth -= childAlloc.width; - winHeight -= childAlloc.height; - - // now we just need to add the new size back in - winWidth += width; - winHeight += height; - // and set it - // this will not move the window in my tests, so we're good - gtk_window_resize(w->window, winWidth, winHeight); -} - -int uiWindowMinimized(uiWindow *w) -{ - // TODO!! - return 0; -} - -void uiWindowSetMinimized(uiWindow *w, int minimized) -{ - if (minimized) - gtk_window_iconify(w->window); - else - gtk_window_deiconify(w->window); -} - -int uiWindowMaximized(uiWindow *w) -{ - return gtk_window_is_maximized(w->window); -} - -void uiWindowSetMaximized(uiWindow *w, int maximized) -{ - if (maximized) - gtk_window_maximize(w->window); - else - gtk_window_unmaximize(w->window); -} - - -int uiWindowFullscreen(uiWindow *w) -{ - return w->fullscreen; -} - -// TODO use window-state-event to track -// TODO does this send an extra size changed? -// TODO what behavior do we want? -void uiWindowSetFullscreen(uiWindow *w, int fullscreen) -{ - w->fullscreen = fullscreen; - if (w->fullscreen) - gtk_window_fullscreen(w->window); - else - gtk_window_unfullscreen(w->window); -} - -void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onContentSizeChanged = f; - w->onContentSizeChangedData = data; -} - -void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) -{ - w->onClosing = f; - w->onClosingData = data; -} - -void uiWindowOnDropFile(uiWindow *w, void (*f)(uiWindow *, char *, void *), void *data) -{ - w->onDropFile = f; - w->onDropFileData = data; -} - -void uiWindowOnGetFocus(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onGetFocus = f; - w->onGetFocusData = data; -} - -void uiWindowOnLoseFocus(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onLoseFocus = f; - w->onLoseFocusData = data; -} - -int uiWindowBorderless(uiWindow *w) -{ - return gtk_window_get_decorated(w->window) == FALSE; -} - -void uiWindowSetBorderless(uiWindow *w, int borderless) -{ - gtk_window_set_decorated(w->window, borderless == 0); -} - -// TODO save and restore expands and aligns -void uiWindowSetChild(uiWindow *w, uiControl *child) -{ - if (w->child != NULL) { - uiControlSetParent(w->child, NULL); - uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE); - } - w->child = child; - if (w->child != NULL) { - uiControlSetParent(w->child, uiControl(w)); - uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, FALSE); - } -} - -int uiWindowMargined(uiWindow *w) -{ - return w->margined; -} - -void uiWindowSetMargined(uiWindow *w, int margined) -{ - w->margined = margined; - setMargined(w->childHolderContainer, w->margined); -} - -static void onDragDataReceived(GtkWidget* widget, GdkDragContext* ctx, gint x, gint y, GtkSelectionData* data, guint info, guint time, gpointer userdata) -{ - uiWindow* w = (uiWindow*)userdata; - - if (gtk_selection_data_get_length(data) > 0 && gtk_selection_data_get_format(data) == 8) - { - gchar** files = gtk_selection_data_get_uris(data); - if (files != NULL && files[0] != NULL) - { - // TODO: multi file support? - - gboolean success = FALSE; - - gchar* file = g_filename_from_uri(files[0], NULL, NULL); - if (file) - { - if (w->onDropFile) - w->onDropFile(w, file, w->onDropFileData); - - success = TRUE; - g_free(file); - } - - - g_strfreev(files); - gtk_drag_finish(ctx, success, FALSE, time); - return; - } - - if (files != NULL) g_strfreev(files); - gtk_drag_finish(ctx, FALSE, FALSE, time); - } -} - -void uiWindowSetDropTarget(uiWindow* w, int drop) -{ - if (!drop) - { - gtk_drag_dest_unset(w->widget); - return; - } - - GtkTargetEntry entry; - entry.target = "text/uri-list"; - entry.flags = GTK_TARGET_OTHER_APP; - entry.info = 1; - - // CHECKME: action copy? - gtk_drag_dest_set(w->widget, GTK_DEST_DEFAULT_ALL, &entry, 1, GDK_ACTION_COPY|GDK_ACTION_MOVE); - - g_signal_connect(w->widget, "drag-data-received", G_CALLBACK(onDragDataReceived), w); -} - -uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, int hasMenubar, int resizable) -{ - uiWindow *w; - - if (!resizable) maximized = 0; - - uiUnixNewControl(uiWindow, w); - - w->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); - w->container = GTK_CONTAINER(w->widget); - w->window = GTK_WINDOW(w->widget); - - gtk_window_set_title(w->window, title); - gtk_window_resize(w->window, width, height); - - w->vboxWidget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - w->vboxContainer = GTK_CONTAINER(w->vboxWidget); - w->vbox = GTK_BOX(w->vboxWidget); - - // set the vbox as the GtkWindow child - gtk_container_add(w->container, w->vboxWidget); - - if (hasMenubar) { - w->menubar = makeMenubar(uiWindow(w)); - gtk_container_add(w->vboxContainer, w->menubar); - } - else - w->menubar = NULL; - - w->childHolderWidget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - w->childHolderContainer = GTK_CONTAINER(w->childHolderWidget); - gtk_widget_set_hexpand(w->childHolderWidget, TRUE); - gtk_widget_set_halign(w->childHolderWidget, GTK_ALIGN_FILL); - gtk_widget_set_vexpand(w->childHolderWidget, TRUE); - gtk_widget_set_valign(w->childHolderWidget, GTK_ALIGN_FILL); - gtk_box_set_homogeneous(GTK_BOX(w->childHolderWidget), TRUE); - gtk_container_add(w->vboxContainer, w->childHolderWidget); - - // show everything in the vbox, but not the GtkWindow itself - gtk_widget_show_all(w->vboxWidget); - - // and connect our events - g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w); - g_signal_connect(w->childHolderWidget, "size-allocate", G_CALLBACK(onSizeAllocate), w); - g_signal_connect(w->widget, "focus-in-event", G_CALLBACK(onGetFocus), w); - g_signal_connect(w->widget, "focus-out-event", G_CALLBACK(onLoseFocus), w); - - uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); - - uiWindowOnDropFile(w, NULL, NULL); - uiWindowOnGetFocus(w, NULL, NULL); - uiWindowOnLoseFocus(w, NULL, NULL); - - // normally it's SetParent() that does this, but we can't call SetParent() on a uiWindow - // TODO we really need to clean this up, especially since see uiWindowDestroy() above - g_object_ref(w->widget); - - gtk_window_set_resizable(w->window, resizable?TRUE:FALSE); - - w->width = width; - w->height = height; - - if (maximized) - gtk_window_maximize(w->window); - else - gtk_window_set_position(w->window, GTK_WIN_POS_CENTER); - - return w; -} - diff --git a/src/libui_sdl/libui/windows/CMakeLists.txt b/src/libui_sdl/libui/windows/CMakeLists.txt deleted file mode 100644 index 24d4ad96..00000000 --- a/src/libui_sdl/libui/windows/CMakeLists.txt +++ /dev/null @@ -1,92 +0,0 @@ -# 3 june 2016 - -list(APPEND _LIBUI_SOURCES - windows/alloc.cpp - windows/area.cpp - windows/areadraw.cpp - windows/areaevents.cpp - windows/areascroll.cpp - windows/areautil.cpp - windows/box.cpp - windows/button.cpp - windows/checkbox.cpp - windows/colorbutton.cpp - windows/colordialog.cpp - windows/combobox.cpp - windows/container.cpp - windows/control.cpp - windows/d2dscratch.cpp - windows/datetimepicker.cpp - windows/debug.cpp - windows/draw.cpp - windows/drawmatrix.cpp - windows/drawpath.cpp - windows/drawtext.cpp - windows/dwrite.cpp - windows/editablecombo.cpp - windows/entry.cpp - windows/events.cpp - windows/fontbutton.cpp - windows/fontdialog.cpp - windows/form.cpp - windows/gl.cpp - windows/graphemes.cpp - windows/grid.cpp - windows/group.cpp - windows/init.cpp - windows/label.cpp - windows/main.cpp - windows/menu.cpp - windows/multilineentry.cpp - windows/parent.cpp - windows/progressbar.cpp - windows/radiobuttons.cpp - windows/separator.cpp - windows/sizing.cpp - windows/slider.cpp - windows/spinbox.cpp - windows/stddialogs.cpp - windows/tab.cpp - windows/tabpage.cpp - windows/text.cpp - windows/utf16.cpp - windows/utilwin.cpp - windows/window.cpp - windows/winpublic.cpp - windows/winutil.cpp - windows/resources.rc -) -set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE) - -list(APPEND _LIBUI_INCLUDEDIRS - windows -) -set(_LIBUI_INCLUDEDIRS _LIBUI_INCLUDEDIRS PARENT_SCOPE) - -# Windows won't link resources in static libraries; we need to provide the libui.res file in this case. -set(_LIBUINAME libui PARENT_SCOPE) -if(NOT BUILD_SHARED_LIBS) - set(_LIBUI_STATIC_RES ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/libui.res PARENT_SCOPE) -endif() -macro(_handle_static) - # TODO this full path feels hacky - add_custom_command( - TARGET libui POST_BUILD - COMMAND - ${CMAKE_COMMAND} -E copy $/CMakeFiles/libui.dir/windows/resources.rc.obj ${_LIBUI_STATIC_RES} - COMMENT "Copying libui.res") -endmacro() - -# notice that usp10 comes before gdi32 -# TODO prune this list -set(_LIBUI_LIBS - user32 kernel32 usp10 gdi32 comctl32 uxtheme msimg32 comdlg32 d2d1 dwrite ole32 oleaut32 oleacc uuid -PARENT_SCOPE) - -if(NOT MSVC) - if(BUILD_SHARED_LIBS) - message(FATAL_ERROR - "Sorry, but libui for Windows can currently only be built as a static library with MinGW. You will need to either build as a static library or switch to MSVC." - ) - endif() -endif() diff --git a/src/libui_sdl/libui/windows/_uipriv_migrate.hpp b/src/libui_sdl/libui/windows/_uipriv_migrate.hpp deleted file mode 100644 index 13d3670e..00000000 --- a/src/libui_sdl/libui/windows/_uipriv_migrate.hpp +++ /dev/null @@ -1,61 +0,0 @@ - -// menu.c -extern HMENU makeMenubar(void); -extern const uiMenuItem *menuIDToItem(UINT_PTR); -extern void runMenuEvent(WORD, uiWindow *); -extern void freeMenubar(HMENU); -extern void uninitMenus(void); - -// draw.c -extern HRESULT initDraw(void); -extern void uninitDraw(void); -extern ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd); -extern uiDrawContext *newContext(ID2D1RenderTarget *); -extern void freeContext(uiDrawContext *); - -// dwrite.cpp -#ifdef __cplusplus -extern IDWriteFactory *dwfactory; -#endif -extern HRESULT initDrawText(void); -extern void uninitDrawText(void); -#ifdef __cplusplus -struct fontCollection { - IDWriteFontCollection *fonts; - WCHAR userLocale[LOCALE_NAME_MAX_LENGTH]; - int userLocaleSuccess; -}; -extern fontCollection *loadFontCollection(void); -extern WCHAR *fontCollectionFamilyName(fontCollection *fc, IDWriteFontFamily *family); -extern void fontCollectionFree(fontCollection *fc); -extern WCHAR *fontCollectionCorrectString(fontCollection *fc, IDWriteLocalizedStrings *names); -#endif - -// drawtext.cpp -#ifdef __cplusplus -extern uiDrawTextFont *mkTextFont(IDWriteFont *df, BOOL addRef, WCHAR *family, BOOL copyFamily, double size); -struct dwriteAttr { - uiDrawTextWeight weight; - uiDrawTextItalic italic; - uiDrawTextStretch stretch; - DWRITE_FONT_WEIGHT dweight; - DWRITE_FONT_STYLE ditalic; - DWRITE_FONT_STRETCH dstretch; -}; -extern void attrToDWriteAttr(struct dwriteAttr *attr); -extern void dwriteAttrToAttr(struct dwriteAttr *attr); -#endif - -// fontdialog.cpp -#ifdef __cplusplus -struct fontDialogParams { - IDWriteFont *font; - double size; - WCHAR *familyName; - WCHAR *styleName; -}; -extern BOOL showFontDialog(HWND parent, struct fontDialogParams *params); -extern void loadInitialFontDialogParams(struct fontDialogParams *params); -extern void destroyFontDialogParams(struct fontDialogParams *params); -extern WCHAR *fontDialogParamsToString(struct fontDialogParams *params); -#endif diff --git a/src/libui_sdl/libui/windows/alloc.cpp b/src/libui_sdl/libui/windows/alloc.cpp deleted file mode 100644 index cf6bd2ed..00000000 --- a/src/libui_sdl/libui/windows/alloc.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// 4 december 2014 -#include "uipriv_windows.hpp" - -typedef std::vector byteArray; - -static std::map heap; -static std::map types; - -void initAlloc(void) -{ - // do nothing -} - -void uninitAlloc(void) -{ - std::ostringstream oss; - std::string ossstr; // keep alive, just to be safe - - if (heap.size() == 0) - return; - for (const auto &alloc : heap) - // note the void * cast; otherwise it'll be treated as a string - oss << (void *) (alloc.first) << " " << types[alloc.second] << "\n"; - ossstr = oss.str(); - printf("data leak: %s\n", ossstr.c_str()); - userbug("Some data was leaked; either you left a uiControl lying around or there's a bug in libui itself. Leaked data:\n%s", ossstr.c_str()); -} - -#define rawBytes(pa) (&((*pa)[0])) - -void *uiAlloc(size_t size, const char *type) -{ - byteArray *out; - - out = new byteArray(size, 0); - heap[rawBytes(out)] = out; - types[out] = type; - return rawBytes(out); -} - -void *uiRealloc(void *_p, size_t size, const char *type) -{ - uint8_t *p = (uint8_t *) _p; - byteArray *arr; - - if (p == NULL) - return uiAlloc(size, type); - arr = heap[p]; - arr->resize(size, 0); - heap.erase(p); - heap[rawBytes(arr)] = arr; - return rawBytes(arr); -} - -void uiFree(void *_p) -{ - uint8_t *p = (uint8_t *) _p; - - if (p == NULL) - implbug("attempt to uiFree(NULL)"); - types.erase(heap[p]); - delete heap[p]; - heap.erase(p); -} diff --git a/src/libui_sdl/libui/windows/area.cpp b/src/libui_sdl/libui/windows/area.cpp deleted file mode 100644 index 72d5145f..00000000 --- a/src/libui_sdl/libui/windows/area.cpp +++ /dev/null @@ -1,291 +0,0 @@ -// 8 september 2015 -#include "uipriv_windows.hpp" -#include "area.hpp" - -// TODO handle WM_DESTROY/WM_NCDESTROY -// TODO same for other Direct2D stuff -static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - uiArea *a; - CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; - RECT client; - WINDOWPOS *wp = (WINDOWPOS *) lParam; - LRESULT lResult; - - a = (uiArea *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); - if (a == NULL) { - if (uMsg == WM_CREATE) { - a = (uiArea *) (cs->lpCreateParams); - // assign a->hwnd here so we can use it immediately - a->hwnd = hwnd; - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) a); - } - // fall through to DefWindowProcW() anyway - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } - - // always recreate the render target if necessary - if (!a->openGL) - { - if (a->rt == NULL) - a->rt = makeHWNDRenderTarget(a->hwnd); - } - - if (areaDoDraw(a, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - - if (uMsg == WM_WINDOWPOSCHANGED) { - if ((wp->flags & SWP_NOSIZE) != 0) - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - a->width = -1; - a->height = -1; - uiWindowsEnsureGetClientRect(a->hwnd, &client); - areaDrawOnResize(a, &client); - areaScrollOnResize(a, &client); - { - double w, h; - loadAreaSize(a, &w, &h); - a->ah->Resize(a->ah, a, (int)w, (int)h); - } - return 0; - } - - if (areaDoScroll(a, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - if (areaDoEvents(a, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - - // nothing done - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -// control implementation - -uiWindowsControlAllDefaultsExceptDestroy(uiArea) - -static void uiAreaDestroy(uiControl *c) -{ - uiArea* a = uiArea(c); - if (a->openGL && a->glcontext) freeGLContext(a->glcontext); - uiWindowsEnsureDestroyWindow(a->hwnd); - uiFreeControl(c); -} - -static void uiAreaMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - *width = c->c.MinWidth; - if (*width < 1) *width = 1; - - *height = c->c.MinHeight; - if (*height < 1) *height = 1; -} - -ATOM registerAreaClass(HICON hDefaultIcon, HCURSOR hDefaultCursor) -{ - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = areaClass; - wc.lpfnWndProc = areaWndProc; - wc.hInstance = hInstance; - wc.hIcon = hDefaultIcon; - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - // this is just to be safe; see the InvalidateRect() call in the WM_WINDOWPOSCHANGED handler for more details - wc.style = CS_HREDRAW | CS_VREDRAW; - return RegisterClassW(&wc); -} - -void unregisterArea(void) -{ - if (UnregisterClassW(areaClass, hInstance) == 0) - logLastError(L"error unregistering uiArea window class"); -} - -void uiAreaSetSize(uiArea *a, int width, int height) -{ - a->scrollWidth = width; - a->scrollHeight = height; - areaUpdateScroll(a); -} - -void uiAreaQueueRedrawAll(uiArea *a) -{ - // don't erase the background; we do that ourselves in doPaint() - invalidateRect(a->hwnd, NULL, FALSE); -} - -void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height) -{ - // TODO -} - -void uiAreaBeginUserWindowMove(uiArea *a) -{ - HWND toplevel; - - // TODO restrict execution - ReleaseCapture(); // TODO use properly and reset internal data structures - toplevel = parentToplevel(a->hwnd); - if (toplevel == NULL) { - // TODO - return; - } - // see http://stackoverflow.com/questions/40249940/how-do-i-initiate-a-user-mouse-driven-move-or-resize-for-custom-window-borders-o#40250654 - SendMessageW(toplevel, WM_SYSCOMMAND, - SC_MOVE | 2, 0); -} - -void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge) -{ - HWND toplevel; - WPARAM wParam; - - // TODO restrict execution - ReleaseCapture(); // TODO use properly and reset internal data structures - toplevel = parentToplevel(a->hwnd); - if (toplevel == NULL) { - // TODO - return; - } - // see http://stackoverflow.com/questions/40249940/how-do-i-initiate-a-user-mouse-driven-move-or-resize-for-custom-window-borders-o#40250654 - wParam = SC_SIZE; - switch (edge) { - case uiWindowResizeEdgeLeft: - wParam |= 1; - break; - case uiWindowResizeEdgeTop: - wParam |= 3; - break; - case uiWindowResizeEdgeRight: - wParam |= 2; - break; - case uiWindowResizeEdgeBottom: - wParam |= 6; - break; - case uiWindowResizeEdgeTopLeft: - wParam |= 4; - break; - case uiWindowResizeEdgeTopRight: - wParam |= 5; - break; - case uiWindowResizeEdgeBottomLeft: - wParam |= 7; - break; - case uiWindowResizeEdgeBottomRight: - wParam |= 8; - break; - } - SendMessageW(toplevel, WM_SYSCOMMAND, - wParam, 0); -} - - -void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b) -{ - a->bgR = r; - a->bgG = g; - a->bgB = b; -} - - -uiArea *uiNewArea(uiAreaHandler *ah) -{ - uiArea *a; - - uiWindowsNewControl(uiArea, a); - - a->width = -1; - a->height = -1; - - a->ah = ah; - a->scrolling = FALSE; - clickCounterReset(&(a->cc)); - - // a->hwnd is assigned in areaWndProc() - uiWindowsEnsureCreateControlHWND(0, - areaClass, L"", - 0, - hInstance, a, - FALSE); - - uiAreaSetBackgroundColor(a, -1, -1, -1); - - a->openGL = 0; - - return a; -} - -uiGLContext *uiAreaGetGLContext(uiArea* a) -{ - if (!a->openGL) userbug("trying to get GL context from non-GL area"); - - return a->glcontext; -} - -uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions) -{ - uiArea *a; - - uiWindowsNewControl(uiArea, a); - - a->width = -1; - a->height = -1; - - a->ah = ah; - a->scrolling = FALSE; - clickCounterReset(&(a->cc)); - - // a->hwnd is assigned in areaWndProc() - uiWindowsEnsureCreateControlHWND(0, - areaClass, L"", - 0, - hInstance, a, - FALSE); - - uiAreaSetBackgroundColor(a, -1, -1, -1); - - a->openGL = 1; - - for (int i = 0; req_versions[i]; i++) - { - int major = uiGLVerMajor(req_versions[i]); - int minor = uiGLVerMinor(req_versions[i]); - a->glcontext = createGLContext(a, major, minor); - if (a->glcontext) break; - } - - return a; -} - -uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height) -{ - uiArea *a; - - uiWindowsNewControl(uiArea, a); - - a->width = -1; - a->height = -1; - - a->ah = ah; - a->scrolling = TRUE; - a->scrollWidth = width; - a->scrollHeight = height; - clickCounterReset(&(a->cc)); - - // a->hwnd is assigned in areaWndProc() - uiWindowsEnsureCreateControlHWND(0, - areaClass, L"", - WS_HSCROLL | WS_VSCROLL, - hInstance, a, - FALSE); - - uiAreaSetBackgroundColor(a, -1, -1, -1); - - a->openGL = 0; // TODO, eventually??? - - // set initial scrolling parameters - areaUpdateScroll(a); - - return a; -} diff --git a/src/libui_sdl/libui/windows/area.hpp b/src/libui_sdl/libui/windows/area.hpp deleted file mode 100644 index cfc45a47..00000000 --- a/src/libui_sdl/libui/windows/area.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// 18 december 2015 - -// TODOs -// - things look very wrong on initial draw -// - initial scrolling is not set properly -// - should background be inherited from parent control? - -struct uiArea { - uiWindowsControl c; - HWND hwnd; - uiAreaHandler *ah; - - int width, height; - - BOOL scrolling; - int scrollWidth; - int scrollHeight; - int hscrollpos; - int vscrollpos; - int hwheelCarry; - int vwheelCarry; - - clickCounter cc; - BOOL capturing; - - BOOL inside; - BOOL tracking; - - int bgR, bgG, bgB; - - int openGL; - uiGLContext* glcontext; - - ID2D1HwndRenderTarget *rt; -}; - -// areadraw.cpp -extern BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); -extern void areaDrawOnResize(uiArea *, RECT *); - -// areascroll.cpp -extern BOOL areaDoScroll(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); -extern void areaScrollOnResize(uiArea *, RECT *); -extern void areaUpdateScroll(uiArea *a); - -// areaevents.cpp -extern BOOL areaDoEvents(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); - -// areautil.cpp -extern void loadAreaSize(uiArea *a, double *width, double *height); -extern void pixelsToDIP(uiArea *a, double *x, double *y); -extern void dipToPixels(uiArea *a, double *x, double *y); - -// gl.cpp -extern uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor); -extern void freeGLContext(uiGLContext* c); diff --git a/src/libui_sdl/libui/windows/areadraw.cpp b/src/libui_sdl/libui/windows/areadraw.cpp deleted file mode 100644 index f369255e..00000000 --- a/src/libui_sdl/libui/windows/areadraw.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// 8 september 2015 -#include "uipriv_windows.hpp" -#include "area.hpp" - -static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip) -{ - uiAreaHandler *ah = a->ah; - uiAreaDrawParams dp; - - if (a->openGL) - { - //(*(ah->Draw))(ah, a, &dp); - return S_OK; - } - - COLORREF bgcolorref; - D2D1_COLOR_F bgcolor; - D2D1_MATRIX_3X2_F scrollTransform; - - // no need to save or restore the graphics state to reset transformations; it's handled by resetTarget() in draw.c, called during the following - dp.Context = newContext(rt); - - loadAreaSize(a, &(dp.AreaWidth), &(dp.AreaHeight)); - - dp.ClipX = clip->left; - dp.ClipY = clip->top; - dp.ClipWidth = clip->right - clip->left; - dp.ClipHeight = clip->bottom - clip->top; - if (a->scrolling) { - dp.ClipX += a->hscrollpos; - dp.ClipY += a->vscrollpos; - } - - rt->BeginDraw(); - - { - float dpi_x, dpi_y; - D2D1_MATRIX_3X2_F dm; - rt->GetDpi(&dpi_x, &dpi_y); - ZeroMemory(&dm, sizeof (D2D1_MATRIX_3X2_F)); - dm._11 = 96.f/dpi_x; - dm._22 = 96.f/dpi_y; - rt->SetTransform(&dm); - } - - if (a->scrolling) { - ZeroMemory(&scrollTransform, sizeof (D2D1_MATRIX_3X2_F)); - scrollTransform._11 = 1; - scrollTransform._22 = 1; - // negative because we want nonzero scroll positions to move the drawing area up/left - scrollTransform._31 = -a->hscrollpos; - scrollTransform._32 = -a->vscrollpos; - rt->SetTransform(&scrollTransform); - } - - // TODO push axis aligned clip - - // TODO only clear the clip area - // TODO clear with actual background brush - if (a->bgR != -1) - { - bgcolor.r = ((float) a->bgR) / 255.0; - bgcolor.g = ((float) a->bgG) / 255.0; - bgcolor.b = ((float) a->bgB) / 255.0; - bgcolor.a = 1.0; - } - else - { - bgcolorref = GetSysColor(COLOR_BTNFACE); - bgcolor.r = ((float) GetRValue(bgcolorref)) / 255.0; - // due to utter apathy on Microsoft's part, GetGValue() does not work with MSVC's Run-Time Error Checks - // it has not worked since 2008 and they have *never* fixed it - // TODO now that -RTCc has just been deprecated entirely, should we switch back? - bgcolor.g = ((float) ((BYTE) ((bgcolorref & 0xFF00) >> 8))) / 255.0; - bgcolor.b = ((float) GetBValue(bgcolorref)) / 255.0; - bgcolor.a = 1.0; - } - rt->Clear(&bgcolor); - - (*(ah->Draw))(ah, a, &dp); - - freeContext(dp.Context); - - // TODO pop axis aligned clip - - return rt->EndDraw(NULL, NULL); -} - -static void onWM_PAINT(uiArea *a) -{ - RECT clip; - HRESULT hr; - - // do not clear the update rect; we do that ourselves in doPaint() - if (GetUpdateRect(a->hwnd, &clip, FALSE) == 0) { - // set a zero clip rect just in case GetUpdateRect() didn't change clip - clip.left = 0; - clip.top = 0; - clip.right = 0; - clip.bottom = 0; - } - hr = doPaint(a, a->rt, &clip); - switch (hr) { - case S_OK: - if (ValidateRect(a->hwnd, NULL) == 0) - logLastError(L"error validating rect"); - break; - case D2DERR_RECREATE_TARGET: - // DON'T validate the rect - // instead, simply drop the render target - // we'll get another WM_PAINT and make the render target again - // TODO would this require us to invalidate the entire client area? - a->rt->Release();; - a->rt = NULL; - break; - default: - logHRESULT(L"error painting", hr); - } -} - -static void onWM_PRINTCLIENT(uiArea *a, HDC dc) -{ - // TODO???? - if (a->openGL) return; - - ID2D1DCRenderTarget *rt; - RECT client; - HRESULT hr; - - uiWindowsEnsureGetClientRect(a->hwnd, &client); - rt = makeHDCRenderTarget(dc, &client); - hr = doPaint(a, rt, &client); - if (hr != S_OK) - logHRESULT(L"error printing uiArea client area", hr); - rt->Release(); -} - -BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - switch (uMsg) { - case WM_PAINT: - onWM_PAINT(a); - *lResult = 0; - return TRUE; - case WM_PRINTCLIENT: - onWM_PRINTCLIENT(a, (HDC) wParam); - *lResult = 0; - return TRUE; - } - return FALSE; -} - -// TODO only if the render target wasn't just created? -void areaDrawOnResize(uiArea *a, RECT *newClient) -{ - if (!a->openGL) - { - D2D1_SIZE_U size; - - size.width = newClient->right - newClient->left; - size.height = newClient->bottom - newClient->top; - // don't track the error; we'll get that in EndDraw() - // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx - a->rt->Resize(&size); - } - - // according to Rick Brewster, we must always redraw the entire client area after calling ID2D1RenderTarget::Resize() (see http://stackoverflow.com/a/33222983/3408572) - // we used to have a uiAreaHandler.RedrawOnResize() method to decide this; now you know why we don't anymore - invalidateRect(a->hwnd, NULL, TRUE); -} diff --git a/src/libui_sdl/libui/windows/areaevents.cpp b/src/libui_sdl/libui/windows/areaevents.cpp deleted file mode 100644 index 46d6ab90..00000000 --- a/src/libui_sdl/libui/windows/areaevents.cpp +++ /dev/null @@ -1,435 +0,0 @@ -// 8 september 2015 -#include "uipriv_windows.hpp" -#include "area.hpp" - -static uiModifiers getModifiers(void) -{ - uiModifiers m = 0; - - if ((GetKeyState(VK_CONTROL) & 0x80) != 0) - m |= uiModifierCtrl; - if ((GetKeyState(VK_MENU) & 0x80) != 0) - m |= uiModifierAlt; - if ((GetKeyState(VK_SHIFT) & 0x80) != 0) - m |= uiModifierShift; - if ((GetKeyState(VK_LWIN) & 0x80) != 0) - m |= uiModifierSuper; - if ((GetKeyState(VK_RWIN) & 0x80) != 0) - m |= uiModifierSuper; - return m; -} - -/* -Windows doesn't natively support mouse crossing events. - -TrackMouseEvent() (and its comctl32.dll wrapper _TrackMouseEvent()) both allow for a window to receive the WM_MOUSELEAVE message when the mouse leaves the client area. There's no equivalent WM_MOUSEENTER because it can be simulated (https://blogs.msdn.microsoft.com/oldnewthing/20031013-00/?p=42193). - -Unfortunately, WM_MOUSELEAVE does not get generated while the mouse is captured. We need to capture for drag behavior to work properly, so this isn't going to mix well. - -So what we do: -- on WM_MOUSEMOVE, if we don't have the capture, start tracking - - this will handle the case of the capture being released while still in the area -- on WM_MOUSELEAVE, mark that we are no longer tracking - - Windows has already done the work of that for us; it's just a flag we use for the next part -- when starting capture, stop tracking if we are tracking -- if capturing, manually check if the pointer is in the client rect on each area event -*/ -static void track(uiArea *a, BOOL tracking) -{ - TRACKMOUSEEVENT tm; - - // do nothing if there's no change - if (a->tracking && tracking) - return; - if (!a->tracking && !tracking) - return; - - a->tracking = tracking; - ZeroMemory(&tm, sizeof (TRACKMOUSEEVENT)); - tm.cbSize = sizeof (TRACKMOUSEEVENT); - tm.dwFlags = TME_LEAVE; - if (!a->tracking) - tm.dwFlags |= TME_CANCEL; - tm.hwndTrack = a->hwnd; - if (_TrackMouseEvent(&tm) == 0) - logLastError(L"error setting up mouse tracking"); -} - -static void capture(uiArea *a, BOOL capturing) -{ - // do nothing if there's no change - if (a->capturing && capturing) - return; - if (!a->capturing && !capturing) - return; - - // change flag first as ReleaseCapture() sends WM_CAPTURECHANGED - a->capturing = capturing; - if (a->capturing) { - track(a, FALSE); - SetCapture(a->hwnd); - } else - if (ReleaseCapture() == 0) - logLastError(L"error releasing capture on drag"); -} - -static void areaMouseEvent(uiArea *a, int down, int up, WPARAM wParam, LPARAM lParam) -{ - uiAreaMouseEvent me; - int button; - POINT clientpt; - RECT client; - BOOL inClient; - double xpix, ypix; - - if (a->capturing) { - clientpt.x = GET_X_LPARAM(lParam); - clientpt.y = GET_Y_LPARAM(lParam); - uiWindowsEnsureGetClientRect(a->hwnd, &client); - inClient = PtInRect(&client, clientpt); - if (inClient && !a->inside) { - a->inside = TRUE; - (*(a->ah->MouseCrossed))(a->ah, a, 0); - clickCounterReset(&(a->cc)); - } else if (!inClient && a->inside) { - a->inside = FALSE; - (*(a->ah->MouseCrossed))(a->ah, a, 1); - clickCounterReset(&(a->cc)); - } - } - - xpix = (double) GET_X_LPARAM(lParam); - ypix = (double) GET_Y_LPARAM(lParam); - // these are in pixels; we need points - //pixelsToDIP(a, &xpix, &ypix); - me.X = xpix; - me.Y = ypix; - if (a->scrolling) { - me.X += a->hscrollpos; - me.Y += a->vscrollpos; - } - - loadAreaSize(a, &(me.AreaWidth), &(me.AreaHeight)); - - me.Down = down; - me.Up = up; - me.Count = 0; - if (me.Down != 0) - // GetMessageTime() returns LONG and GetDoubleClckTime() returns UINT, which are int32 and uint32, respectively, but we don't need to worry about the signedness because for the same bit widths and two's complement arithmetic, s1-s2 == u1-u2 if bits(s1)==bits(s2) and bits(u1)==bits(u2) (and Windows requires two's complement: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/27/422551.aspx) - // signedness isn't much of an issue for these calls anyway because http://stackoverflow.com/questions/24022225/what-are-the-sign-extension-rules-for-calling-windows-api-functions-stdcall-t and that we're only using unsigned values (think back to how you (didn't) handle signedness in assembly language) AND because of the above AND because the statistics below (time interval and width/height) really don't make sense if negative - // GetSystemMetrics() returns int, which is int32 - me.Count = clickCounterClick(&(a->cc), me.Down, - me.X, me.Y, - GetMessageTime(), GetDoubleClickTime(), - GetSystemMetrics(SM_CXDOUBLECLK) / 2, - GetSystemMetrics(SM_CYDOUBLECLK) / 2); - - // though wparam will contain control and shift state, let's just one function to get modifiers for both keyboard and mouse events; it'll work the same anyway since we have to do this for alt and windows key (super) - me.Modifiers = getModifiers(); - - button = me.Down; - if (button == 0) - button = me.Up; - me.Held1To64 = 0; - if (button != 1 && (wParam & MK_LBUTTON) != 0) - me.Held1To64 |= 1 << 0; - if (button != 2 && (wParam & MK_MBUTTON) != 0) - me.Held1To64 |= 1 << 1; - if (button != 3 && (wParam & MK_RBUTTON) != 0) - me.Held1To64 |= 1 << 2; - if (button != 4 && (wParam & MK_XBUTTON1) != 0) - me.Held1To64 |= 1 << 3; - if (button != 5 && (wParam & MK_XBUTTON2) != 0) - me.Held1To64 |= 1 << 4; - - // on Windows, we have to capture on drag ourselves - if (me.Down != 0) - capture(a, TRUE); - // only release capture when all buttons released - if (me.Up != 0 && me.Held1To64 == 0) - capture(a, FALSE); - - (*(a->ah->MouseEvent))(a->ah, a, &me); -} - -// TODO genericize this so it can be called above -static void onMouseEntered(uiArea *a) -{ - if (a->inside) - return; - if (a->capturing) // we handle mouse crossing in areaMouseEvent() - return; - track(a, TRUE); - (*(a->ah->MouseCrossed))(a->ah, a, 0); - // TODO figure out why we did this to begin with; either we do it on both GTK+ and Windows or not at all - clickCounterReset(&(a->cc)); -} - -// TODO genericize it so that it can be called above -static void onMouseLeft(uiArea *a) -{ - a->tracking = FALSE; - a->inside = FALSE; - (*(a->ah->MouseCrossed))(a->ah, a, 1); - // TODO figure out why we did this to begin with; either we do it on both GTK+ and Windows or not at all - clickCounterReset(&(a->cc)); -} - -// we use VK_SNAPSHOT as a sentinel because libui will never support the print screen key; that key belongs to the user -struct extkeymap { - WPARAM vk; - uiExtKey extkey; -}; - -// all mappings come from GLFW - https://github.com/glfw/glfw/blob/master/src/win32_window.c#L152 -static const struct extkeymap numpadExtKeys[] = { - { VK_HOME, uiExtKeyN7 }, - { VK_UP, uiExtKeyN8 }, - { VK_PRIOR, uiExtKeyN9 }, - { VK_LEFT, uiExtKeyN4 }, - { VK_CLEAR, uiExtKeyN5 }, - { VK_RIGHT, uiExtKeyN6 }, - { VK_END, uiExtKeyN1 }, - { VK_DOWN, uiExtKeyN2 }, - { VK_NEXT, uiExtKeyN3 }, - { VK_INSERT, uiExtKeyN0 }, - { VK_DELETE, uiExtKeyNDot }, - { VK_SNAPSHOT, 0 }, -}; - -static const struct extkeymap extKeys[] = { - { VK_ESCAPE, uiExtKeyEscape }, - { VK_INSERT, uiExtKeyInsert }, - { VK_DELETE, uiExtKeyDelete }, - { VK_HOME, uiExtKeyHome }, - { VK_END, uiExtKeyEnd }, - { VK_PRIOR, uiExtKeyPageUp }, - { VK_NEXT, uiExtKeyPageDown }, - { VK_UP, uiExtKeyUp }, - { VK_DOWN, uiExtKeyDown }, - { VK_LEFT, uiExtKeyLeft }, - { VK_RIGHT, uiExtKeyRight }, - { VK_F1, uiExtKeyF1 }, - { VK_F2, uiExtKeyF2 }, - { VK_F3, uiExtKeyF3 }, - { VK_F4, uiExtKeyF4 }, - { VK_F5, uiExtKeyF5 }, - { VK_F6, uiExtKeyF6 }, - { VK_F7, uiExtKeyF7 }, - { VK_F8, uiExtKeyF8 }, - { VK_F9, uiExtKeyF9 }, - { VK_F10, uiExtKeyF10 }, - { VK_F11, uiExtKeyF11 }, - { VK_F12, uiExtKeyF12 }, - // numpad numeric keys and . are handled in common/areaevents.c - // numpad enter is handled in code below - { VK_ADD, uiExtKeyNAdd }, - { VK_SUBTRACT, uiExtKeyNSubtract }, - { VK_MULTIPLY, uiExtKeyNMultiply }, - { VK_DIVIDE, uiExtKeyNDivide }, - { VK_SNAPSHOT, 0 }, -}; - -static const struct { - WPARAM vk; - uiModifiers mod; -} modKeys[] = { - // even if the separate left/right aren't necessary, have them here anyway, just to be safe - { VK_CONTROL, uiModifierCtrl }, - { VK_LCONTROL, uiModifierCtrl }, - { VK_RCONTROL, uiModifierCtrl }, - { VK_MENU, uiModifierAlt }, - { VK_LMENU, uiModifierAlt }, - { VK_RMENU, uiModifierAlt }, - { VK_SHIFT, uiModifierShift }, - { VK_LSHIFT, uiModifierShift }, - { VK_RSHIFT, uiModifierShift }, - // there's no combined Windows key virtual-key code as there is with the others - { VK_LWIN, uiModifierSuper }, - { VK_RWIN, uiModifierSuper }, - { VK_SNAPSHOT, 0 }, -}; - -static int areaKeyEvent(uiArea *a, int up, WPARAM wParam, LPARAM lParam) -{ - uiAreaKeyEvent ke; - int righthand; - int i; - - ke.Key = 0; - ke.ExtKey = 0; - ke.Modifier = 0; - - ke.Modifiers = getModifiers(); - - ke.Scancode = (lParam >> 16) & 0x1FF; - - ke.Up = up; - ke.Repeat = (lParam & 0x40000000) ? 1:0; - - // Arisotura note: I don't actually need all this key decoding - // raw scancodes are all I need for this -#if 0 - // the numeric keypad keys when Num Lock is off are considered left-hand keys as the separate navigation buttons were added later - // the numeric keypad Enter, however, is a right-hand key because it has the same virtual-key code as the typewriter Enter - righthand = (lParam & 0x01000000) != 0; - if (righthand) { - if (wParam == VK_RETURN) { - ke.ExtKey = uiExtKeyNEnter; - goto keyFound; - } - } else - // this is special handling for numpad keys to ignore the state of Num Lock and Shift; see http://blogs.msdn.com/b/oldnewthing/archive/2004/09/06/226045.aspx and https://github.com/glfw/glfw/blob/master/src/win32_window.c#L152 - for (i = 0; numpadExtKeys[i].vk != VK_SNAPSHOT; i++) - if (numpadExtKeys[i].vk == wParam) { - ke.ExtKey = numpadExtKeys[i].extkey; - goto keyFound; - } - - // okay, those above cases didn't match anything - // first try the extended keys - for (i = 0; extKeys[i].vk != VK_SNAPSHOT; i++) - if (extKeys[i].vk == wParam) { - ke.ExtKey = extKeys[i].extkey; - goto keyFound; - } - - // then try modifier keys - for (i = 0; modKeys[i].vk != VK_SNAPSHOT; i++) - if (modKeys[i].vk == wParam) { - ke.Modifier = modKeys[i].mod; - // and don't include the key in Modifiers - ke.Modifiers &= ~ke.Modifier; - goto keyFound; - } - - // and finally everything else - if (fromScancode((lParam >> 16) & 0xFF, &ke)) - goto keyFound; - - // not a supported key, assume unhandled - // TODO the original code only did this if ke.Modifiers == 0 - why? - return 0; - -keyFound: -#endif - return (*(a->ah->KeyEvent))(a->ah, a, &ke); -} - -char* uiKeyName(int scancode) -{ - WCHAR tmp[64]; - GetKeyNameText(scancode<<16, tmp, 64); - return toUTF8(tmp); -} - -// We don't handle the standard Windows keyboard messages directly, to avoid both the dialog manager and TranslateMessage(). -// Instead, we set up a message filter and do things there. -// That stuff is later in this file. -enum { - // start at 0x40 to avoid clobbering dialog messages - msgAreaKeyDown = WM_USER + 0x40, - msgAreaKeyUp, -}; - -BOOL areaDoEvents(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - switch (uMsg) { - case WM_ACTIVATE: - // don't keep the double-click timer running if the user switched programs in between clicks - clickCounterReset(&(a->cc)); - *lResult = 0; - return TRUE; - case WM_MOUSEMOVE: - onMouseEntered(a); - areaMouseEvent(a, 0, 0, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_MOUSELEAVE: - onMouseLeft(a); - *lResult = 0; - return TRUE; - case WM_LBUTTONDOWN: - SetFocus(a->hwnd); - areaMouseEvent(a, 1, 0, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_LBUTTONUP: - areaMouseEvent(a, 0, 1, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_MBUTTONDOWN: - SetFocus(a->hwnd); - areaMouseEvent(a, 2, 0, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_MBUTTONUP: - areaMouseEvent(a, 0, 2, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_RBUTTONDOWN: - SetFocus(a->hwnd); - areaMouseEvent(a, 3, 0, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_RBUTTONUP: - areaMouseEvent(a, 0, 3, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_XBUTTONDOWN: - SetFocus(a->hwnd); - // values start at 1; we want them to start at 4 - areaMouseEvent(a, - GET_XBUTTON_WPARAM(wParam) + 3, 0, - GET_KEYSTATE_WPARAM(wParam), lParam); - *lResult = TRUE; // XBUTTON messages are different! - return TRUE; - case WM_XBUTTONUP: - areaMouseEvent(a, - 0, GET_XBUTTON_WPARAM(wParam) + 3, - GET_KEYSTATE_WPARAM(wParam), lParam); - *lResult = TRUE; // XBUTTON messages are different! - return TRUE; - case WM_CAPTURECHANGED: - if (a->capturing) { - a->capturing = FALSE; - (*(a->ah->DragBroken))(a->ah, a); - } - *lResult = 0; - return TRUE; - case msgAreaKeyDown: - *lResult = (LRESULT) areaKeyEvent(a, 0, wParam, lParam); - return TRUE; - case msgAreaKeyUp: - *lResult = (LRESULT) areaKeyEvent(a, 1, wParam, lParam); - return TRUE; - } - return FALSE; -} - -// TODO affect visibility properly -// TODO what did this mean -BOOL areaFilter(MSG *msg) -{ - LRESULT handled; - - // is the recipient an area? - if (msg->hwnd == NULL) // this can happen; for example, WM_TIMER - return FALSE; - if (windowClassOf(msg->hwnd, areaClass, NULL) != 0) - return FALSE; // nope - - handled = 0; - switch (msg->message) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - handled = SendMessageW(msg->hwnd, msgAreaKeyDown, msg->wParam, msg->lParam); - break; - case WM_KEYUP: - case WM_SYSKEYUP: - handled = SendMessageW(msg->hwnd, msgAreaKeyUp, msg->wParam, msg->lParam); - break; - // otherwise handled remains 0, as we didn't handle this - } - return (BOOL) handled; -} diff --git a/src/libui_sdl/libui/windows/areascroll.cpp b/src/libui_sdl/libui/windows/areascroll.cpp deleted file mode 100644 index f18d0ad8..00000000 --- a/src/libui_sdl/libui/windows/areascroll.cpp +++ /dev/null @@ -1,247 +0,0 @@ -// 8 september 2015 -#include "uipriv_windows.hpp" -#include "area.hpp" - -// TODO -// - move from pixels to points somehow -// - add a function to offset points and rects by scrolling amounts; call it from doPaint() in areadraw.c -// - recalculate scrolling after: -// - creation? -// - resize? -// - recreating the render target? (after moving to points) -// - error if these are called without scrollbars? - -struct scrollParams { - int *pos; - int pagesize; - int length; - int *wheelCarry; - UINT wheelSPIAction; -}; - -static void scrollto(uiArea *a, int which, struct scrollParams *p, int pos) -{ - SCROLLINFO si; - - // note that the pos < 0 check is /after/ the p->length - p->pagesize check - // it used to be /before/; this was actually a bug in Raymond Chen's original algorithm: if there are fewer than a page's worth of items, p->length - p->pagesize will be negative and our content draw at the bottom of the window - // this SHOULD have the same effect with that bug fixed and no others introduced... (thanks to devin on irc.badnik.net for confirming this logic) - if (pos > p->length - p->pagesize) - pos = p->length - p->pagesize; - if (pos < 0) - pos = 0; - - // Direct2D doesn't have a method for scrolling the existing contents of a render target. - // We'll have to just invalidate everything and hope for the best. - invalidateRect(a->hwnd, NULL, FALSE); - - *(p->pos) = pos; - - // now commit our new scrollbar setup... - ZeroMemory(&si, sizeof (SCROLLINFO)); - si.cbSize = sizeof (SCROLLINFO); - si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - si.nPage = p->pagesize; - si.nMin = 0; - si.nMax = p->length - 1; // endpoint inclusive - si.nPos = *(p->pos); - SetScrollInfo(a->hwnd, which, &si, TRUE); -} - -static void scrollby(uiArea *a, int which, struct scrollParams *p, int delta) -{ - scrollto(a, which, p, *(p->pos) + delta); -} - -static void scroll(uiArea *a, int which, struct scrollParams *p, WPARAM wParam, LPARAM lParam) -{ - int pos; - SCROLLINFO si; - - pos = *(p->pos); - switch (LOWORD(wParam)) { - case SB_LEFT: // also SB_TOP - pos = 0; - break; - case SB_RIGHT: // also SB_BOTTOM - pos = p->length - p->pagesize; - break; - case SB_LINELEFT: // also SB_LINEUP - pos--; - break; - case SB_LINERIGHT: // also SB_LINEDOWN - pos++; - break; - case SB_PAGELEFT: // also SB_PAGEUP - pos -= p->pagesize; - break; - case SB_PAGERIGHT: // also SB_PAGEDOWN - pos += p->pagesize; - break; - case SB_THUMBPOSITION: - ZeroMemory(&si, sizeof (SCROLLINFO)); - si.cbSize = sizeof (SCROLLINFO); - si.fMask = SIF_POS; - if (GetScrollInfo(a->hwnd, which, &si) == 0) - logLastError(L"error getting thumb position for area"); - pos = si.nPos; - break; - case SB_THUMBTRACK: - ZeroMemory(&si, sizeof (SCROLLINFO)); - si.cbSize = sizeof (SCROLLINFO); - si.fMask = SIF_TRACKPOS; - if (GetScrollInfo(a->hwnd, which, &si) == 0) - logLastError(L"error getting thumb track position for area"); - pos = si.nTrackPos; - break; - } - scrollto(a, which, p, pos); -} - -static void wheelscroll(uiArea *a, int which, struct scrollParams *p, WPARAM wParam, LPARAM lParam) -{ - int delta; - int lines; - UINT scrollAmount; - - delta = GET_WHEEL_DELTA_WPARAM(wParam); - if (SystemParametersInfoW(p->wheelSPIAction, 0, &scrollAmount, 0) == 0) - // TODO use scrollAmount == 3 (for both v and h) instead? - logLastError(L"error getting area wheel scroll amount"); - if (scrollAmount == WHEEL_PAGESCROLL) - scrollAmount = p->pagesize; - if (scrollAmount == 0) // no mouse wheel scrolling (or t->pagesize == 0) - return; - // the rest of this is basically http://blogs.msdn.com/b/oldnewthing/archive/2003/08/07/54615.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/08/11/54624.aspx - // see those pages for information on subtleties - delta += *(p->wheelCarry); - lines = delta * ((int) scrollAmount) / WHEEL_DELTA; - *(p->wheelCarry) = delta - lines * WHEEL_DELTA / ((int) scrollAmount); - scrollby(a, which, p, -lines); -} - -static void hscrollParams(uiArea *a, struct scrollParams *p) -{ - RECT r; - - ZeroMemory(p, sizeof (struct scrollParams)); - p->pos = &(a->hscrollpos); - // TODO get rid of these and replace with points - uiWindowsEnsureGetClientRect(a->hwnd, &r); - p->pagesize = r.right - r.left; - p->length = a->scrollWidth; - p->wheelCarry = &(a->hwheelCarry); - p->wheelSPIAction = SPI_GETWHEELSCROLLCHARS; -} - -static void hscrollto(uiArea *a, int pos) -{ - struct scrollParams p; - - hscrollParams(a, &p); - scrollto(a, SB_HORZ, &p, pos); -} - -static void hscrollby(uiArea *a, int delta) -{ - struct scrollParams p; - - hscrollParams(a, &p); - scrollby(a, SB_HORZ, &p, delta); -} - -static void hscroll(uiArea *a, WPARAM wParam, LPARAM lParam) -{ - struct scrollParams p; - - hscrollParams(a, &p); - scroll(a, SB_HORZ, &p, wParam, lParam); -} - -static void hwheelscroll(uiArea *a, WPARAM wParam, LPARAM lParam) -{ - struct scrollParams p; - - hscrollParams(a, &p); - wheelscroll(a, SB_HORZ, &p, wParam, lParam); -} - -static void vscrollParams(uiArea *a, struct scrollParams *p) -{ - RECT r; - - ZeroMemory(p, sizeof (struct scrollParams)); - p->pos = &(a->vscrollpos); - uiWindowsEnsureGetClientRect(a->hwnd, &r); - p->pagesize = r.bottom - r.top; - p->length = a->scrollHeight; - p->wheelCarry = &(a->vwheelCarry); - p->wheelSPIAction = SPI_GETWHEELSCROLLLINES; -} - -static void vscrollto(uiArea *a, int pos) -{ - struct scrollParams p; - - vscrollParams(a, &p); - scrollto(a, SB_VERT, &p, pos); -} - -static void vscrollby(uiArea *a, int delta) -{ - struct scrollParams p; - - vscrollParams(a, &p); - scrollby(a, SB_VERT, &p, delta); -} - -static void vscroll(uiArea *a, WPARAM wParam, LPARAM lParam) -{ - struct scrollParams p; - - vscrollParams(a, &p); - scroll(a, SB_VERT, &p, wParam, lParam); -} - -static void vwheelscroll(uiArea *a, WPARAM wParam, LPARAM lParam) -{ - struct scrollParams p; - - vscrollParams(a, &p); - wheelscroll(a, SB_VERT, &p, wParam, lParam); -} - -BOOL areaDoScroll(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - switch (uMsg) { - case WM_HSCROLL: - hscroll(a, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_MOUSEHWHEEL: - hwheelscroll(a, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_VSCROLL: - vscroll(a, wParam, lParam); - *lResult = 0; - return TRUE; - case WM_MOUSEWHEEL: - vwheelscroll(a, wParam, lParam); - *lResult = 0; - return TRUE; - } - return FALSE; -} - -void areaScrollOnResize(uiArea *a, RECT *client) -{ - areaUpdateScroll(a); -} - -void areaUpdateScroll(uiArea *a) -{ - // use a no-op scroll to simulate scrolling - hscrollby(a, 0); - vscrollby(a, 0); -} diff --git a/src/libui_sdl/libui/windows/areautil.cpp b/src/libui_sdl/libui/windows/areautil.cpp deleted file mode 100644 index ea13221c..00000000 --- a/src/libui_sdl/libui/windows/areautil.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// 18 december 2015 -#include "uipriv_windows.hpp" -#include "area.hpp" - -// TODO: make those int rather than double -void loadAreaSize(uiArea *a, double *width, double *height) -{ - D2D1_SIZE_F size; - - if (a->width != -1) - { - *width = (double)a->width; - *height = (double)a->height; - return; - } - - *width = 0; - *height = 0; - if (!a->scrolling) { - /*if (rt == NULL) - rt = a->rt; - size = realGetSize(rt); - *width = size.width; - *height = size.height; - dipToPixels(a, width, height);*/ - RECT rect; - GetWindowRect(a->hwnd, &rect); - *width = (double)(rect.right - rect.left); - *height = (double)(rect.bottom - rect.top); - } - - a->width = (int)*width; - a->height = (int)*height; -} - -void pixelsToDIP(uiArea *a, double *x, double *y) -{ - FLOAT dpix, dpiy; - - a->rt->GetDpi(&dpix, &dpiy); - // see https://msdn.microsoft.com/en-us/library/windows/desktop/dd756649%28v=vs.85%29.aspx (and others; search "direct2d mouse") - *x = (*x * 96) / dpix; - *y = (*y * 96) / dpiy; -} - -void dipToPixels(uiArea *a, double *x, double *y) -{ - FLOAT dpix, dpiy; - - a->rt->GetDpi(&dpix, &dpiy); - *x = (*x * dpix) / 96; - *y = (*y * dpiy) / 96; -} diff --git a/src/libui_sdl/libui/windows/box.cpp b/src/libui_sdl/libui/windows/box.cpp deleted file mode 100644 index 5ed84476..00000000 --- a/src/libui_sdl/libui/windows/box.cpp +++ /dev/null @@ -1,324 +0,0 @@ -// 7 april 2015 -#include "uipriv_windows.hpp" - -struct boxChild { - uiControl *c; - int stretchy; - int width; - int height; -}; - -struct uiBox { - uiWindowsControl c; - HWND hwnd; - std::vector *controls; - int vertical; - int padded; -}; - -static void boxPadding(uiBox *b, int *xpadding, int *ypadding) -{ - uiWindowsSizing sizing; - - *xpadding = 0; - *ypadding = 0; - if (b->padded) { - uiWindowsGetSizing(b->hwnd, &sizing); - uiWindowsSizingStandardPadding(&sizing, xpadding, ypadding); - } -} - -static void boxRelayout(uiBox *b) -{ - RECT r; - int x, y, width, height; - int xpadding, ypadding; - int nStretchy; - int stretchywid, stretchyht; - int i; - int minimumWidth, minimumHeight; - int nVisible; - - if (b->controls->size() == 0) - return; - - uiWindowsEnsureGetClientRect(b->hwnd, &r); - x = r.left; - y = r.top; - width = r.right - r.left; - height = r.bottom - r.top; - - // -1) get this Box's padding - boxPadding(b, &xpadding, &ypadding); - - // 1) get width and height of non-stretchy controls - // this will tell us how much space will be left for stretchy controls - stretchywid = width; - stretchyht = height; - nStretchy = 0; - nVisible = 0; - for (struct boxChild &bc : *(b->controls)) { - if (!uiControlVisible(bc.c)) - continue; - nVisible++; - if (bc.stretchy) { - nStretchy++; - continue; - } - uiWindowsControlMinimumSize(uiWindowsControl(bc.c), &minimumWidth, &minimumHeight); - if (b->vertical) { // all controls have same width - bc.width = width; - bc.height = minimumHeight; - stretchyht -= minimumHeight; - } else { // all controls have same height - bc.width = minimumWidth; - bc.height = height; - stretchywid -= minimumWidth; - } - } - if (nVisible == 0) // nothing to do - return; - - // 2) now inset the available rect by the needed padding - if (b->vertical) { - height -= (nVisible - 1) * ypadding; - stretchyht -= (nVisible - 1) * ypadding; - } else { - width -= (nVisible - 1) * xpadding; - stretchywid -= (nVisible - 1) * xpadding; - } - - // 3) now get the size of stretchy controls - if (nStretchy != 0) { - if (b->vertical) - stretchyht /= nStretchy; - else - stretchywid /= nStretchy; - for (struct boxChild &bc : *(b->controls)) { - if (!uiControlVisible(bc.c)) - continue; - if (bc.stretchy) { - bc.width = stretchywid; - bc.height = stretchyht; - } - } - } - - // 4) now we can position controls - // first, make relative to the top-left corner of the container - x = 0; - y = 0; - for (const struct boxChild &bc : *(b->controls)) { - if (!uiControlVisible(bc.c)) - continue; - uiWindowsEnsureMoveWindowDuringResize((HWND) uiControlHandle(bc.c), x, y, bc.width, bc.height); - if (b->vertical) - y += bc.height + ypadding; - else - x += bc.width + xpadding; - } -} - -static void uiBoxDestroy(uiControl *c) -{ - uiBox *b = uiBox(c); - - for (const struct boxChild &bc : *(b->controls)) { - uiControlSetParent(bc.c, NULL); - uiControlDestroy(bc.c); - } - delete b->controls; - uiWindowsEnsureDestroyWindow(b->hwnd); - uiFreeControl(uiControl(b)); -} - -uiWindowsControlDefaultHandle(uiBox) -uiWindowsControlDefaultParent(uiBox) -uiWindowsControlDefaultSetParent(uiBox) -uiWindowsControlDefaultToplevel(uiBox) -uiWindowsControlDefaultVisible(uiBox) -uiWindowsControlDefaultShow(uiBox) -uiWindowsControlDefaultHide(uiBox) -uiWindowsControlDefaultEnabled(uiBox) -uiWindowsControlDefaultEnable(uiBox) -uiWindowsControlDefaultDisable(uiBox) -uiWindowsControlDefaultSetFocus(uiBox) - -static void uiBoxSyncEnableState(uiWindowsControl *c, int enabled) -{ - uiBox *b = uiBox(c); - - if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(b), enabled)) - return; - for (const struct boxChild &bc : *(b->controls)) - uiWindowsControlSyncEnableState(uiWindowsControl(bc.c), enabled); -} - -uiWindowsControlDefaultSetParentHWND(uiBox) - -static void uiBoxMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiBox *b = uiBox(c); - int xpadding, ypadding; - int nStretchy; - // these two contain the largest minimum width and height of all stretchy controls in the box - // all stretchy controls will use this value to determine the final minimum size - int maxStretchyWidth, maxStretchyHeight; - int minimumWidth, minimumHeight; - int nVisible; - - *width = 0; - *height = 0; - if (b->controls->size() == 0) - return; - - // 0) get this Box's padding - boxPadding(b, &xpadding, &ypadding); - - // 1) add in the size of non-stretchy controls and get (but not add in) the largest widths and heights of stretchy controls - // we still add in like direction of stretchy controls - nStretchy = 0; - maxStretchyWidth = 0; - maxStretchyHeight = 0; - nVisible = 0; - for (const struct boxChild &bc : *(b->controls)) { - if (!uiControlVisible(bc.c)) - continue; - nVisible++; - uiWindowsControlMinimumSize(uiWindowsControl(bc.c), &minimumWidth, &minimumHeight); - if (bc.stretchy) { - nStretchy++; - if (maxStretchyWidth < minimumWidth) - maxStretchyWidth = minimumWidth; - if (maxStretchyHeight < minimumHeight) - maxStretchyHeight = minimumHeight; - } - if (b->vertical) { - if (*width < minimumWidth) - *width = minimumWidth; - if (!bc.stretchy) - *height += minimumHeight; - } else { - if (!bc.stretchy) - *width += minimumWidth; - if (*height < minimumHeight) - *height = minimumHeight; - } - } - if (nVisible == 0) // just return 0x0 - return; - - // 2) now outset the desired rect with the needed padding - if (b->vertical) - *height += (nVisible - 1) * ypadding; - else - *width += (nVisible - 1) * xpadding; - - // 3) and now we can add in stretchy controls - if (b->vertical) - *height += nStretchy * maxStretchyHeight; - else - *width += nStretchy * maxStretchyWidth; -} - -static void uiBoxMinimumSizeChanged(uiWindowsControl *c) -{ - uiBox *b = uiBox(c); - - if (uiWindowsControlTooSmall(uiWindowsControl(b))) { - uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(b)); - return; - } - boxRelayout(b); -} - -static void uiBoxSetMinSize(uiControl *c, int w, int h) -{ - // checkme - uiBoxMinimumSizeChanged(uiWindowsControl(c)); -} - -uiWindowsControlDefaultLayoutRect(uiBox) -uiWindowsControlDefaultAssignControlIDZOrder(uiBox) - -static void uiBoxChildVisibilityChanged(uiWindowsControl *c) -{ - // TODO eliminate the redundancy - uiWindowsControlMinimumSizeChanged(c); -} - -static void boxArrangeChildren(uiBox *b) -{ - LONG_PTR controlID; - HWND insertAfter; - - controlID = 100; - insertAfter = NULL; - for (const struct boxChild &bc : *(b->controls)) - uiWindowsControlAssignControlIDZOrder(uiWindowsControl(bc.c), &controlID, &insertAfter); -} - -void uiBoxAppend(uiBox *b, uiControl *c, int stretchy) -{ - struct boxChild bc; - - bc.c = c; - bc.stretchy = stretchy; - uiControlSetParent(bc.c, uiControl(b)); - uiWindowsControlSetParentHWND(uiWindowsControl(bc.c), b->hwnd); - b->controls->push_back(bc); - boxArrangeChildren(b); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(b)); -} - -void uiBoxDelete(uiBox *b, int index) -{ - uiControl *c; - - c = (*(b->controls))[index].c; - uiControlSetParent(c, NULL); - uiWindowsControlSetParentHWND(uiWindowsControl(c), NULL); - b->controls->erase(b->controls->begin() + index); - boxArrangeChildren(b); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(b)); -} - -int uiBoxPadded(uiBox *b) -{ - return b->padded; -} - -void uiBoxSetPadded(uiBox *b, int padded) -{ - b->padded = padded; - uiWindowsControlMinimumSizeChanged(uiWindowsControl(b)); -} - -static void onResize(uiWindowsControl *c) -{ - boxRelayout(uiBox(c)); -} - -static uiBox *finishNewBox(int vertical) -{ - uiBox *b; - - uiWindowsNewControl(uiBox, b); - - b->hwnd = uiWindowsMakeContainer(uiWindowsControl(b), onResize); - - b->vertical = vertical; - b->controls = new std::vector; - - return b; -} - -uiBox *uiNewHorizontalBox(void) -{ - return finishNewBox(0); -} - -uiBox *uiNewVerticalBox(void) -{ - return finishNewBox(1); -} diff --git a/src/libui_sdl/libui/windows/button.cpp b/src/libui_sdl/libui/windows/button.cpp deleted file mode 100644 index aa34bfc5..00000000 --- a/src/libui_sdl/libui/windows/button.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// 7 april 2015 -#include "uipriv_windows.hpp" - -struct uiButton { - uiWindowsControl c; - HWND hwnd; - void (*onClicked)(uiButton *, void *); - void *onClickedData; - - SIZE idealSize; - int idealSizeCached; -}; - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiButton *b = uiButton(c); - - if (code != BN_CLICKED) - return FALSE; - (*(b->onClicked))(b, b->onClickedData); - *lResult = 0; - return TRUE; -} - -static void uiButtonDestroy(uiControl *c) -{ - uiButton *b = uiButton(c); - - uiWindowsUnregisterWM_COMMANDHandler(b->hwnd); - uiWindowsEnsureDestroyWindow(b->hwnd); - uiFreeControl(uiControl(b)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiButton) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define buttonHeight 14 -#define buttonMinWidth 64 - -static void uiButtonMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiButton *b = uiButton(c); - SIZE size; - uiWindowsSizing sizing; - int y; - - if (b->idealSizeCached) - { - *width = b->idealSize.cx; - *height = b->idealSize.cy; - return; - } - - // try the comctl32 version 6 way - size.cx = 0; // explicitly ask for ideal size - size.cy = 0; - if (SendMessageW(b->hwnd, BCM_GETIDEALSIZE, 0, (LPARAM) (&size)) != FALSE) { - *width = size.cx; - if (*width < buttonMinWidth) *width = buttonMinWidth; - *height = size.cy; - b->idealSize.cx = *width; - b->idealSize.cy = *height; - b->idealSizeCached = true; - return; - } - - // that didn't work; fall back to using Microsoft's metrics - // Microsoft says to use a fixed width for all buttons; this isn't good enough - // use the text width instead, with some edge padding - *width = uiWindowsWindowTextWidth(b->hwnd) + (2 * GetSystemMetrics(SM_CXEDGE)); - if (*width < buttonMinWidth) *width = buttonMinWidth; - y = buttonHeight; - uiWindowsGetSizing(b->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y); - *height = y; - b->idealSize.cx = *width; - b->idealSize.cy = *height; - b->idealSizeCached = true; -} - -static void defaultOnClicked(uiButton *b, void *data) -{ - // do nothing -} - -char *uiButtonText(uiButton *b) -{ - return uiWindowsWindowText(b->hwnd); -} - -void uiButtonSetText(uiButton *b, const char *text) -{ - uiWindowsSetWindowText(b->hwnd, text); - b->idealSizeCached = 0; - // changing the text might necessitate a change in the button's size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(b)); -} - -void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *, void *), void *data) -{ - b->onClicked = f; - b->onClickedData = data; -} - -uiButton *uiNewButton(const char *text) -{ - uiButton *b; - WCHAR *wtext; - - uiWindowsNewControl(uiButton, b); - - wtext = toUTF16(text); - b->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"button", wtext, - BS_PUSHBUTTON | WS_TABSTOP, - hInstance, NULL, - TRUE); - uiFree(wtext); - - uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b)); - uiButtonOnClicked(b, defaultOnClicked, NULL); - - b->idealSizeCached = 0; - - return b; -} diff --git a/src/libui_sdl/libui/windows/checkbox.cpp b/src/libui_sdl/libui/windows/checkbox.cpp deleted file mode 100644 index be425c00..00000000 --- a/src/libui_sdl/libui/windows/checkbox.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// 7 april 2015 -#include "uipriv_windows.hpp" - -struct uiCheckbox { - uiWindowsControl c; - HWND hwnd; - void (*onToggled)(uiCheckbox *, void *); - void *onToggledData; -}; - -static BOOL onWM_COMMAND(uiControl *cc, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiCheckbox *c = uiCheckbox(cc); - WPARAM check; - - if (code != BN_CLICKED) - return FALSE; - - // we didn't use BS_AUTOCHECKBOX (http://blogs.msdn.com/b/oldnewthing/archive/2014/05/22/10527522.aspx) so we have to manage the check state ourselves - check = BST_CHECKED; - if (SendMessage(c->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED) - check = BST_UNCHECKED; - SendMessage(c->hwnd, BM_SETCHECK, check, 0); - - (*(c->onToggled))(c, c->onToggledData); - *lResult = 0; - return TRUE; -} - -static void uiCheckboxDestroy(uiControl *cc) -{ - uiCheckbox *c = uiCheckbox(cc); - - uiWindowsUnregisterWM_COMMANDHandler(c->hwnd); - uiWindowsEnsureDestroyWindow(c->hwnd); - uiFreeControl(uiControl(c)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiCheckbox) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define checkboxHeight 10 -// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx -#define checkboxXFromLeftOfBoxToLeftOfLabel 12 - -static void uiCheckboxMinimumSize(uiWindowsControl *cc, int *width, int *height) -{ - uiCheckbox *c = uiCheckbox(cc); - uiWindowsSizing sizing; - int x, y; - - x = checkboxXFromLeftOfBoxToLeftOfLabel; - y = checkboxHeight; - uiWindowsGetSizing(c->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x + uiWindowsWindowTextWidth(c->hwnd); - *height = y; -} - -static void defaultOnToggled(uiCheckbox *c, void *data) -{ - // do nothing -} - -char *uiCheckboxText(uiCheckbox *c) -{ - return uiWindowsWindowText(c->hwnd); -} - -void uiCheckboxSetText(uiCheckbox *c, const char *text) -{ - uiWindowsSetWindowText(c->hwnd, text); - // changing the text might necessitate a change in the checkbox's size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(c)); -} - -void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *, void *), void *data) -{ - c->onToggled = f; - c->onToggledData = data; -} - -int uiCheckboxChecked(uiCheckbox *c) -{ - return SendMessage(c->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED; -} - -void uiCheckboxSetChecked(uiCheckbox *c, int checked) -{ - WPARAM check; - - check = BST_CHECKED; - if (!checked) - check = BST_UNCHECKED; - SendMessage(c->hwnd, BM_SETCHECK, check, 0); -} - -uiCheckbox *uiNewCheckbox(const char *text) -{ - uiCheckbox *c; - WCHAR *wtext; - - uiWindowsNewControl(uiCheckbox, c); - - wtext = toUTF16(text); - c->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"button", wtext, - BS_CHECKBOX | WS_TABSTOP, - hInstance, NULL, - TRUE); - uiFree(wtext); - - uiWindowsRegisterWM_COMMANDHandler(c->hwnd, onWM_COMMAND, uiControl(c)); - uiCheckboxOnToggled(c, defaultOnToggled, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/windows/colorbutton.cpp b/src/libui_sdl/libui/windows/colorbutton.cpp deleted file mode 100644 index c1ba6954..00000000 --- a/src/libui_sdl/libui/windows/colorbutton.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// 16 may 2016 -#include "uipriv_windows.hpp" - -struct uiColorButton { - uiWindowsControl c; - HWND hwnd; - double r; - double g; - double b; - double a; - void (*onChanged)(uiColorButton *, void *); - void *onChangedData; -}; - -static void uiColorButtonDestroy(uiControl *c) -{ - uiColorButton *b = uiColorButton(c); - - uiWindowsUnregisterWM_COMMANDHandler(b->hwnd); - uiWindowsUnregisterWM_NOTIFYHandler(b->hwnd); - uiWindowsEnsureDestroyWindow(b->hwnd); - uiFreeControl(uiControl(b)); -} - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiColorButton *b = uiColorButton(c); - HWND parent; - struct colorDialogRGBA rgba; - - if (code != BN_CLICKED) - return FALSE; - - parent = parentToplevel(b->hwnd); - rgba.r = b->r; - rgba.g = b->g; - rgba.b = b->b; - rgba.a = b->a; - if (showColorDialog(parent, &rgba)) { - b->r = rgba.r; - b->g = rgba.g; - b->b = rgba.b; - b->a = rgba.a; - invalidateRect(b->hwnd, NULL, TRUE); - (*(b->onChanged))(b, b->onChangedData); - } - - *lResult = 0; - return TRUE; -} - -static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult) -{ - uiColorButton *b = uiColorButton(c); - NMCUSTOMDRAW *nm = (NMCUSTOMDRAW *) nmhdr; - RECT client; - ID2D1DCRenderTarget *rt; - D2D1_RECT_F r; - D2D1_COLOR_F color; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1SolidColorBrush *brush; - uiWindowsSizing sizing; - int x, y; - HRESULT hr; - - if (nmhdr->code != NM_CUSTOMDRAW) - return FALSE; - // and allow the button to draw its background - if (nm->dwDrawStage != CDDS_PREPAINT) - return FALSE; - - uiWindowsEnsureGetClientRect(b->hwnd, &client); - rt = makeHDCRenderTarget(nm->hdc, &client); - rt->BeginDraw(); - - uiWindowsGetSizing(b->hwnd, &sizing); - x = 3; // should be enough - y = 3; - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - r.left = client.left + x; - r.top = client.top + y; - r.right = client.right - x; - r.bottom = client.bottom - y; - - color.r = b->r; - color.g = b->g; - color.b = b->b; - color.a = b->a; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateSolidColorBrush(&color, &bprop, &brush); - if (hr != S_OK) - logHRESULT(L"error creating brush for color button", hr); - rt->FillRectangle(&r, brush); - brush->Release(); - - hr = rt->EndDraw(NULL, NULL); - if (hr != S_OK) - logHRESULT(L"error drawing color on color button", hr); - rt->Release(); - - // skip default processing (don't draw text) - *lResult = CDRF_SKIPDEFAULT; - return TRUE; -} - -uiWindowsControlAllDefaultsExceptDestroy(uiColorButton) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define buttonHeight 14 - -// TODO check widths -static void uiColorButtonMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiColorButton *b = uiColorButton(c); - SIZE size; - uiWindowsSizing sizing; - int y; - - // try the comctl32 version 6 way - size.cx = 0; // explicitly ask for ideal size - size.cy = 0; - if (SendMessageW(b->hwnd, BCM_GETIDEALSIZE, 0, (LPARAM) (&size)) != FALSE) { - *width = size.cx; - *height = size.cy; - return; - } - - // that didn't work; fall back to using Microsoft's metrics - // Microsoft says to use a fixed width for all buttons; this isn't good enough - // use the text width instead, with some edge padding - *width = uiWindowsWindowTextWidth(b->hwnd) + (2 * GetSystemMetrics(SM_CXEDGE)); - y = buttonHeight; - uiWindowsGetSizing(b->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y); - *height = y; -} - -static void defaultOnChanged(uiColorButton *b, void *data) -{ - // do nothing -} - -void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a) -{ - *r = b->r; - *g = b->g; - *bl = b->b; - *a = b->a; -} - -void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a) -{ - b->r = r; - b->g = g; - b->b = bl; - b->a = a; - invalidateRect(b->hwnd, NULL, TRUE); -} - -void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data) -{ - b->onChanged = f; - b->onChangedData = data; -} - -uiColorButton *uiNewColorButton(void) -{ - uiColorButton *b; - - uiWindowsNewControl(uiColorButton, b); - - // initial color is black - b->r = 0.0; - b->g = 0.0; - b->b = 0.0; - b->a = 1.0; - - b->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"button", L" ", // TODO; can't use "" TODO - BS_PUSHBUTTON | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b)); - uiWindowsRegisterWM_NOTIFYHandler(b->hwnd, onWM_NOTIFY, uiControl(b)); - uiColorButtonOnChanged(b, defaultOnChanged, NULL); - - return b; -} diff --git a/src/libui_sdl/libui/windows/colordialog.cpp b/src/libui_sdl/libui/windows/colordialog.cpp deleted file mode 100644 index 86d046da..00000000 --- a/src/libui_sdl/libui/windows/colordialog.cpp +++ /dev/null @@ -1,1255 +0,0 @@ -// 16 may 2016 -#include "uipriv_windows.hpp" - -// TODO should the d2dscratch programs capture mouse? - -struct colorDialog { - HWND hwnd; - - HWND svChooser; - HWND hSlider; - HWND preview; - HWND opacitySlider; - HWND editH; - HWND editS; - HWND editV; - HWND editRDouble, editRInt; - HWND editGDouble, editGInt; - HWND editBDouble, editBInt; - HWND editADouble, editAInt; - HWND editHex; - - double h; - double s; - double v; - double a; - struct colorDialogRGBA *out; - - BOOL updating; -}; - -// both of these are from the wikipedia page on HSV -// TODO what to do about negative h? -static void rgb2HSV(double r, double g, double b, double *h, double *s, double *v) -{ - double M, m; - int whichmax; - double c; - - M = r; - whichmax = 0; - if (M < g) { - M = g; - whichmax = 1; - } - if (M < b) { - M = b; - whichmax = 2; - } - m = r; - if (m > g) - m = g; - if (m > b) - m = b; - c = M - m; - - if (c == 0) - *h = 0; - else { - switch (whichmax) { - case 0: - *h = ((g - b) / c); - *h = fmod(*h, 6); - break; - case 1: - *h = ((b - r) / c) + 2; - break; - case 2: - *h = ((r - g) / c) + 4; - break; - } - *h /= 6; // put in range [0,1) - } - - *v = M; - - if (c == 0) - *s = 0; - else - *s = c / *v; -} - -// TODO negative R values? -static void hsv2RGB(double h, double s, double v, double *r, double *g, double *b) -{ - double c; - double hPrime; - int h60; - double x; - double m; - - c = v * s; - hPrime = h * 6; - h60 = (int) hPrime; // equivalent to splitting into 60° chunks - x = c * (1.0 - fabs(fmod(hPrime, 2) - 1.0)); - m = v - c; - switch (h60) { - case 0: - *r = c + m; - *g = x + m; - *b = m; - return; - case 1: - *r = x + m; - *g = c + m; - *b = m; - return; - case 2: - *r = m; - *g = c + m; - *b = x + m; - return; - case 3: - *r = m; - *g = x + m; - *b = c + m; - return; - case 4: - *r = x + m; - *g = m; - *b = c + m; - return; - case 5: - *r = c + m; - *g = m; - *b = x + m; - return; - } - // TODO -} - -#define hexd L"0123456789ABCDEF" - -static void rgba2Hex(uint8_t r, uint8_t g, uint8_t b, uint8_t a, WCHAR *buf) -{ - buf[0] = L'#'; - buf[1] = hexd[(a >> 4) & 0xF]; - buf[2] = hexd[a & 0xF]; - buf[3] = hexd[(r >> 4) & 0xF]; - buf[4] = hexd[r & 0xF]; - buf[5] = hexd[(g >> 4) & 0xF]; - buf[6] = hexd[g & 0xF]; - buf[7] = hexd[(b >> 4) & 0xF]; - buf[8] = hexd[b & 0xF]; - buf[9] = L'\0'; -} - -static int convHexDigit(WCHAR c) -{ - if (c >= L'0' && c <= L'9') - return c - L'0'; - if (c >= L'A' && c <= L'F') - return c - L'A' + 0xA; - if (c >= L'a' && c <= L'f') - return c - L'a' + 0xA; - return -1; -} - -// TODO allow #NNN shorthand -static BOOL hex2RGBA(WCHAR *buf, double *r, double *g, double *b, double *a) -{ - uint8_t component; - int i; - - if (*buf == L'#') - buf++; - - component = 0; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i) << 4; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i); - *a = ((double) component) / 255; - - component = 0; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i) << 4; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i); - *r = ((double) component) / 255; - - component = 0; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i) << 4; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i); - *g = ((double) component) / 255; - - if (*buf == L'\0') { // #NNNNNN syntax - *b = *g; - *g = *r; - *r = *a; - *a = 1; - return TRUE; - } - - component = 0; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i) << 4; - i = convHexDigit(*buf++); - if (i < 0) - return FALSE; - component |= ((uint8_t) i); - *b = ((double) component) / 255; - - return *buf == L'\0'; -} - -static void updateDouble(HWND hwnd, double d, HWND whichChanged) -{ - WCHAR *str; - - if (whichChanged == hwnd) - return; - str = ftoutf16(d); - setWindowText(hwnd, str); - uiFree(str); -} - -static void updateDialog(struct colorDialog *c, HWND whichChanged) -{ - double r, g, b; - uint8_t rb, gb, bb, ab; - WCHAR *str; - WCHAR hexbuf[16]; // more than enough - - c->updating = TRUE; - - updateDouble(c->editH, c->h, whichChanged); - updateDouble(c->editS, c->s, whichChanged); - updateDouble(c->editV, c->v, whichChanged); - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - - updateDouble(c->editRDouble, r, whichChanged); - updateDouble(c->editGDouble, g, whichChanged); - updateDouble(c->editBDouble, b, whichChanged); - updateDouble(c->editADouble, c->a, whichChanged); - - rb = (uint8_t) (r * 255); - gb = (uint8_t) (g * 255); - bb = (uint8_t) (b * 255); - ab = (uint8_t) (c->a * 255); - - if (whichChanged != c->editRInt) { - str = itoutf16(rb); - setWindowText(c->editRInt, str); - uiFree(str); - } - if (whichChanged != c->editGInt) { - str = itoutf16(gb); - setWindowText(c->editGInt, str); - uiFree(str); - } - if (whichChanged != c->editBInt) { - str = itoutf16(bb); - setWindowText(c->editBInt, str); - uiFree(str); - } - if (whichChanged != c->editAInt) { - str = itoutf16(ab); - setWindowText(c->editAInt, str); - uiFree(str); - } - - if (whichChanged != c->editHex) { - rgba2Hex(rb, gb, bb, ab, hexbuf); - setWindowText(c->editHex, hexbuf); - } - - // TODO TRUE? - invalidateRect(c->svChooser, NULL, TRUE); - invalidateRect(c->hSlider, NULL, TRUE); - invalidateRect(c->preview, NULL, TRUE); - invalidateRect(c->opacitySlider, NULL, TRUE); - - c->updating = FALSE; -} - -// this imitates http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx -static void drawGrid(ID2D1RenderTarget *rt, D2D1_RECT_F *fillRect) -{ - D2D1_SIZE_F size; - D2D1_PIXEL_FORMAT pformat; - ID2D1BitmapRenderTarget *brt; - D2D1_COLOR_F color; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1SolidColorBrush *brush; - D2D1_RECT_F rect; - ID2D1Bitmap *bitmap; - D2D1_BITMAP_BRUSH_PROPERTIES bbp; - ID2D1BitmapBrush *bb; - HRESULT hr; - - // mind the divisions; they represent the fact the original uses a viewport - size.width = 100 / 10; - size.height = 100 / 10; - // yay more ABI bugs - - pformat = rt->GetPixelFormat(); - - hr = rt->CreateCompatibleRenderTarget(&size, NULL, - &pformat, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, - &brt); - if (hr != S_OK) - logHRESULT(L"error creating render target for grid", hr); - - brt->BeginDraw(); - - color.r = 1.0; - color.g = 1.0; - color.b = 1.0; - color.a = 1.0; - brt->Clear(&color); - - color = D2D1::ColorF(D2D1::ColorF::LightGray, 1.0); - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = brt->CreateSolidColorBrush(&color, &bprop, &brush); - if (hr != S_OK) - logHRESULT(L"error creating brush for grid", hr); - rect.left = 0; - rect.top = 0; - rect.right = 50 / 10; - rect.bottom = 50 / 10; - brt->FillRectangle(&rect, brush); - rect.left = 50 / 10; - rect.top = 50 / 10; - rect.right = 100 / 10; - rect.bottom = 100 / 10; - brt->FillRectangle(&rect, brush); - brush->Release(); - - hr = brt->EndDraw(NULL, NULL); - if (hr != S_OK) - logHRESULT(L"error finalizing render target for grid", hr); - hr = brt->GetBitmap(&bitmap); - if (hr != S_OK) - logHRESULT(L"error getting bitmap for grid", hr); - brt->Release(); - - ZeroMemory(&bbp, sizeof (D2D1_BITMAP_BRUSH_PROPERTIES)); - bbp.extendModeX = D2D1_EXTEND_MODE_WRAP; - bbp.extendModeY = D2D1_EXTEND_MODE_WRAP; - bbp.interpolationMode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR; - hr = rt->CreateBitmapBrush(bitmap, &bbp, &bprop, &bb); - if (hr != S_OK) - logHRESULT(L"error creating bitmap brush for grid", hr); - rt->FillRectangle(fillRect, bb); - bb->Release(); - bitmap->Release(); -} - -// this interesting approach comes from http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx -static void drawSVChooser(struct colorDialog *c, ID2D1RenderTarget *rt) -{ - D2D1_SIZE_F size; - D2D1_RECT_F rect; - double rTop, gTop, bTop; - D2D1_GRADIENT_STOP stops[2]; - ID2D1GradientStopCollection *collection; - D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lprop; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1LinearGradientBrush *brush; - ID2D1LinearGradientBrush *opacity; - ID2D1Layer *layer; - D2D1_LAYER_PARAMETERS layerparams; - D2D1_ELLIPSE mparam; - D2D1_COLOR_F mcolor; - ID2D1SolidColorBrush *markerBrush; - HRESULT hr; - - size = realGetSize(rt); - rect.left = 0; - rect.top = 0; - rect.right = size.width; - rect.bottom = size.height; - - drawGrid(rt, &rect); - - // first, draw a vertical gradient from the current hue at max S/V to black - // the source example draws it upside down; let's do so too just to be safe - hsv2RGB(c->h, 1.0, 1.0, &rTop, &gTop, &bTop); - stops[0].position = 0; - stops[0].color.r = 0.0; - stops[0].color.g = 0.0; - stops[0].color.b = 0.0; - stops[0].color.a = 1.0; - stops[1].position = 1; - stops[1].color.r = rTop; - stops[1].color.g = gTop; - stops[1].color.b = bTop; - stops[1].color.a = 1.0; - hr = rt->CreateGradientStopCollection(stops, 2, - D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, - &collection); - if (hr != S_OK) - logHRESULT(L"error making gradient stop collection for first gradient in SV chooser", hr); - ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); - lprop.startPoint.x = size.width / 2; - lprop.startPoint.y = size.height; - lprop.endPoint.x = size.width / 2; - lprop.endPoint.y = 0; - // TODO decide what to do about the duplication of this - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = c->a; // note this part; we also use it below for the layer - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateLinearGradientBrush(&lprop, &bprop, - collection, &brush); - if (hr != S_OK) - logHRESULT(L"error making gradient brush for first gradient in SV chooser", hr); - rt->FillRectangle(&rect, brush); - brush->Release(); - collection->Release(); - - // second, create an opacity mask for the third step: a horizontal gradientthat goes from opaque to translucent - stops[0].position = 0; - stops[0].color.r = 0.0; - stops[0].color.g = 0.0; - stops[0].color.b = 0.0; - stops[0].color.a = 1.0; - stops[1].position = 1; - stops[1].color.r = 0.0; - stops[1].color.g = 0.0; - stops[1].color.b = 0.0; - stops[1].color.a = 0.0; - hr = rt->CreateGradientStopCollection(stops, 2, - D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, - &collection); - if (hr != S_OK) - logHRESULT(L"error making gradient stop collection for opacity mask gradient in SV chooser", hr); - ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); - lprop.startPoint.x = 0; - lprop.startPoint.y = size.height / 2; - lprop.endPoint.x = size.width; - lprop.endPoint.y = size.height / 2; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateLinearGradientBrush(&lprop, &bprop, - collection, &opacity); - if (hr != S_OK) - logHRESULT(L"error making gradient brush for opacity mask gradient in SV chooser", hr); - collection->Release(); - - // finally, make a vertical gradient from white at the top to black at the bottom (right side up this time) and with the previous opacity mask - stops[0].position = 0; - stops[0].color.r = 1.0; - stops[0].color.g = 1.0; - stops[0].color.b = 1.0; - stops[0].color.a = 1.0; - stops[1].position = 1; - stops[1].color.r = 0.0; - stops[1].color.g = 0.0; - stops[1].color.b = 0.0; - stops[1].color.a = 1.0; - hr = rt->CreateGradientStopCollection(stops, 2, - D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, - &collection); - if (hr != S_OK) - logHRESULT(L"error making gradient stop collection for second gradient in SV chooser", hr); - ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); - lprop.startPoint.x = size.width / 2; - lprop.startPoint.y = 0; - lprop.endPoint.x = size.width / 2; - lprop.endPoint.y = size.height; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateLinearGradientBrush(&lprop, &bprop, - collection, &brush); - if (hr != S_OK) - logHRESULT(L"error making gradient brush for second gradient in SV chooser", hr); - // oh but wait we can't use FillRectangle() with an opacity mask - // and we can't use FillGeometry() with both an opacity mask and a non-bitmap - // layers it is! - hr = rt->CreateLayer(&size, &layer); - if (hr != S_OK) - logHRESULT(L"error making layer for second gradient in SV chooser", hr); - ZeroMemory(&layerparams, sizeof (D2D1_LAYER_PARAMETERS)); - layerparams.contentBounds = rect; - // TODO make sure these are right - layerparams.geometricMask = NULL; - layerparams.maskAntialiasMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE; - layerparams.maskTransform._11 = 1; - layerparams.maskTransform._22 = 1; - layerparams.opacity = c->a; // here's the other use of c->a to note - layerparams.opacityBrush = opacity; - layerparams.layerOptions = D2D1_LAYER_OPTIONS_NONE; - rt->PushLayer(&layerparams, layer); - rt->FillRectangle(&rect, brush); - rt->PopLayer(); - layer->Release(); - brush->Release(); - collection->Release(); - opacity->Release(); - - // and now we just draw the marker - ZeroMemory(&mparam, sizeof (D2D1_ELLIPSE)); - mparam.point.x = c->s * size.width; - mparam.point.y = (1 - c->v) * size.height; - mparam.radiusX = 7; - mparam.radiusY = 7; - // TODO make the color contrast? - mcolor.r = 1.0; - mcolor.g = 1.0; - mcolor.b = 1.0; - mcolor.a = 1.0; - bprop.opacity = 1.0; // the marker should always be opaque - hr = rt->CreateSolidColorBrush(&mcolor, &bprop, &markerBrush); - if (hr != S_OK) - logHRESULT(L"error creating brush for SV chooser marker", hr); - rt->DrawEllipse(&mparam, markerBrush, 2, NULL); - markerBrush->Release(); -} - -static LRESULT CALLBACK svChooserSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - ID2D1RenderTarget *rt; - struct colorDialog *c; - D2D1_POINT_2F *pos; - D2D1_SIZE_F *size; - - c = (struct colorDialog *) dwRefData; - switch (uMsg) { - case msgD2DScratchPaint: - rt = (ID2D1RenderTarget *) lParam; - drawSVChooser(c, rt); - return 0; - case msgD2DScratchLButtonDown: - pos = (D2D1_POINT_2F *) wParam; - size = (D2D1_SIZE_F *) lParam; - c->s = pos->x / size->width; - c->v = 1 - (pos->y / size->height); - updateDialog(c, NULL); - return 0; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, svChooserSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing color dialog SV chooser subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -static void drawArrow(ID2D1RenderTarget *rt, D2D1_POINT_2F center, double hypot) -{ - double leg; - D2D1_RECT_F rect; - D2D1_MATRIX_3X2_F oldtf, rotate; - D2D1_COLOR_F color; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1SolidColorBrush *brush; - HRESULT hr; - - // to avoid needing a geometry, this will just be a rotated square - // compute the length of each side; the diagonal of the square is 2 * offset to gradient - // a^2 + a^2 = c^2 -> 2a^2 = c^2 - // a = sqrt(c^2/2) - hypot *= hypot; - hypot /= 2; - leg = sqrt(hypot); - rect.left = center.x - leg; - rect.top = center.y - leg; - rect.right = center.x + leg; - rect.bottom = center.y + leg; - - // now we need to rotate the render target 45° (either way works) about the center point - rt->GetTransform(&oldtf); - rotate = oldtf * D2D1::Matrix3x2F::Rotation(45, center); - rt->SetTransform(&rotate); - - // and draw - color.r = 0.0; - color.g = 0.0; - color.b = 0.0; - color.a = 1.0; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateSolidColorBrush(&color, &bprop, &brush); - if (hr != S_OK) - logHRESULT(L"error creating brush for arrow", hr); - rt->FillRectangle(&rect, brush); - brush->Release(); - - // clean up - rt->SetTransform(&oldtf); -} - -// the gradient stuff also comes from http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx -#define nStops (30) -#define degPerStop (360 / nStops) -#define stopIncr (1.0 / ((double) nStops)) - -static void drawHSlider(struct colorDialog *c, ID2D1RenderTarget *rt) -{ - D2D1_SIZE_F size; - D2D1_RECT_F rect; - D2D1_GRADIENT_STOP stops[nStops]; - double r, g, b; - int i; - double h; - ID2D1GradientStopCollection *collection; - D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lprop; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1LinearGradientBrush *brush; - double hypot; - D2D1_POINT_2F center; - HRESULT hr; - - size = realGetSize(rt); - rect.left = size.width / 6; // leftmost sixth for arrow - rect.top = 0; - rect.right = size.width; - rect.bottom = size.height; - - for (i = 0; i < nStops; i++) { - h = ((double) (i * degPerStop)) / 360.0; - if (i == (nStops - 1)) - h = 0; - hsv2RGB(h, 1.0, 1.0, &r, &g, &b); - stops[i].position = ((double) i) * stopIncr; - stops[i].color.r = r; - stops[i].color.g = g; - stops[i].color.b = b; - stops[i].color.a = 1.0; - } - // and pin the last one - stops[i - 1].position = 1.0; - - hr = rt->CreateGradientStopCollection(stops, nStops, - // note that in this case this gamma is explicitly specified by the original - D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, - &collection); - if (hr != S_OK) - logHRESULT(L"error creating stop collection for H slider gradient", hr); - ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); - lprop.startPoint.x = (rect.right - rect.left) / 2; - lprop.startPoint.y = 0; - lprop.endPoint.x = (rect.right - rect.left) / 2; - lprop.endPoint.y = size.height; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateLinearGradientBrush(&lprop, &bprop, - collection, &brush); - if (hr != S_OK) - logHRESULT(L"error creating gradient brush for H slider", hr); - rt->FillRectangle(&rect, brush); - brush->Release(); - collection->Release(); - - // now draw a black arrow - center.x = 0; - center.y = c->h * size.height; - hypot = rect.left; - drawArrow(rt, center, hypot); -} - -static LRESULT CALLBACK hSliderSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - ID2D1RenderTarget *rt; - struct colorDialog *c; - D2D1_POINT_2F *pos; - D2D1_SIZE_F *size; - - c = (struct colorDialog *) dwRefData; - switch (uMsg) { - case msgD2DScratchPaint: - rt = (ID2D1RenderTarget *) lParam; - drawHSlider(c, rt); - return 0; - case msgD2DScratchLButtonDown: - pos = (D2D1_POINT_2F *) wParam; - size = (D2D1_SIZE_F *) lParam; - c->h = pos->y / size->height; - updateDialog(c, NULL); - return 0; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, hSliderSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing color dialog H slider subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -static void drawPreview(struct colorDialog *c, ID2D1RenderTarget *rt) -{ - D2D1_SIZE_F size; - D2D1_RECT_F rect; - double r, g, b; - D2D1_COLOR_F color; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1SolidColorBrush *brush; - HRESULT hr; - - size = realGetSize(rt); - rect.left = 0; - rect.top = 0; - rect.right = size.width; - rect.bottom = size.height; - - drawGrid(rt, &rect); - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - color.r = r; - color.g = g; - color.b = b; - color.a = c->a; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateSolidColorBrush(&color, &bprop, &brush); - if (hr != S_OK) - logHRESULT(L"error creating brush for preview", hr); - rt->FillRectangle(&rect, brush); - brush->Release(); -} - -static LRESULT CALLBACK previewSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - ID2D1RenderTarget *rt; - struct colorDialog *c; - - c = (struct colorDialog *) dwRefData; - switch (uMsg) { - case msgD2DScratchPaint: - rt = (ID2D1RenderTarget *) lParam; - drawPreview(c, rt); - return 0; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, previewSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing color dialog previewer subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -// once again, this is based on the Microsoft sample above -static void drawOpacitySlider(struct colorDialog *c, ID2D1RenderTarget *rt) -{ - D2D1_SIZE_F size; - D2D1_RECT_F rect; - D2D1_GRADIENT_STOP stops[2]; - ID2D1GradientStopCollection *collection; - D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lprop; - D2D1_BRUSH_PROPERTIES bprop; - ID2D1LinearGradientBrush *brush; - double hypot; - D2D1_POINT_2F center; - HRESULT hr; - - size = realGetSize(rt); - rect.left = 0; - rect.top = 0; - rect.right = size.width; - rect.bottom = size.height * (5.0 / 6.0); // bottommost sixth for arrow - - drawGrid(rt, &rect); - - stops[0].position = 0.0; - stops[0].color.r = 0.0; - stops[0].color.g = 0.0; - stops[0].color.b = 0.0; - stops[0].color.a = 1.0; - stops[1].position = 1.0; - stops[1].color.r = 1.0; // this is the XAML color Transparent, as in the source - stops[1].color.g = 1.0; - stops[1].color.b = 1.0; - stops[1].color.a = 0.0; - hr = rt->CreateGradientStopCollection(stops, 2, - // note that in this case this gamma is explicitly specified by the original - D2D1_GAMMA_2_2, D2D1_EXTEND_MODE_CLAMP, - &collection); - if (hr != S_OK) - logHRESULT(L"error creating stop collection for opacity slider gradient", hr); - ZeroMemory(&lprop, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); - lprop.startPoint.x = 0; - lprop.startPoint.y = (rect.bottom - rect.top) / 2; - lprop.endPoint.x = size.width; - lprop.endPoint.y = (rect.bottom - rect.top) / 2; - ZeroMemory(&bprop, sizeof (D2D1_BRUSH_PROPERTIES)); - bprop.opacity = 1.0; - bprop.transform._11 = 1; - bprop.transform._22 = 1; - hr = rt->CreateLinearGradientBrush(&lprop, &bprop, - collection, &brush); - if (hr != S_OK) - logHRESULT(L"error creating gradient brush for opacity slider", hr); - rt->FillRectangle(&rect, brush); - brush->Release(); - collection->Release(); - - // now draw a black arrow - center.x = (1 - c->a) * size.width; - center.y = size.height; - hypot = size.height - rect.bottom; - drawArrow(rt, center, hypot); -} - -static LRESULT CALLBACK opacitySliderSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - ID2D1RenderTarget *rt; - struct colorDialog *c; - D2D1_POINT_2F *pos; - D2D1_SIZE_F *size; - - c = (struct colorDialog *) dwRefData; - switch (uMsg) { - case msgD2DScratchPaint: - rt = (ID2D1RenderTarget *) lParam; - drawOpacitySlider(c, rt); - return 0; - case msgD2DScratchLButtonDown: - pos = (D2D1_POINT_2F *) wParam; - size = (D2D1_SIZE_F *) lParam; - c->a = 1 - (pos->x / size->width); - updateDialog(c, NULL); - return 0; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, opacitySliderSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing color dialog opacity slider subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -// TODO extract into d2dscratch.cpp, use in font dialog -HWND replaceWithD2DScratch(HWND parent, int id, SUBCLASSPROC subproc, void *data) -{ - HWND replace; - RECT r; - - replace = getDlgItem(parent, id); - uiWindowsEnsureGetWindowRect(replace, &r); - mapWindowRect(NULL, parent, &r); - uiWindowsEnsureDestroyWindow(replace); - return newD2DScratch(parent, &r, (HMENU) id, subproc, (DWORD_PTR) data); - // TODO preserve Z-order -} - -// a few issues: -// - some controls are positioned wrong; see http://stackoverflow.com/questions/37263267/why-are-some-of-my-controls-positioned-slightly-off-in-a-dialog-template-in-a-re -// - labels are too low; need to adjust them by the font's internal leading -// fixupControlPositions() and the following helper routines fix that for us - -static LONG offsetTo(HWND a, HWND b) -{ - RECT ra, rb; - - uiWindowsEnsureGetWindowRect(a, &ra); - uiWindowsEnsureGetWindowRect(b, &rb); - return rb.top - ra.bottom; -} - -static void moveWindowsUp(struct colorDialog *c, LONG by, ...) -{ - va_list ap; - HWND cur; - RECT r; - - va_start(ap, by); - for (;;) { - cur = va_arg(ap, HWND); - if (cur == NULL) - break; - uiWindowsEnsureGetWindowRect(cur, &r); - mapWindowRect(NULL, c->hwnd, &r); - r.top -= by; - r.bottom -= by; - // TODO this isn't technically during a resize - uiWindowsEnsureMoveWindowDuringResize(cur, - r.left, r.top, - r.right - r.left, r.bottom - r.top); - } - va_end(ap); -} - -static void fixupControlPositions(struct colorDialog *c) -{ - HWND labelH; - HWND labelS; - HWND labelV; - HWND labelR; - HWND labelG; - HWND labelB; - HWND labelA; - HWND labelHex; - LONG offset; - uiWindowsSizing sizing; - - labelH = getDlgItem(c->hwnd, rcHLabel); - labelS = getDlgItem(c->hwnd, rcSLabel); - labelV = getDlgItem(c->hwnd, rcVLabel); - labelR = getDlgItem(c->hwnd, rcRLabel); - labelG = getDlgItem(c->hwnd, rcGLabel); - labelB = getDlgItem(c->hwnd, rcBLabel); - labelA = getDlgItem(c->hwnd, rcALabel); - labelHex = getDlgItem(c->hwnd, rcHexLabel); - - offset = offsetTo(c->editH, c->editS); - moveWindowsUp(c, offset, - labelS, c->editS, - labelG, c->editGDouble, c->editGInt, - NULL); - offset = offsetTo(c->editS, c->editV); - moveWindowsUp(c, offset, - labelV, c->editV, - labelB, c->editBDouble, c->editBInt, - NULL); - offset = offsetTo(c->editBDouble, c->editADouble); - moveWindowsUp(c, offset, - labelA, c->editADouble, c->editAInt, - NULL); - - getSizing(c->hwnd, &sizing, (HFONT) SendMessageW(labelH, WM_GETFONT, 0, 0)); - offset = sizing.InternalLeading; - moveWindowsUp(c, offset, - labelH, labelS, labelV, - labelR, labelG, labelB, labelA, - labelHex, - NULL); -} - -static struct colorDialog *beginColorDialog(HWND hwnd, LPARAM lParam) -{ - struct colorDialog *c; - - c = uiNew(struct colorDialog); - c->hwnd = hwnd; - c->out = (struct colorDialogRGBA *) lParam; - // load initial values now - rgb2HSV(c->out->r, c->out->g, c->out->b, &(c->h), &(c->s), &(c->v)); - c->a = c->out->a; - - // TODO set up d2dscratches - - // TODO prefix all these with rcColor instead of just rc - c->editH = getDlgItem(c->hwnd, rcH); - c->editS = getDlgItem(c->hwnd, rcS); - c->editV = getDlgItem(c->hwnd, rcV); - c->editRDouble = getDlgItem(c->hwnd, rcRDouble); - c->editRInt = getDlgItem(c->hwnd, rcRInt); - c->editGDouble = getDlgItem(c->hwnd, rcGDouble); - c->editGInt = getDlgItem(c->hwnd, rcGInt); - c->editBDouble = getDlgItem(c->hwnd, rcBDouble); - c->editBInt = getDlgItem(c->hwnd, rcBInt); - c->editADouble = getDlgItem(c->hwnd, rcADouble); - c->editAInt = getDlgItem(c->hwnd, rcAInt); - c->editHex = getDlgItem(c->hwnd, rcHex); - - c->svChooser = replaceWithD2DScratch(c->hwnd, rcColorSVChooser, svChooserSubProc, c); - c->hSlider = replaceWithD2DScratch(c->hwnd, rcColorHSlider, hSliderSubProc, c); - c->preview = replaceWithD2DScratch(c->hwnd, rcPreview, previewSubProc, c); - c->opacitySlider = replaceWithD2DScratch(c->hwnd, rcOpacitySlider, opacitySliderSubProc, c); - - fixupControlPositions(c); - - // and get the ball rolling - updateDialog(c, NULL); - return c; -} - -static void endColorDialog(struct colorDialog *c, INT_PTR code) -{ - if (EndDialog(c->hwnd, code) == 0) - logLastError(L"error ending color dialog"); - uiFree(c); -} - -// TODO make this void on the font dialog too -static void tryFinishDialog(struct colorDialog *c, WPARAM wParam) -{ - // cancelling - if (LOWORD(wParam) != IDOK) { - endColorDialog(c, 1); - return; - } - - // OK - hsv2RGB(c->h, c->s, c->v, &(c->out->r), &(c->out->g), &(c->out->b)); - c->out->a = c->a; - endColorDialog(c, 2); -} - -static double editDouble(HWND hwnd) -{ - WCHAR *s; - double d; - - s = windowText(hwnd); - d = _wtof(s); - uiFree(s); - return d; -} - -static void hChanged(struct colorDialog *c) -{ - double h; - - h = editDouble(c->editH); - if (h < 0 || h >= 1.0) // note the >= - return; - c->h = h; - updateDialog(c, c->editH); -} - -static void sChanged(struct colorDialog *c) -{ - double s; - - s = editDouble(c->editS); - if (s < 0 || s > 1) - return; - c->s = s; - updateDialog(c, c->editS); -} - -static void vChanged(struct colorDialog *c) -{ - double v; - - v = editDouble(c->editV); - if (v < 0 || v > 1) - return; - c->v = v; - updateDialog(c, c->editV); -} - -static void rDoubleChanged(struct colorDialog *c) -{ - double r, g, b; - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - r = editDouble(c->editRDouble); - if (r < 0 || r > 1) - return; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - updateDialog(c, c->editRDouble); -} - -static void gDoubleChanged(struct colorDialog *c) -{ - double r, g, b; - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - g = editDouble(c->editGDouble); - if (g < 0 || g > 1) - return; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - updateDialog(c, c->editGDouble); -} - -static void bDoubleChanged(struct colorDialog *c) -{ - double r, g, b; - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - b = editDouble(c->editBDouble); - if (b < 0 || b > 1) - return; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - updateDialog(c, c->editBDouble); -} - -static void aDoubleChanged(struct colorDialog *c) -{ - double a; - - a = editDouble(c->editADouble); - if (a < 0 || a > 1) - return; - c->a = a; - updateDialog(c, c->editADouble); -} - -static int editInt(HWND hwnd) -{ - WCHAR *s; - int i; - - s = windowText(hwnd); - i = _wtoi(s); - uiFree(s); - return i; -} - -static void rIntChanged(struct colorDialog *c) -{ - double r, g, b; - int i; - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - i = editInt(c->editRInt); - if (i < 0 || i > 255) - return; - r = ((double) i) / 255.0; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - updateDialog(c, c->editRInt); -} - -static void gIntChanged(struct colorDialog *c) -{ - double r, g, b; - int i; - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - i = editInt(c->editGInt); - if (i < 0 || i > 255) - return; - g = ((double) i) / 255.0; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - updateDialog(c, c->editGInt); -} - -static void bIntChanged(struct colorDialog *c) -{ - double r, g, b; - int i; - - hsv2RGB(c->h, c->s, c->v, &r, &g, &b); - i = editInt(c->editBInt); - if (i < 0 || i > 255) - return; - b = ((double) i) / 255.0; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - updateDialog(c, c->editBInt); -} - -static void aIntChanged(struct colorDialog *c) -{ - int a; - - a = editInt(c->editAInt); - if (a < 0 || a > 255) - return; - c->a = ((double) a) / 255; - updateDialog(c, c->editAInt); -} - -static void hexChanged(struct colorDialog *c) -{ - WCHAR *buf; - double r, g, b, a; - BOOL is; - - buf = windowText(c->editHex); - is = hex2RGBA(buf, &r, &g, &b, &a); - uiFree(buf); - if (!is) - return; - rgb2HSV(r, g, b, &(c->h), &(c->s), &(c->v)); - c->a = a; - updateDialog(c, c->editHex); -} - -// TODO change fontdialog to use this -// note that if we make this const, we get lots of weird compiler errors -static std::map changed = { - { rcH, hChanged }, - { rcS, sChanged }, - { rcV, vChanged }, - { rcRDouble, rDoubleChanged }, - { rcGDouble, gDoubleChanged }, - { rcBDouble, bDoubleChanged }, - { rcADouble, aDoubleChanged }, - { rcRInt, rIntChanged }, - { rcGInt, gIntChanged }, - { rcBInt, bIntChanged }, - { rcAInt, aIntChanged }, - { rcHex, hexChanged }, -}; - -static INT_PTR CALLBACK colorDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - struct colorDialog *c; - - c = (struct colorDialog *) GetWindowLongPtrW(hwnd, DWLP_USER); - if (c == NULL) { - if (uMsg == WM_INITDIALOG) { - c = beginColorDialog(hwnd, lParam); - SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR) c); - return TRUE; - } - return FALSE; - } - - switch (uMsg) { - case WM_COMMAND: - SetWindowLongPtrW(c->hwnd, DWLP_MSGRESULT, 0); // just in case - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - if (HIWORD(wParam) != BN_CLICKED) - return FALSE; - tryFinishDialog(c, wParam); - return TRUE; - case rcH: - case rcS: - case rcV: - case rcRDouble: - case rcGDouble: - case rcBDouble: - case rcADouble: - case rcRInt: - case rcGInt: - case rcBInt: - case rcAInt: - case rcHex: - if (HIWORD(wParam) != EN_CHANGE) - return FALSE; - if (c->updating) // prevent infinite recursion during an update - return FALSE; - (*(changed[LOWORD(wParam)]))(c); - return TRUE; - } - return FALSE; - } - return FALSE; -} - -BOOL showColorDialog(HWND parent, struct colorDialogRGBA *c) -{ - switch (DialogBoxParamW(hInstance, MAKEINTRESOURCE(rcColorDialog), parent, colorDialogDlgProc, (LPARAM) c)) { - case 1: // cancel - return FALSE; - case 2: // ok - // make the compiler happy by putting the return after the switch - break; - default: - logLastError(L"error running color dialog"); - } - return TRUE; -} diff --git a/src/libui_sdl/libui/windows/combobox.cpp b/src/libui_sdl/libui/windows/combobox.cpp deleted file mode 100644 index 87c999ea..00000000 --- a/src/libui_sdl/libui/windows/combobox.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.hpp" - -// we as Common Controls 6 users don't need to worry about the height of comboboxes; see http://blogs.msdn.com/b/oldnewthing/archive/2006/03/10/548537.aspx - -struct uiCombobox { - uiWindowsControl c; - HWND hwnd; - void (*onSelected)(uiCombobox *, void *); - void *onSelectedData; -}; - -static BOOL onWM_COMMAND(uiControl *cc, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiCombobox *c = uiCombobox(cc); - - if (code != CBN_SELCHANGE) - return FALSE; - (*(c->onSelected))(c, c->onSelectedData); - *lResult = 0; - return TRUE; -} - -void uiComboboxDestroy(uiControl *cc) -{ - uiCombobox *c = uiCombobox(cc); - - uiWindowsUnregisterWM_COMMANDHandler(c->hwnd); - uiWindowsEnsureDestroyWindow(c->hwnd); - uiFreeControl(uiControl(c)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiCombobox) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define comboboxWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary; LONGTERM */ -#define comboboxHeight 14 /* LONGTERM: is this too high? */ - -static void uiComboboxMinimumSize(uiWindowsControl *cc, int *width, int *height) -{ - uiCombobox *c = uiCombobox(cc); - uiWindowsSizing sizing; - int x, y; - - x = comboboxWidth; - y = comboboxHeight; - uiWindowsGetSizing(c->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -static void defaultOnSelected(uiCombobox *c, void *data) -{ - // do nothing -} - -void uiComboboxAppend(uiCombobox *c, const char *text) -{ - WCHAR *wtext; - LRESULT res; - - wtext = toUTF16(text); - res = SendMessageW(c->hwnd, CB_ADDSTRING, 0, (LPARAM) wtext); - if (res == (LRESULT) CB_ERR) - logLastError(L"error appending item to uiCombobox"); - else if (res == (LRESULT) CB_ERRSPACE) - logLastError(L"memory exhausted appending item to uiCombobox"); - uiFree(wtext); -} - -int uiComboboxSelected(uiCombobox *c) -{ - LRESULT n; - - n = SendMessage(c->hwnd, CB_GETCURSEL, 0, 0); - if (n == (LRESULT) CB_ERR) - return -1; - return n; -} - -void uiComboboxSetSelected(uiCombobox *c, int n) -{ - // TODO error check - SendMessageW(c->hwnd, CB_SETCURSEL, (WPARAM) n, 0); -} - -void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data) -{ - c->onSelected = f; - c->onSelectedData = data; -} - -uiCombobox *uiNewCombobox(void) -{ - uiCombobox *c; - - uiWindowsNewControl(uiCombobox, c); - - c->hwnd = uiWindowsEnsureCreateControlHWND(WS_EX_CLIENTEDGE, - L"combobox", L"", - CBS_DROPDOWNLIST | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_COMMANDHandler(c->hwnd, onWM_COMMAND, uiControl(c)); - uiComboboxOnSelected(c, defaultOnSelected, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/windows/compilerver.hpp b/src/libui_sdl/libui/windows/compilerver.hpp deleted file mode 100644 index 6c9e6b81..00000000 --- a/src/libui_sdl/libui/windows/compilerver.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// 9 june 2015 - -// Visual Studio (Microsoft's compilers) -// VS2013 is needed for va_copy(). -#ifdef _MSC_VER -#if _MSC_VER < 1800 -#error Visual Studio 2013 or higher is required to build libui. -#endif -#endif - -// LONGTERM MinGW - -// other compilers can be added here as necessary diff --git a/src/libui_sdl/libui/windows/container.cpp b/src/libui_sdl/libui/windows/container.cpp deleted file mode 100644 index 9ec1e280..00000000 --- a/src/libui_sdl/libui/windows/container.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// 26 april 2015 -#include "uipriv_windows.hpp" - -// Code for the HWND of the following uiControls: -// - uiBox -// - uiRadioButtons -// - uiSpinbox -// - uiTab -// - uiForm -// - uiGrid - -struct containerInit { - uiWindowsControl *c; - void (*onResize)(uiWindowsControl *); -}; - -static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - RECT r; - HDC dc; - PAINTSTRUCT ps; - CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; - WINDOWPOS *wp = (WINDOWPOS *) lParam; - MINMAXINFO *mmi = (MINMAXINFO *) lParam; - struct containerInit *init; - uiWindowsControl *c; - void (*onResize)(uiWindowsControl *); - int minwid, minht; - LRESULT lResult; - - if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - switch (uMsg) { - case WM_CREATE: - init = (struct containerInit *) (cs->lpCreateParams); - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (init->onResize)); - SetWindowLongPtrW(hwnd, 0, (LONG_PTR) (init->c)); - break; // defer to DefWindowProc() - case WM_WINDOWPOSCHANGED: - if ((wp->flags & SWP_NOSIZE) != 0) - break; // defer to DefWindowProc(); - onResize = (void (*)(uiWindowsControl *)) GetWindowLongPtrW(hwnd, GWLP_USERDATA); - c = (uiWindowsControl *) GetWindowLongPtrW(hwnd, 0); - (*(onResize))(c); - return 0; - case WM_GETMINMAXINFO: - lResult = DefWindowProcW(hwnd, uMsg, wParam, lParam); - c = (uiWindowsControl *) GetWindowLongPtrW(hwnd, 0); - uiWindowsControlMinimumSize(c, &minwid, &minht); - mmi->ptMinTrackSize.x = minwid; - mmi->ptMinTrackSize.y = minht; - return lResult; - case WM_PAINT: - dc = BeginPaint(hwnd, &ps); - if (dc == NULL) { - logLastError(L"error beginning container paint"); - // bail out; hope DefWindowProc() catches us - break; - } - r = ps.rcPaint; - paintContainerBackground(hwnd, dc, &r); - EndPaint(hwnd, &ps); - return 0; - // tab controls use this to draw the background of the tab area - case WM_PRINTCLIENT: - uiWindowsEnsureGetClientRect(hwnd, &r); - paintContainerBackground(hwnd, (HDC) wParam, &r); - return 0; - case WM_ERASEBKGND: - // avoid some flicker - // we draw the whole update area anyway - return 1; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -ATOM initContainer(HICON hDefaultIcon, HCURSOR hDefaultCursor) -{ - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = containerClass; - wc.lpfnWndProc = containerWndProc; - wc.hInstance = hInstance; - wc.hIcon = hDefaultIcon; - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - wc.cbWndExtra = sizeof (void *); - return RegisterClassW(&wc); -} - -void uninitContainer(void) -{ - if (UnregisterClassW(containerClass, hInstance) == 0) - logLastError(L"error unregistering container window class"); -} - -HWND uiWindowsMakeContainer(uiWindowsControl *c, void (*onResize)(uiWindowsControl *)) -{ - struct containerInit init; - - // TODO onResize cannot be NULL - init.c = c; - init.onResize = onResize; - return uiWindowsEnsureCreateControlHWND(WS_EX_CONTROLPARENT, - containerClass, L"", - 0, - hInstance, (LPVOID) (&init), - FALSE); -} diff --git a/src/libui_sdl/libui/windows/control.cpp b/src/libui_sdl/libui/windows/control.cpp deleted file mode 100644 index ce953cf9..00000000 --- a/src/libui_sdl/libui/windows/control.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// 16 august 2015 -#include "uipriv_windows.hpp" - -void uiWindowsControlSyncEnableState(uiWindowsControl *c, int enabled) -{ - (*(c->SyncEnableState))(c, enabled); -} - -void uiWindowsControlSetParentHWND(uiWindowsControl *c, HWND parent) -{ - (*(c->SetParentHWND))(c, parent); -} - -void uiWindowsControlMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - (*(c->MinimumSize))(c, width, height); -} - -void uiWindowsControlMinimumSizeChanged(uiWindowsControl *c) -{ - (*(c->MinimumSizeChanged))(c); -} - -// TODO get rid of this -void uiWindowsControlLayoutRect(uiWindowsControl *c, RECT *r) -{ - (*(c->LayoutRect))(c, r); -} - -void uiWindowsControlAssignControlIDZOrder(uiWindowsControl *c, LONG_PTR *controlID, HWND *insertAfter) -{ - (*(c->AssignControlIDZOrder))(c, controlID, insertAfter); -} - -void uiWindowsControlChildVisibilityChanged(uiWindowsControl *c) -{ - (*(c->ChildVisibilityChanged))(c); -} - -HWND uiWindowsEnsureCreateControlHWND(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, HINSTANCE hInstance, LPVOID lpParam, BOOL useStandardControlFont) -{ - HWND hwnd; - - // don't let using the arrow keys in a uiRadioButtons leave the radio buttons - if ((dwStyle & WS_TABSTOP) != 0) - dwStyle |= WS_GROUP; - hwnd = CreateWindowExW(dwExStyle, - lpClassName, lpWindowName, - dwStyle | WS_CHILD | WS_VISIBLE, - 0, 0, - // use a nonzero initial size just in case some control breaks with a zero initial size - 100, 100, - utilWindow, NULL, hInstance, lpParam); - if (hwnd == NULL) { - logLastError(L"error creating window"); - // TODO return a decoy window - } - if (useStandardControlFont) - SendMessageW(hwnd, WM_SETFONT, (WPARAM) hMessageFont, (LPARAM) TRUE); - return hwnd; -} - -// choose a value distinct from uiWindowSignature -#define uiWindowsControlSignature 0x4D53576E - -uiWindowsControl *uiWindowsAllocControl(size_t n, uint32_t typesig, const char *typenamestr) -{ - return uiWindowsControl(uiAllocControl(n, uiWindowsControlSignature, typesig, typenamestr)); -} - -BOOL uiWindowsShouldStopSyncEnableState(uiWindowsControl *c, BOOL enabled) -{ - int ce; - - ce = uiControlEnabled(uiControl(c)); - // only stop if we're going from disabled back to enabled; don't stop under any other condition - // (if we stop when going from enabled to disabled then enabled children of a disabled control won't get disabled at the OS level) - if (!ce && enabled) - return TRUE; - return FALSE; -} - -void uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl *c) -{ - LONG_PTR controlID; - HWND insertAfter; - - controlID = 100; - insertAfter = NULL; - uiWindowsControlAssignControlIDZOrder(c, &controlID, &insertAfter); -} - -BOOL uiWindowsControlTooSmall(uiWindowsControl *c) -{ - RECT r; - int width, height; - - uiWindowsControlLayoutRect(c, &r); - uiWindowsControlMinimumSize(c, &width, &height); - if ((r.right - r.left) < width) - return TRUE; - if ((r.bottom - r.top) < height) - return TRUE; - return FALSE; -} - -void uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl *c) -{ - uiControl *parent; - - parent = uiControlParent(uiControl(c)); - if (parent != NULL) - uiWindowsControlMinimumSizeChanged(uiWindowsControl(parent)); -} - -// TODO rename this nad the OS X this and hugging ones to NotifyChild -void uiWindowsControlNotifyVisibilityChanged(uiWindowsControl *c) -{ - // TODO we really need to figure this out; the duplication is a mess - uiWindowsControlContinueMinimumSizeChanged(c); -} diff --git a/src/libui_sdl/libui/windows/d2dscratch.cpp b/src/libui_sdl/libui/windows/d2dscratch.cpp deleted file mode 100644 index 6dc2ba5f..00000000 --- a/src/libui_sdl/libui/windows/d2dscratch.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// 17 april 2016 -#include "uipriv_windows.hpp" - -// The Direct2D scratch window is a utility for libui internal use to do quick things with Direct2D. -// To use, call newD2DScratch() passing in a subclass procedure. This subclass procedure should handle the msgD2DScratchPaint message, which has the following usage: -// - wParam - 0 -// - lParam - ID2D1RenderTarget * -// - lResult - 0 -// You can optionally also handle msgD2DScratchLButtonDown, which is sent when the left mouse button is either pressed for the first time or held while the mouse is moving. -// - wParam - position in DIPs, as D2D1_POINT_2F * -// - lParam - size of render target in DIPs, as D2D1_SIZE_F * -// - lResult - 0 -// Other messages can also be handled here. - -// TODO allow resize - -#define d2dScratchClass L"libui_d2dScratchClass" - -// TODO clip rect -static HRESULT d2dScratchDoPaint(HWND hwnd, ID2D1RenderTarget *rt) -{ - COLORREF bgcolorref; - D2D1_COLOR_F bgcolor; - - rt->BeginDraw(); - - // TODO only clear the clip area - // TODO clear with actual background brush - bgcolorref = GetSysColor(COLOR_BTNFACE); - bgcolor.r = ((float) GetRValue(bgcolorref)) / 255.0; - // due to utter apathy on Microsoft's part, GetGValue() does not work with MSVC's Run-Time Error Checks - // it has not worked since 2008 and they have *never* fixed it - // TODO now that -RTCc has just been deprecated entirely, should we switch back? - bgcolor.g = ((float) ((BYTE) ((bgcolorref & 0xFF00) >> 8))) / 255.0; - bgcolor.b = ((float) GetBValue(bgcolorref)) / 255.0; - bgcolor.a = 1.0; - rt->Clear(&bgcolor); - - SendMessageW(hwnd, msgD2DScratchPaint, 0, (LPARAM) rt); - - return rt->EndDraw(NULL, NULL); -} - -static void d2dScratchDoLButtonDown(HWND hwnd, ID2D1RenderTarget *rt, LPARAM lParam) -{ - double xpix, ypix; - FLOAT dpix, dpiy; - D2D1_POINT_2F pos; - D2D1_SIZE_F size; - - xpix = (double) GET_X_LPARAM(lParam); - ypix = (double) GET_Y_LPARAM(lParam); - // these are in pixels; we need points - // TODO separate the function from areautil.cpp? - rt->GetDpi(&dpix, &dpiy); - pos.x = (xpix * 96) / dpix; - pos.y = (ypix * 96) / dpiy; - - size = realGetSize(rt); - - SendMessageW(hwnd, msgD2DScratchLButtonDown, (WPARAM) (&pos), (LPARAM) (&size)); -} - -static LRESULT CALLBACK d2dScratchWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - LONG_PTR init; - ID2D1HwndRenderTarget *rt; - ID2D1DCRenderTarget *dcrt; - RECT client; - HRESULT hr; - - init = GetWindowLongPtrW(hwnd, 0); - if (!init) { - if (uMsg == WM_CREATE) - SetWindowLongPtrW(hwnd, 0, (LONG_PTR) TRUE); - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } - - rt = (ID2D1HwndRenderTarget *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); - if (rt == NULL) { - rt = makeHWNDRenderTarget(hwnd); - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) rt); - } - - switch (uMsg) { - case WM_DESTROY: - rt->Release(); - SetWindowLongPtrW(hwnd, 0, (LONG_PTR) FALSE); - break; - case WM_PAINT: - hr = d2dScratchDoPaint(hwnd, rt); - switch (hr) { - case S_OK: - if (ValidateRect(hwnd, NULL) == 0) - logLastError(L"error validating D2D scratch control rect"); - break; - case D2DERR_RECREATE_TARGET: - // DON'T validate the rect - // instead, simply drop the render target - // we'll get another WM_PAINT and make the render target again - // TODO would this require us to invalidate the entire client area? - rt->Release(); - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) NULL); - break; - default: - logHRESULT(L"error drawing D2D scratch window", hr); - } - return 0; - case WM_PRINTCLIENT: - uiWindowsEnsureGetClientRect(hwnd, &client); - dcrt = makeHDCRenderTarget((HDC) wParam, &client); - hr = d2dScratchDoPaint(hwnd, dcrt); - if (hr != S_OK) - logHRESULT(L"error printing D2D scratch window client area", hr); - dcrt->Release(); - return 0; - case WM_LBUTTONDOWN: - d2dScratchDoLButtonDown(hwnd, rt, lParam); - return 0; - case WM_MOUSEMOVE: - // also send LButtonDowns when dragging - if ((wParam & MK_LBUTTON) != 0) - d2dScratchDoLButtonDown(hwnd, rt, lParam); - return 0; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -ATOM registerD2DScratchClass(HICON hDefaultIcon, HCURSOR hDefaultCursor) -{ - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = d2dScratchClass; - wc.lpfnWndProc = d2dScratchWndProc; - wc.hInstance = hInstance; - wc.hIcon = hDefaultIcon; - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - wc.cbWndExtra = sizeof (LONG_PTR); // for the init status - return RegisterClassW(&wc); -} - -void unregisterD2DScratchClass(void) -{ - if (UnregisterClassW(d2dScratchClass, hInstance) == 0) - logLastError(L"error unregistering D2D scratch window class"); -} - -HWND newD2DScratch(HWND parent, RECT *rect, HMENU controlID, SUBCLASSPROC subclass, DWORD_PTR subclassData) -{ - HWND hwnd; - - hwnd = CreateWindowExW(0, - d2dScratchClass, L"", - WS_CHILD | WS_VISIBLE, - rect->left, rect->top, - rect->right - rect->left, rect->bottom - rect->top, - parent, controlID, hInstance, NULL); - if (hwnd == NULL) - // TODO return decoy window - logLastError(L"error creating D2D scratch window"); - if (SetWindowSubclass(hwnd, subclass, 0, subclassData) == FALSE) - logLastError(L"error subclassing D2D scratch window"); - return hwnd; -} diff --git a/src/libui_sdl/libui/windows/datetimepicker.cpp b/src/libui_sdl/libui/windows/datetimepicker.cpp deleted file mode 100644 index e105c2fd..00000000 --- a/src/libui_sdl/libui/windows/datetimepicker.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// 22 may 2015 -#include "uipriv_windows.hpp" - -struct uiDateTimePicker { - uiWindowsControl c; - HWND hwnd; -}; - -// utility functions - -#define GLI(what, buf, n) GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, what, buf, n) - -// The real date/time picker does a manual replacement of "yy" with "yyyy" for DTS_SHORTDATECENTURYFORMAT. -// Because we're also duplicating its functionality (see below), we have to do it too. -static WCHAR *expandYear(WCHAR *dts, int n) -{ - WCHAR *out; - WCHAR *p, *q; - int ny = 0; - - // allocate more than we need to be safe - out = (WCHAR *) uiAlloc((n * 3) * sizeof (WCHAR), "WCHAR[]"); - q = out; - for (p = dts; *p != L'\0'; p++) { - // first, if the current character is a y, increment the number of consecutive ys - // otherwise, stop counting, and if there were only two, add two more to make four - if (*p != L'y') { - if (ny == 2) { - *q++ = L'y'; - *q++ = L'y'; - } - ny = 0; - } else - ny++; - // next, handle quoted blocks - // we do this AFTER the above so yy'abc' becomes yyyy'abc' and not yy'abc'yy - // this handles the case of 'a''b' elegantly as well - if (*p == L'\'') { - // copy the opening quote - *q++ = *p; - // copy the contents - for (;;) { - p++; - if (*p == L'\'') - break; - if (*p == L'\0') - implbug("unterminated quote in system-provided locale date string in expandYear()"); - *q++ = *p; - } - // and fall through to copy the closing quote - } - // copy the current character - *q++ = *p; - } - // handle trailing yy - if (ny == 2) { - *q++ = L'y'; - *q++ = L'y'; - } - *q++ = L'\0'; - return out; -} - -// Windows has no combined date/time prebuilt constant; we have to build the format string ourselves -// TODO use a default format if one fails -static void setDateTimeFormat(HWND hwnd) -{ - WCHAR *unexpandedDate, *date; - WCHAR *time; - WCHAR *datetime; - int ndate, ntime; - - ndate = GLI(LOCALE_SSHORTDATE, NULL, 0); - if (ndate == 0) - logLastError(L"error getting date string length"); - date = (WCHAR *) uiAlloc(ndate * sizeof (WCHAR), "WCHAR[]"); - if (GLI(LOCALE_SSHORTDATE, date, ndate) == 0) - logLastError(L"error geting date string"); - unexpandedDate = date; // so we can free it - date = expandYear(unexpandedDate, ndate); - uiFree(unexpandedDate); - - ntime = GLI(LOCALE_STIMEFORMAT, NULL, 0); - if (ndate == 0) - logLastError(L"error getting time string length"); - time = (WCHAR *) uiAlloc(ntime * sizeof (WCHAR), "WCHAR[]"); - if (GLI(LOCALE_STIMEFORMAT, time, ntime) == 0) - logLastError(L"error geting time string"); - - datetime = strf(L"%s %s", date, time); - if (SendMessageW(hwnd, DTM_SETFORMAT, 0, (LPARAM) datetime) == 0) - logLastError(L"error applying format string to date/time picker"); - - uiFree(datetime); - uiFree(time); - uiFree(date); -} - -// control implementation - -static void uiDateTimePickerDestroy(uiControl *c) -{ - uiDateTimePicker *d = uiDateTimePicker(c); - - uiWindowsUnregisterReceiveWM_WININICHANGE(d->hwnd); - uiWindowsEnsureDestroyWindow(d->hwnd); - uiFreeControl(uiControl(d)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiDateTimePicker) - -// the height returned from DTM_GETIDEALSIZE is unreliable; see http://stackoverflow.com/questions/30626549/what-is-the-proper-use-of-dtm-getidealsize-treating-the-returned-size-as-pixels -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define entryHeight 14 - -static void uiDateTimePickerMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiDateTimePicker *d = uiDateTimePicker(c); - SIZE s; - uiWindowsSizing sizing; - int y; - - s.cx = 0; - s.cy = 0; - SendMessageW(d->hwnd, DTM_GETIDEALSIZE, 0, (LPARAM) (&s)); - *width = s.cx; - - y = entryHeight; - uiWindowsGetSizing(d->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y); - *height = y; -} - -static uiDateTimePicker *finishNewDateTimePicker(DWORD style) -{ - uiDateTimePicker *d; - - uiWindowsNewControl(uiDateTimePicker, d); - - d->hwnd = uiWindowsEnsureCreateControlHWND(WS_EX_CLIENTEDGE, - DATETIMEPICK_CLASSW, L"", - style | WS_TABSTOP, - hInstance, NULL, - TRUE); - - // automatically update date/time format when user changes locale settings - // for the standard styles, this is in the date-time picker itself - // for our date/time mode, we do it in a subclass assigned in uiNewDateTimePicker() - uiWindowsRegisterReceiveWM_WININICHANGE(d->hwnd); - - return d; -} - -static LRESULT CALLBACK datetimepickerSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - switch (uMsg) { - case WM_WININICHANGE: - // we can optimize this by only doing it when the real date/time picker does it - // unfortunately, I don't know when that is :/ - // hopefully this won't hurt - setDateTimeFormat(hwnd); - return 0; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, datetimepickerSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing date-time picker locale change handling subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -uiDateTimePicker *uiNewDateTimePicker(void) -{ - uiDateTimePicker *d; - - d = finishNewDateTimePicker(0); - setDateTimeFormat(d->hwnd); - if (SetWindowSubclass(d->hwnd, datetimepickerSubProc, 0, (DWORD_PTR) d) == FALSE) - logLastError(L"error subclassing date-time-picker to assist in locale change handling"); - // TODO set a suitable default in this case - return d; -} - -uiDateTimePicker *uiNewDatePicker(void) -{ - return finishNewDateTimePicker(DTS_SHORTDATECENTURYFORMAT); -} - -uiDateTimePicker *uiNewTimePicker(void) -{ - return finishNewDateTimePicker(DTS_TIMEFORMAT); -} diff --git a/src/libui_sdl/libui/windows/debug.cpp b/src/libui_sdl/libui/windows/debug.cpp deleted file mode 100644 index cfafffdc..00000000 --- a/src/libui_sdl/libui/windows/debug.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// 25 february 2015 -#include "uipriv_windows.hpp" - -// LONGTERM disable logging and stopping on no-debug builds - -static void printDebug(const WCHAR *msg) -{ - OutputDebugStringW(msg); -} - -HRESULT _logLastError(debugargs, const WCHAR *s) -{ - DWORD le; - WCHAR *msg; - WCHAR *formatted; - BOOL useFormatted; - - le = GetLastError(); - - useFormatted = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, le, 0, (LPWSTR) (&formatted), 0, NULL) != 0; - if (!useFormatted) - formatted = L"\n"; - msg = strf(L"[libui] %s:%s:%s() %s: GetLastError() == %I32u %s", - file, line, func, - s, le, formatted); - if (useFormatted) - LocalFree(formatted); // ignore error - printDebug(msg); - uiFree(msg); - DebugBreak(); - - SetLastError(le); - // a function does not have to set a last error - // if the last error we get is actually 0, then HRESULT_FROM_WIN32(0) will return S_OK (0 cast to an HRESULT, since 0 <= 0), which we don't want - // prevent this by returning E_FAIL - if (le == 0) - return E_FAIL; - return HRESULT_FROM_WIN32(le); -} - -HRESULT _logHRESULT(debugargs, const WCHAR *s, HRESULT hr) -{ - WCHAR *msg; - WCHAR *formatted; - BOOL useFormatted; - - useFormatted = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, 0, (LPWSTR) (&formatted), 0, NULL) != 0; - if (!useFormatted) - formatted = L"\n"; - msg = strf(L"[libui] %s:%s:%s() %s: HRESULT == 0x%08I32X %s", - file, line, func, - s, hr, formatted); - if (useFormatted) - LocalFree(formatted); // ignore error - printDebug(msg); - uiFree(msg); - DebugBreak(); - - return hr; -} - -void realbug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap) -{ - va_list ap2; - char *msg; - size_t n; - WCHAR *final; - - va_copy(ap2, ap); - n = _vscprintf(format, ap2); - va_end(ap2); - n++; // terminating '\0' - - msg = (char *) uiAlloc(n * sizeof (char), "char[]"); - // includes terminating '\0' according to example in https://msdn.microsoft.com/en-us/library/xa1a1a6z.aspx - vsprintf_s(msg, n, format, ap); - - final = strf(L"[libui] %hs:%hs:%hs() %hs%hs\n", file, line, func, prefix, msg); - uiFree(msg); - printDebug(final); - uiFree(final); - - DebugBreak(); -} diff --git a/src/libui_sdl/libui/windows/draw.cpp b/src/libui_sdl/libui/windows/draw.cpp deleted file mode 100644 index 9a815b91..00000000 --- a/src/libui_sdl/libui/windows/draw.cpp +++ /dev/null @@ -1,578 +0,0 @@ -// 7 september 2015 -#include "uipriv_windows.hpp" -#include "draw.hpp" - -ID2D1Factory *d2dfactory = NULL; - -HRESULT initDraw(void) -{ - D2D1_FACTORY_OPTIONS opts; - - ZeroMemory(&opts, sizeof (D2D1_FACTORY_OPTIONS)); - // TODO make this an option - opts.debugLevel = D2D1_DEBUG_LEVEL_NONE; - return D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, - IID_ID2D1Factory, - &opts, - (void **) (&d2dfactory)); -} - -void uninitDraw(void) -{ - d2dfactory->Release(); -} - -ID2D1HwndRenderTarget *makeHWNDRenderTarget(HWND hwnd) -{ - D2D1_RENDER_TARGET_PROPERTIES props; - D2D1_HWND_RENDER_TARGET_PROPERTIES hprops; - HDC dc; - RECT r; - ID2D1HwndRenderTarget *rt; - HRESULT hr; - - // we need a DC for the DPI - // we *could* just use the screen DPI but why when we have a window handle and its DC has a DPI - dc = GetDC(hwnd); - if (dc == NULL) - logLastError(L"error getting DC to find DPI"); - - ZeroMemory(&props, sizeof (D2D1_RENDER_TARGET_PROPERTIES)); - props.type = D2D1_RENDER_TARGET_TYPE_HARDWARE;//DEFAULT; - props.pixelFormat.format = DXGI_FORMAT_UNKNOWN; - props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN; - props.dpiX = GetDeviceCaps(dc, LOGPIXELSX); - props.dpiY = GetDeviceCaps(dc, LOGPIXELSY); - props.usage = D2D1_RENDER_TARGET_USAGE_NONE; - props.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; - - if (ReleaseDC(hwnd, dc) == 0) - logLastError(L"error releasing DC for finding DPI"); - - uiWindowsEnsureGetClientRect(hwnd, &r); - - ZeroMemory(&hprops, sizeof (D2D1_HWND_RENDER_TARGET_PROPERTIES)); - hprops.hwnd = hwnd; - hprops.pixelSize.width = r.right - r.left; - hprops.pixelSize.height = r.bottom - r.top; - // according to Rick Brewster, some drivers will misbehave if we don't specify this (see http://stackoverflow.com/a/33222983/3408572) - hprops.presentOptions = D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS; - - hr = d2dfactory->CreateHwndRenderTarget( - &props, - &hprops, - &rt); - if (hr != S_OK) - { - props.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; - hr = d2dfactory->CreateHwndRenderTarget( - &props, - &hprops, - &rt); - if (hr != S_OK) - logHRESULT(L"error creating HWND render target", hr); - } - - return rt; -} - -ID2D1DCRenderTarget *makeHDCRenderTarget(HDC dc, RECT *r) -{ - D2D1_RENDER_TARGET_PROPERTIES props; - ID2D1DCRenderTarget *rt; - HRESULT hr; - - ZeroMemory(&props, sizeof (D2D1_RENDER_TARGET_PROPERTIES)); - props.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; - props.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; - props.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; - props.dpiX = GetDeviceCaps(dc, LOGPIXELSX); - props.dpiY = GetDeviceCaps(dc, LOGPIXELSY); - props.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE; - props.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; - - hr = d2dfactory->CreateDCRenderTarget(&props, &rt); - if (hr != S_OK) - logHRESULT(L"error creating DC render target", hr); - hr = rt->BindDC(dc, r); - if (hr != S_OK) - logHRESULT(L"error binding DC to DC render target", hr); - return rt; -} - -static void resetTarget(ID2D1RenderTarget *rt) -{ - D2D1_MATRIX_3X2_F dm; - - // transformations persist - // reset to the identity matrix - ZeroMemory(&dm, sizeof (D2D1_MATRIX_3X2_F)); - dm._11 = 1; - dm._22 = 1; - rt->SetTransform(&dm); -} - -uiDrawContext *newContext(ID2D1RenderTarget *rt) -{ - uiDrawContext *c; - - c = uiNew(uiDrawContext); - c->rt = rt; - c->states = new std::vector; - resetTarget(c->rt); - return c; -} - -void freeContext(uiDrawContext *c) -{ - if (c->currentClip != NULL) - c->currentClip->Release(); - if (c->states->size() != 0) - // TODO do this on other platforms - userbug("You did not balance uiDrawSave() and uiDrawRestore() calls."); - delete c->states; - uiFree(c); -} - -static ID2D1Brush *makeSolidBrush(uiDrawBrush *b, ID2D1RenderTarget *rt, D2D1_BRUSH_PROPERTIES *props) -{ - D2D1_COLOR_F color; - ID2D1SolidColorBrush *brush; - HRESULT hr; - - color.r = b->R; - color.g = b->G; - color.b = b->B; - color.a = b->A; - - hr = rt->CreateSolidColorBrush( - &color, - props, - &brush); - if (hr != S_OK) - logHRESULT(L"error creating solid brush", hr); - return brush; -} - -static ID2D1GradientStopCollection *mkstops(uiDrawBrush *b, ID2D1RenderTarget *rt) -{ - ID2D1GradientStopCollection *s; - D2D1_GRADIENT_STOP *stops; - size_t i; - HRESULT hr; - - stops = (D2D1_GRADIENT_STOP *) uiAlloc(b->NumStops * sizeof (D2D1_GRADIENT_STOP), "D2D1_GRADIENT_STOP[]"); - for (i = 0; i < b->NumStops; i++) { - stops[i].position = b->Stops[i].Pos; - stops[i].color.r = b->Stops[i].R; - stops[i].color.g = b->Stops[i].G; - stops[i].color.b = b->Stops[i].B; - stops[i].color.a = b->Stops[i].A; - } - - hr = rt->CreateGradientStopCollection( - stops, - b->NumStops, - D2D1_GAMMA_2_2, // this is the default for the C++-only overload of ID2D1RenderTarget::GradientStopCollection() - D2D1_EXTEND_MODE_CLAMP, - &s); - if (hr != S_OK) - logHRESULT(L"error creating stop collection", hr); - - uiFree(stops); - return s; -} - -static ID2D1Brush *makeLinearBrush(uiDrawBrush *b, ID2D1RenderTarget *rt, D2D1_BRUSH_PROPERTIES *props) -{ - ID2D1LinearGradientBrush *brush; - D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES gprops; - ID2D1GradientStopCollection *stops; - HRESULT hr; - - ZeroMemory(&gprops, sizeof (D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)); - gprops.startPoint.x = b->X0; - gprops.startPoint.y = b->Y0; - gprops.endPoint.x = b->X1; - gprops.endPoint.y = b->Y1; - - stops = mkstops(b, rt); - - hr = rt->CreateLinearGradientBrush( - &gprops, - props, - stops, - &brush); - if (hr != S_OK) - logHRESULT(L"error creating gradient brush", hr); - - // the example at https://msdn.microsoft.com/en-us/library/windows/desktop/dd756682%28v=vs.85%29.aspx says this is safe to do now - stops->Release(); - return brush; -} - -static ID2D1Brush *makeRadialBrush(uiDrawBrush *b, ID2D1RenderTarget *rt, D2D1_BRUSH_PROPERTIES *props) -{ - ID2D1RadialGradientBrush *brush; - D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES gprops; - ID2D1GradientStopCollection *stops; - HRESULT hr; - - ZeroMemory(&gprops, sizeof (D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES)); - gprops.gradientOriginOffset.x = b->X0 - b->X1; - gprops.gradientOriginOffset.y = b->Y0 - b->Y1; - gprops.center.x = b->X1; - gprops.center.y = b->Y1; - gprops.radiusX = b->OuterRadius; - gprops.radiusY = b->OuterRadius; - - stops = mkstops(b, rt); - - hr = rt->CreateRadialGradientBrush( - &gprops, - props, - stops, - &brush); - if (hr != S_OK) - logHRESULT(L"error creating gradient brush", hr); - - stops->Release(); - return brush; -} - -static ID2D1Brush *makeBrush(uiDrawBrush *b, ID2D1RenderTarget *rt) -{ - D2D1_BRUSH_PROPERTIES props; - - ZeroMemory(&props, sizeof (D2D1_BRUSH_PROPERTIES)); - props.opacity = 1.0; - // identity matrix - props.transform._11 = 1; - props.transform._22 = 1; - - switch (b->Type) { - case uiDrawBrushTypeSolid: - return makeSolidBrush(b, rt, &props); - case uiDrawBrushTypeLinearGradient: - return makeLinearBrush(b, rt, &props); - case uiDrawBrushTypeRadialGradient: - return makeRadialBrush(b, rt, &props); -// case uiDrawBrushTypeImage: -// TODO - } - - // TODO do this on all platforms - userbug("Invalid brush type %d given to drawing operation.", b->Type); - // TODO dummy brush? - return NULL; // make compiler happy -} - -// how clipping works: -// every fill and stroke is done on a temporary layer with the clip geometry applied to it -// this is really the only way to clip in Direct2D that doesn't involve opacity images -// reference counting: -// - initially the clip is NULL, which means do not use a layer -// - the first time uiDrawClip() is called, we take a reference on the path passed in (this is also why uiPathEnd() is needed) -// - every successive time, we create a new PathGeometry and merge the current clip with the new path, releasing the reference we took earlier and taking a reference to the new one -// - in Save, we take another reference; in Restore we drop the refernece to the existing path geometry and transfer that saved ref to the new path geometry over to the context -// uiDrawFreePath() doesn't destroy the path geometry, it just drops the reference count, so a clip can exist independent of its path - -static ID2D1Layer *applyClip(uiDrawContext *c) -{ - ID2D1Layer *layer; - D2D1_LAYER_PARAMETERS params; - HRESULT hr; - - // if no clip, don't do anything - if (c->currentClip == NULL) - return NULL; - - // create a layer for clipping - // we have to explicitly make the layer because we're still targeting Windows 7 - hr = c->rt->CreateLayer(NULL, &layer); - if (hr != S_OK) - logHRESULT(L"error creating clip layer", hr); - - // apply it as the clip - ZeroMemory(¶ms, sizeof (D2D1_LAYER_PARAMETERS)); - // this is the equivalent of InfiniteRect() in d2d1helper.h - params.contentBounds.left = -FLT_MAX; - params.contentBounds.top = -FLT_MAX; - params.contentBounds.right = FLT_MAX; - params.contentBounds.bottom = FLT_MAX; - params.geometricMask = (ID2D1Geometry *) (c->currentClip); - // TODO is this correct? - params.maskAntialiasMode = c->rt->GetAntialiasMode(); - // identity matrix - params.maskTransform._11 = 1; - params.maskTransform._22 = 1; - params.opacity = 1.0; - params.opacityBrush = NULL; - params.layerOptions = D2D1_LAYER_OPTIONS_NONE; - // TODO is this correct? - if (c->rt->GetTextAntialiasMode() == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE) - params.layerOptions = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE; - c->rt->PushLayer(¶ms, layer); - - // return the layer so it can be freed later - return layer; -} - -static void unapplyClip(uiDrawContext *c, ID2D1Layer *layer) -{ - if (layer == NULL) - return; - c->rt->PopLayer(); - layer->Release(); -} - -void uiDrawStroke(uiDrawContext *c, uiDrawPath *p, uiDrawBrush *b, uiDrawStrokeParams *sp) -{ - ID2D1Brush *brush; - ID2D1StrokeStyle *style; - D2D1_STROKE_STYLE_PROPERTIES dsp; - FLOAT *dashes; - size_t i; - ID2D1Layer *cliplayer; - HRESULT hr; - - brush = makeBrush(b, c->rt); - - ZeroMemory(&dsp, sizeof (D2D1_STROKE_STYLE_PROPERTIES)); - switch (sp->Cap) { - case uiDrawLineCapFlat: - dsp.startCap = D2D1_CAP_STYLE_FLAT; - dsp.endCap = D2D1_CAP_STYLE_FLAT; - dsp.dashCap = D2D1_CAP_STYLE_FLAT; - break; - case uiDrawLineCapRound: - dsp.startCap = D2D1_CAP_STYLE_ROUND; - dsp.endCap = D2D1_CAP_STYLE_ROUND; - dsp.dashCap = D2D1_CAP_STYLE_ROUND; - break; - case uiDrawLineCapSquare: - dsp.startCap = D2D1_CAP_STYLE_SQUARE; - dsp.endCap = D2D1_CAP_STYLE_SQUARE; - dsp.dashCap = D2D1_CAP_STYLE_SQUARE; - break; - } - switch (sp->Join) { - case uiDrawLineJoinMiter: - dsp.lineJoin = D2D1_LINE_JOIN_MITER_OR_BEVEL; - dsp.miterLimit = sp->MiterLimit; - break; - case uiDrawLineJoinRound: - dsp.lineJoin = D2D1_LINE_JOIN_ROUND; - break; - case uiDrawLineJoinBevel: - dsp.lineJoin = D2D1_LINE_JOIN_BEVEL; - break; - } - dsp.dashStyle = D2D1_DASH_STYLE_SOLID; - dashes = NULL; - // note that dash widths and the dash phase are scaled up by the thickness by Direct2D - // TODO be sure to formally document this - if (sp->NumDashes != 0) { - dsp.dashStyle = D2D1_DASH_STYLE_CUSTOM; - dashes = (FLOAT *) uiAlloc(sp->NumDashes * sizeof (FLOAT), "FLOAT[]"); - for (i = 0; i < sp->NumDashes; i++) - dashes[i] = sp->Dashes[i] / sp->Thickness; - } - dsp.dashOffset = sp->DashPhase / sp->Thickness; - hr = d2dfactory->CreateStrokeStyle( - &dsp, - dashes, - sp->NumDashes, - &style); - if (hr != S_OK) - logHRESULT(L"error creating stroke style", hr); - if (sp->NumDashes != 0) - uiFree(dashes); - - cliplayer = applyClip(c); - c->rt->DrawGeometry( - pathGeometry(p), - brush, - sp->Thickness, - style); - unapplyClip(c, cliplayer); - - style->Release(); - brush->Release(); -} - -void uiDrawFill(uiDrawContext *c, uiDrawPath *p, uiDrawBrush *b) -{ - ID2D1Brush *brush; - ID2D1Layer *cliplayer; - - brush = makeBrush(b, c->rt); - cliplayer = applyClip(c); - c->rt->FillGeometry( - pathGeometry(p), - brush, - NULL); - unapplyClip(c, cliplayer); - brush->Release(); -} - -void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m) -{ - D2D1_MATRIX_3X2_F dm, cur; - - c->rt->GetTransform(&cur); - m2d(m, &dm); - // you would think we have to do already * m, right? - // WRONG! we have to do m * already - // why? a few reasons - // a) this lovely comment in cairo's source - http://cgit.freedesktop.org/cairo/tree/src/cairo-matrix.c?id=0537479bd1d4c5a3bc0f6f41dec4deb98481f34a#n330 - // Direct2D uses column vectors and I don't know if this is even documented - // b) that's what Core Graphics does - // TODO see if Microsoft says to do this - dm = dm * cur; // for whatever reason operator * is defined but not operator *= - c->rt->SetTransform(&dm); -} - -void uiDrawClip(uiDrawContext *c, uiDrawPath *path) -{ - ID2D1PathGeometry *newPath; - ID2D1GeometrySink *newSink; - HRESULT hr; - - // if there's no current clip, borrow the path - if (c->currentClip == NULL) { - c->currentClip = pathGeometry(path); - // we have to take our own reference to that clip - c->currentClip->AddRef(); - return; - } - - // otherwise we have to intersect the current path with the new one - // we do that into a new path, and then replace c->currentClip with that new path - hr = d2dfactory->CreatePathGeometry(&newPath); - if (hr != S_OK) - logHRESULT(L"error creating new path", hr); - hr = newPath->Open(&newSink); - if (hr != S_OK) - logHRESULT(L"error opening new path", hr); - hr = c->currentClip->CombineWithGeometry( - pathGeometry(path), - D2D1_COMBINE_MODE_INTERSECT, - NULL, - // TODO is this correct or can this be set per target? - D2D1_DEFAULT_FLATTENING_TOLERANCE, - newSink); - if (hr != S_OK) - logHRESULT(L"error intersecting old path with new path", hr); - hr = newSink->Close(); - if (hr != S_OK) - logHRESULT(L"error closing new path", hr); - newSink->Release(); - - // okay we have the new clip; we just need to replace the old one with it - c->currentClip->Release(); - c->currentClip = newPath; - // we have a reference already; no need for another -} - -struct drawState { - ID2D1DrawingStateBlock *dsb; - ID2D1PathGeometry *clip; -}; - -void uiDrawSave(uiDrawContext *c) -{ - struct drawState state; - HRESULT hr; - - hr = d2dfactory->CreateDrawingStateBlock( - // TODO verify that these are correct - NULL, - NULL, - &(state.dsb)); - if (hr != S_OK) - logHRESULT(L"error creating drawing state block", hr); - c->rt->SaveDrawingState(state.dsb); - - // if we have a clip, we need to hold another reference to it - if (c->currentClip != NULL) - c->currentClip->AddRef(); - state.clip = c->currentClip; // even if NULL assign it - - c->states->push_back(state); -} - -void uiDrawRestore(uiDrawContext *c) -{ - struct drawState state; - - state = (*(c->states))[c->states->size() - 1]; - c->states->pop_back(); - - c->rt->RestoreDrawingState(state.dsb); - state.dsb->Release(); - - // if we have a current clip, we need to drop it - if (c->currentClip != NULL) - c->currentClip->Release(); - // no need to explicitly addref or release; just transfer the ref - c->currentClip = state.clip; -} - - -// bitmap API - -uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha) -{ - uiDrawBitmap* bmp; - HRESULT hr; - - bmp = uiNew(uiDrawBitmap); - - D2D1_BITMAP_PROPERTIES bp2 = D2D1::BitmapProperties(); - bp2.dpiX = 0; - bp2.dpiY = 0; - bp2.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, - alpha ? D2D1_ALPHA_MODE_PREMULTIPLIED : D2D1_ALPHA_MODE_IGNORE); - - //c->rt->BeginDraw(); - - hr = c->rt->CreateBitmap(D2D1::SizeU(width,height), NULL, 0, &bp2, &bmp->bmp); - if (hr != S_OK) - logHRESULT(L"error creating bitmap", hr); - - //c->rt->EndDraw(); - - bmp->Width = width; - bmp->Height = height; - bmp->Stride = width*4; - - return bmp; -} - -void uiDrawBitmapUpdate(uiDrawBitmap* bmp, const void* data) -{ - D2D1_RECT_U rekt = D2D1::RectU(0, 0, bmp->Width, bmp->Height); - bmp->bmp->CopyFromMemory(&rekt, data, bmp->Stride); -} - -void uiDrawBitmapDraw(uiDrawContext* c, uiDrawBitmap* bmp, uiRect* srcrect, uiRect* dstrect, int filter) -{ - D2D_RECT_F _srcrect = D2D1::RectF(srcrect->X, srcrect->Y, srcrect->X+srcrect->Width, srcrect->Y+srcrect->Height); - D2D_RECT_F _dstrect = D2D1::RectF(dstrect->X, dstrect->Y, dstrect->X+dstrect->Width, dstrect->Y+dstrect->Height); - - float dpix, dpiy; - c->rt->GetDpi(&dpix, &dpiy); - _srcrect.left = (_srcrect.left * 96.0f) / dpix; - _srcrect.top = (_srcrect.top * 96.0f) / dpiy; - _srcrect.right = (_srcrect.right * 96.0f) / dpix; - _srcrect.bottom = (_srcrect.bottom * 96.0f) / dpiy; - - c->rt->DrawBitmap(bmp->bmp, &_dstrect, 1.0f, filter ? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR : D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, &_srcrect); -} - -void uiDrawFreeBitmap(uiDrawBitmap* bmp) -{ - bmp->bmp->Release(); - uiFree(bmp); -} diff --git a/src/libui_sdl/libui/windows/draw.hpp b/src/libui_sdl/libui/windows/draw.hpp deleted file mode 100644 index 992d0505..00000000 --- a/src/libui_sdl/libui/windows/draw.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// 5 may 2016 - -// draw.cpp -extern ID2D1Factory *d2dfactory; -struct uiDrawContext { - ID2D1RenderTarget *rt; - // TODO find out how this works - std::vector *states; - ID2D1PathGeometry *currentClip; -}; - -struct uiDrawBitmap { - int Width; - int Height; - int Stride; - - ID2D1Bitmap* bmp; -}; - -// drawpath.cpp -extern ID2D1PathGeometry *pathGeometry(uiDrawPath *p); - -// drawmatrix.cpp -extern void m2d(uiDrawMatrix *m, D2D1_MATRIX_3X2_F *d); diff --git a/src/libui_sdl/libui/windows/drawmatrix.cpp b/src/libui_sdl/libui/windows/drawmatrix.cpp deleted file mode 100644 index 090972a5..00000000 --- a/src/libui_sdl/libui/windows/drawmatrix.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// 7 september 2015 -#include "uipriv_windows.hpp" -#include "draw.hpp" - -void m2d(uiDrawMatrix *m, D2D1_MATRIX_3X2_F *d) -{ - d->_11 = m->M11; - d->_12 = m->M12; - d->_21 = m->M21; - d->_22 = m->M22; - d->_31 = m->M31; - d->_32 = m->M32; -} - -static void d2m(D2D1_MATRIX_3X2_F *d, uiDrawMatrix *m) -{ - m->M11 = d->_11; - m->M12 = d->_12; - m->M21 = d->_21; - m->M22 = d->_22; - m->M31 = d->_31; - m->M32 = d->_32; -} - -void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y) -{ - D2D1_MATRIX_3X2_F dm; - - m2d(m, &dm); - dm = dm * D2D1::Matrix3x2F::Translation(x, y); - d2m(&dm, m); -} - -void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y) -{ - D2D1_MATRIX_3X2_F dm; - D2D1_POINT_2F center; - - m2d(m, &dm); - center.x = xCenter; - center.y = yCenter; - dm = dm * D2D1::Matrix3x2F::Scale(x, y, center); - d2m(&dm, m); -} - -#define r2d(x) (x * (180.0 / uiPi)) - -void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount) -{ - D2D1_MATRIX_3X2_F dm; - D2D1_POINT_2F center; - - m2d(m, &dm); - center.x = x; - center.y = y; - dm = dm * D2D1::Matrix3x2F::Rotation(r2d(amount), center); - d2m(&dm, m); -} - -void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount) -{ - D2D1_MATRIX_3X2_F dm; - D2D1_POINT_2F center; - - m2d(m, &dm); - center.x = x; - center.y = y; - dm = dm * D2D1::Matrix3x2F::Skew(r2d(xamount), r2d(yamount), center); - d2m(&dm, m); -} - -void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src) -{ - D2D1_MATRIX_3X2_F c, d; - - m2d(dest, &c); - m2d(src, &d); - c = c * d; - d2m(&c, dest); -} - -int uiDrawMatrixInvertible(uiDrawMatrix *m) -{ - D2D1_MATRIX_3X2_F d; - - m2d(m, &d); - return D2D1IsMatrixInvertible(&d) != FALSE; -} - -int uiDrawMatrixInvert(uiDrawMatrix *m) -{ - D2D1_MATRIX_3X2_F d; - - m2d(m, &d); - if (D2D1InvertMatrix(&d) == FALSE) - return 0; - d2m(&d, m); - return 1; -} - -void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y) -{ - D2D1::Matrix3x2F dm; - D2D1_POINT_2F pt; - - m2d(m, &dm); - pt.x = *x; - pt.y = *y; - pt = dm.TransformPoint(pt); - *x = pt.x; - *y = pt.y; -} - -void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y) -{ - fallbackTransformSize(m, x, y); -} diff --git a/src/libui_sdl/libui/windows/drawpath.cpp b/src/libui_sdl/libui/windows/drawpath.cpp deleted file mode 100644 index 49855be6..00000000 --- a/src/libui_sdl/libui/windows/drawpath.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// 7 september 2015 -#include "uipriv_windows.hpp" -#include "draw.hpp" - -// TODO -// - write a test for transform followed by clip and clip followed by transform to make sure they work the same as on gtk+ and cocoa -// - write a test for nested transforms for gtk+ - -struct uiDrawPath { - ID2D1PathGeometry *path; - ID2D1GeometrySink *sink; - BOOL inFigure; -}; - -uiDrawPath *uiDrawNewPath(uiDrawFillMode fillmode) -{ - uiDrawPath *p; - HRESULT hr; - - p = uiNew(uiDrawPath); - hr = d2dfactory->CreatePathGeometry(&(p->path)); - if (hr != S_OK) - logHRESULT(L"error creating path", hr); - hr = p->path->Open(&(p->sink)); - if (hr != S_OK) - logHRESULT(L"error opening path", hr); - switch (fillmode) { - case uiDrawFillModeWinding: - p->sink->SetFillMode(D2D1_FILL_MODE_WINDING); - break; - case uiDrawFillModeAlternate: - p->sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); - break; - } - return p; -} - -void uiDrawFreePath(uiDrawPath *p) -{ - if (p->inFigure) - p->sink->EndFigure(D2D1_FIGURE_END_OPEN); - if (p->sink != NULL) - // TODO close sink first? - p->sink->Release(); - p->path->Release(); - uiFree(p); -} - -void uiDrawPathNewFigure(uiDrawPath *p, double x, double y) -{ - D2D1_POINT_2F pt; - - if (p->inFigure) - p->sink->EndFigure(D2D1_FIGURE_END_OPEN); - pt.x = x; - pt.y = y; - p->sink->BeginFigure(pt, D2D1_FIGURE_BEGIN_FILLED); - p->inFigure = TRUE; -} - -// Direct2D arcs require a little explanation. -// An arc in Direct2D is defined by the chord between the endpoints. -// There are four possible arcs with the same two endpoints that you can draw this way. -// See https://www.youtube.com/watch?v=ATS0ANW1UxQ for a demonstration. -// There is a property rotationAngle which deals with the rotation /of the entire ellipse that forms an ellpitical arc/ - it's effectively a transformation on the arc. -// That is to say, it's NOT THE SWEEP. -// The sweep is defined by the start and end points and whether the arc is "large". -// As a result, this design does not allow for full circles or ellipses with a single arc; they have to be simulated with two. - -struct arc { - double xCenter; - double yCenter; - double radius; - double startAngle; - double sweep; - int negative; -}; - -// this is used for the comparison below -// if it falls apart it can be changed later -#define aerMax 6 * DBL_EPSILON - -static void drawArc(uiDrawPath *p, struct arc *a, void (*startFunction)(uiDrawPath *, double, double)) -{ - double sinx, cosx; - double startX, startY; - double endX, endY; - D2D1_ARC_SEGMENT as; - BOOL fullCircle; - double absSweep; - - // as above, we can't do a full circle with one arc - // simulate it with two half-circles - // of course, we have a dragon: equality on floating-point values! - // I've chosen to do the AlmostEqualRelative() technique in https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - fullCircle = FALSE; - // use the absolute value to tackle both ≥2Ï€ and ≤-2Ï€ at the same time - absSweep = fabs(a->sweep); - if (absSweep > (2 * uiPi)) // this part is easy - fullCircle = TRUE; - else { - double aerDiff; - - aerDiff = fabs(absSweep - (2 * uiPi)); - // if we got here then we know a->sweep is larger (or the same!) - fullCircle = aerDiff <= absSweep * aerMax; - } - // TODO make sure this works right for the negative direction - if (fullCircle) { - a->sweep = uiPi; - drawArc(p, a, startFunction); - a->startAngle += uiPi; - drawArc(p, a, NULL); - return; - } - - // first, figure out the arc's endpoints - // unfortunately D2D1SinCos() is only defined on Windows 8 and newer - // the MSDN page doesn't say this, but says it requires d2d1_1.h, which is listed as only supported on Windows 8 and newer elsewhere on MSDN - // so we must use sin() and cos() and hope it's right... - sinx = sin(a->startAngle); - cosx = cos(a->startAngle); - startX = a->xCenter + a->radius * cosx; - startY = a->yCenter + a->radius * sinx; - sinx = sin(a->startAngle + a->sweep); - cosx = cos(a->startAngle + a->sweep); - endX = a->xCenter + a->radius * cosx; - endY = a->yCenter + a->radius * sinx; - - // now do the initial step to get the current point to be the start point - // this is either creating a new figure, drawing a line, or (in the case of our full circle code above) doing nothing - if (startFunction != NULL) - (*startFunction)(p, startX, startY); - - // now we can draw the arc - as.point.x = endX; - as.point.y = endY; - as.size.width = a->radius; - as.size.height = a->radius; - as.rotationAngle = 0; // as above, not relevant for circles - if (a->negative) - as.sweepDirection = D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; - else - as.sweepDirection = D2D1_SWEEP_DIRECTION_CLOCKWISE; - // TODO explain the outer if - if (!a->negative) - if (a->sweep > uiPi) - as.arcSize = D2D1_ARC_SIZE_LARGE; - else - as.arcSize = D2D1_ARC_SIZE_SMALL; - else - // TODO especially this part - if (a->sweep > uiPi) - as.arcSize = D2D1_ARC_SIZE_SMALL; - else - as.arcSize = D2D1_ARC_SIZE_LARGE; - p->sink->AddArc(&as); -} - -void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) -{ - struct arc a; - - a.xCenter = xCenter; - a.yCenter = yCenter; - a.radius = radius; - a.startAngle = startAngle; - a.sweep = sweep; - a.negative = negative; - drawArc(p, &a, uiDrawPathNewFigure); -} - -void uiDrawPathLineTo(uiDrawPath *p, double x, double y) -{ - D2D1_POINT_2F pt; - - pt.x = x; - pt.y = y; - p->sink->AddLine(pt); -} - -void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative) -{ - struct arc a; - - a.xCenter = xCenter; - a.yCenter = yCenter; - a.radius = radius; - a.startAngle = startAngle; - a.sweep = sweep; - a.negative = negative; - drawArc(p, &a, uiDrawPathLineTo); -} - -void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY) -{ - D2D1_BEZIER_SEGMENT s; - - s.point1.x = c1x; - s.point1.y = c1y; - s.point2.x = c2x; - s.point2.y = c2y; - s.point3.x = endX; - s.point3.y = endY; - p->sink->AddBezier(&s); -} - -void uiDrawPathCloseFigure(uiDrawPath *p) -{ - p->sink->EndFigure(D2D1_FIGURE_END_CLOSED); - p->inFigure = FALSE; -} - -void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height) -{ - // this is the same algorithm used by cairo and Core Graphics, according to their documentations - uiDrawPathNewFigure(p, x, y); - uiDrawPathLineTo(p, x + width, y); - uiDrawPathLineTo(p, x + width, y + height); - uiDrawPathLineTo(p, x, y + height); - uiDrawPathCloseFigure(p); -} - -void uiDrawPathEnd(uiDrawPath *p) -{ - HRESULT hr; - - if (p->inFigure) { - p->sink->EndFigure(D2D1_FIGURE_END_OPEN); - // needed for uiDrawFreePath() - p->inFigure = FALSE; - } - hr = p->sink->Close(); - if (hr != S_OK) - logHRESULT(L"error closing path", hr); - p->sink->Release(); - // also needed for uiDrawFreePath() - p->sink = NULL; -} - -ID2D1PathGeometry *pathGeometry(uiDrawPath *p) -{ - if (p->sink != NULL) - userbug("You cannot draw with a uiDrawPath that was not ended. (path: %p)", p); - return p->path; -} diff --git a/src/libui_sdl/libui/windows/drawtext.cpp b/src/libui_sdl/libui/windows/drawtext.cpp deleted file mode 100644 index 05a24f67..00000000 --- a/src/libui_sdl/libui/windows/drawtext.cpp +++ /dev/null @@ -1,531 +0,0 @@ -// 22 december 2015 -#include "uipriv_windows.hpp" -#include "draw.hpp" -// TODO really migrate - -// notes: -// only available in windows 8 and newer: -// - character spacing -// - kerning control -// - justficiation (how could I possibly be making this up?!) -// - vertical text (SERIOUSLY?! WHAT THE ACTUAL FUCK, MICROSOFT?!?!?!? DID YOU NOT THINK ABOUT THIS THE FIRST TIME, TRYING TO IMPROVE THE INTERNATIONALIZATION OF WINDOWS 7?!?!?! bonus: some parts of MSDN even say 8.1 and up only!) - -struct uiDrawFontFamilies { - fontCollection *fc; -}; - -uiDrawFontFamilies *uiDrawListFontFamilies(void) -{ - struct uiDrawFontFamilies *ff; - - ff = uiNew(struct uiDrawFontFamilies); - ff->fc = loadFontCollection(); - return ff; -} - -int uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff) -{ - return ff->fc->fonts->GetFontFamilyCount(); -} - -char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, int n) -{ - IDWriteFontFamily *family; - WCHAR *wname; - char *name; - HRESULT hr; - - hr = ff->fc->fonts->GetFontFamily(n, &family); - if (hr != S_OK) - logHRESULT(L"error getting font out of collection", hr); - wname = fontCollectionFamilyName(ff->fc, family); - name = toUTF8(wname); - uiFree(wname); - family->Release(); - return name; -} - -void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff) -{ - fontCollectionFree(ff->fc); - uiFree(ff); -} - -struct uiDrawTextFont { - IDWriteFont *f; - WCHAR *family; // save for convenience in uiDrawNewTextLayout() - double size; -}; - -uiDrawTextFont *mkTextFont(IDWriteFont *df, BOOL addRef, WCHAR *family, BOOL copyFamily, double size) -{ - uiDrawTextFont *font; - WCHAR *copy; - HRESULT hr; - - font = uiNew(uiDrawTextFont); - font->f = df; - if (addRef) - font->f->AddRef(); - if (copyFamily) { - copy = (WCHAR *) uiAlloc((wcslen(family) + 1) * sizeof (WCHAR), "WCHAR[]"); - wcscpy(copy, family); - font->family = copy; - } else - font->family = family; - font->size = size; - return font; -} - -// TODO consider moving these all to dwrite.cpp - -// TODO MinGW-w64 is missing this one -#define DWRITE_FONT_WEIGHT_SEMI_LIGHT (DWRITE_FONT_WEIGHT(350)) -static const struct { - bool lastOne; - uiDrawTextWeight uival; - DWRITE_FONT_WEIGHT dwval; -} dwriteWeights[] = { - { false, uiDrawTextWeightThin, DWRITE_FONT_WEIGHT_THIN }, - { false, uiDrawTextWeightUltraLight, DWRITE_FONT_WEIGHT_ULTRA_LIGHT }, - { false, uiDrawTextWeightLight, DWRITE_FONT_WEIGHT_LIGHT }, - { false, uiDrawTextWeightBook, DWRITE_FONT_WEIGHT_SEMI_LIGHT }, - { false, uiDrawTextWeightNormal, DWRITE_FONT_WEIGHT_NORMAL }, - { false, uiDrawTextWeightMedium, DWRITE_FONT_WEIGHT_MEDIUM }, - { false, uiDrawTextWeightSemiBold, DWRITE_FONT_WEIGHT_SEMI_BOLD }, - { false, uiDrawTextWeightBold, DWRITE_FONT_WEIGHT_BOLD }, - { false, uiDrawTextWeightUltraBold, DWRITE_FONT_WEIGHT_ULTRA_BOLD }, - { false, uiDrawTextWeightHeavy, DWRITE_FONT_WEIGHT_HEAVY }, - { true, uiDrawTextWeightUltraHeavy, DWRITE_FONT_WEIGHT_ULTRA_BLACK, }, -}; - -static const struct { - bool lastOne; - uiDrawTextItalic uival; - DWRITE_FONT_STYLE dwval; -} dwriteItalics[] = { - { false, uiDrawTextItalicNormal, DWRITE_FONT_STYLE_NORMAL }, - { false, uiDrawTextItalicOblique, DWRITE_FONT_STYLE_OBLIQUE }, - { true, uiDrawTextItalicItalic, DWRITE_FONT_STYLE_ITALIC }, -}; - -static const struct { - bool lastOne; - uiDrawTextStretch uival; - DWRITE_FONT_STRETCH dwval; -} dwriteStretches[] = { - { false, uiDrawTextStretchUltraCondensed, DWRITE_FONT_STRETCH_ULTRA_CONDENSED }, - { false, uiDrawTextStretchExtraCondensed, DWRITE_FONT_STRETCH_EXTRA_CONDENSED }, - { false, uiDrawTextStretchCondensed, DWRITE_FONT_STRETCH_CONDENSED }, - { false, uiDrawTextStretchSemiCondensed, DWRITE_FONT_STRETCH_SEMI_CONDENSED }, - { false, uiDrawTextStretchNormal, DWRITE_FONT_STRETCH_NORMAL }, - { false, uiDrawTextStretchSemiExpanded, DWRITE_FONT_STRETCH_SEMI_EXPANDED }, - { false, uiDrawTextStretchExpanded, DWRITE_FONT_STRETCH_EXPANDED }, - { false, uiDrawTextStretchExtraExpanded, DWRITE_FONT_STRETCH_EXTRA_EXPANDED }, - { true, uiDrawTextStretchUltraExpanded, DWRITE_FONT_STRETCH_ULTRA_EXPANDED }, -}; - -void attrToDWriteAttr(struct dwriteAttr *attr) -{ - bool found; - int i; - - found = false; - for (i = 0; ; i++) { - if (dwriteWeights[i].uival == attr->weight) { - attr->dweight = dwriteWeights[i].dwval; - found = true; - break; - } - if (dwriteWeights[i].lastOne) - break; - } - if (!found) - userbug("Invalid text weight %d passed to text function.", attr->weight); - - found = false; - for (i = 0; ; i++) { - if (dwriteItalics[i].uival == attr->italic) { - attr->ditalic = dwriteItalics[i].dwval; - found = true; - break; - } - if (dwriteItalics[i].lastOne) - break; - } - if (!found) - userbug("Invalid text italic %d passed to text function.", attr->italic); - - found = false; - for (i = 0; ; i++) { - if (dwriteStretches[i].uival == attr->stretch) { - attr->dstretch = dwriteStretches[i].dwval; - found = true; - break; - } - if (dwriteStretches[i].lastOne) - break; - } - if (!found) - // TODO on other platforms too - userbug("Invalid text stretch %d passed to text function.", attr->stretch); -} - -void dwriteAttrToAttr(struct dwriteAttr *attr) -{ - int weight, against, n; - int curdiff, curindex; - bool found; - int i; - - // weight is scaled; we need to test to see what's nearest - weight = (int) (attr->dweight); - against = (int) (dwriteWeights[0].dwval); - curdiff = abs(against - weight); - curindex = 0; - for (i = 1; ; i++) { - against = (int) (dwriteWeights[i].dwval); - n = abs(against - weight); - if (n < curdiff) { - curdiff = n; - curindex = i; - } - if (dwriteWeights[i].lastOne) - break; - } - attr->weight = dwriteWeights[i].uival; - - // italic and stretch are simple values; we can just do a matching search - found = false; - for (i = 0; ; i++) { - if (dwriteItalics[i].dwval == attr->ditalic) { - attr->italic = dwriteItalics[i].uival; - found = true; - break; - } - if (dwriteItalics[i].lastOne) - break; - } - if (!found) - // these are implbug()s because users shouldn't be able to get here directly; TODO? - implbug("invalid italic %d passed to dwriteAttrToAttr()", attr->ditalic); - - found = false; - for (i = 0; ; i++) { - if (dwriteStretches[i].dwval == attr->dstretch) { - attr->stretch = dwriteStretches[i].uival; - found = true; - break; - } - if (dwriteStretches[i].lastOne) - break; - } - if (!found) - implbug("invalid stretch %d passed to dwriteAttrToAttr()", attr->dstretch); -} - -uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc) -{ - uiDrawTextFont *font; - IDWriteFontCollection *collection; - UINT32 index; - BOOL exists; - struct dwriteAttr attr; - IDWriteFontFamily *family; - WCHAR *wfamily; - IDWriteFont *match; - HRESULT hr; - - // always get the latest available font information - hr = dwfactory->GetSystemFontCollection(&collection, TRUE); - if (hr != S_OK) - logHRESULT(L"error getting system font collection", hr); - - wfamily = toUTF16(desc->Family); - hr = collection->FindFamilyName(wfamily, &index, &exists); - if (hr != S_OK) - logHRESULT(L"error finding font family", hr); - if (!exists) - implbug("LONGTERM family not found in uiDrawLoadClosestFont()", hr); - hr = collection->GetFontFamily(index, &family); - if (hr != S_OK) - logHRESULT(L"error loading font family", hr); - - attr.weight = desc->Weight; - attr.italic = desc->Italic; - attr.stretch = desc->Stretch; - attrToDWriteAttr(&attr); - hr = family->GetFirstMatchingFont( - attr.dweight, - attr.dstretch, - attr.ditalic, - &match); - if (hr != S_OK) - logHRESULT(L"error loading font", hr); - - font = mkTextFont(match, - FALSE, // we own the initial reference; no need to add another one - wfamily, FALSE, // will be freed with font - desc->Size); - - family->Release(); - collection->Release(); - - return font; -} - -void uiDrawFreeTextFont(uiDrawTextFont *font) -{ - font->f->Release(); - uiFree(font->family); - uiFree(font); -} - -uintptr_t uiDrawTextFontHandle(uiDrawTextFont *font) -{ - return (uintptr_t) (font->f); -} - -void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc) -{ - // TODO - - desc->Size = font->size; - - // TODO -} - -// text sizes are 1/72 of an inch -// points in Direct2D are 1/96 of an inch (https://msdn.microsoft.com/en-us/library/windows/desktop/ff684173%28v=vs.85%29.aspx, https://msdn.microsoft.com/en-us/library/windows/desktop/hh447022%28v=vs.85%29.aspx) -// As for the actual conversion from design units, see: -// - http://cboard.cprogramming.com/windows-programming/136733-directwrite-font-height-issues.html -// - https://sourceforge.net/p/vstgui/mailman/message/32483143/ -// - http://xboxforums.create.msdn.com/forums/t/109445.aspx -// - https://msdn.microsoft.com/en-us/library/dd183564%28v=vs.85%29.aspx -// - http://www.fontbureau.com/blog/the-em/ -// TODO make points here about how DIPs in DirectWrite == DIPs in Direct2D; if not, figure out what they really are? for the width and layout functions later -static double scaleUnits(double what, double designUnitsPerEm, double size) -{ - return (what / designUnitsPerEm) * (size * (96.0 / 72.0)); -} - -void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics) -{ - DWRITE_FONT_METRICS dm; - - font->f->GetMetrics(&dm); - metrics->Ascent = scaleUnits(dm.ascent, dm.designUnitsPerEm, font->size); - metrics->Descent = scaleUnits(dm.descent, dm.designUnitsPerEm, font->size); - // TODO what happens if dm.xxx is negative? - // TODO remember what this was for - metrics->Leading = scaleUnits(dm.lineGap, dm.designUnitsPerEm, font->size); - metrics->UnderlinePos = scaleUnits(dm.underlinePosition, dm.designUnitsPerEm, font->size); - metrics->UnderlineThickness = scaleUnits(dm.underlineThickness, dm.designUnitsPerEm, font->size); -} - -// some attributes, such as foreground color, can't be applied until after we establish a Direct2D context :/ so we have to prepare all attributes in advance -// also since there's no way to clear the attributes from a layout en masse (apart from overwriting them all), we'll play it safe by creating a new layout each time -enum layoutAttrType { - layoutAttrColor, -}; - -struct layoutAttr { - enum layoutAttrType type; - int start; - int end; - double components[4]; -}; - -struct uiDrawTextLayout { - WCHAR *text; - size_t textlen; - size_t *graphemes; - double width; - IDWriteTextFormat *format; - std::vector *attrs; -}; - -uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width) -{ - uiDrawTextLayout *layout; - HRESULT hr; - - layout = uiNew(uiDrawTextLayout); - - hr = dwfactory->CreateTextFormat(defaultFont->family, - NULL, - defaultFont->f->GetWeight(), - defaultFont->f->GetStyle(), - defaultFont->f->GetStretch(), - // typographic points are 1/72 inch; this parameter is 1/96 inch - // fortunately Microsoft does this too, in https://msdn.microsoft.com/en-us/library/windows/desktop/dd371554%28v=vs.85%29.aspx - defaultFont->size * (96.0 / 72.0), - // see http://stackoverflow.com/questions/28397971/idwritefactorycreatetextformat-failing and https://msdn.microsoft.com/en-us/library/windows/desktop/dd368203.aspx - // TODO use the current locale again? - L"", - &(layout->format)); - if (hr != S_OK) - logHRESULT(L"error creating IDWriteTextFormat", hr); - - layout->text = toUTF16(text); - layout->textlen = wcslen(layout->text); - layout->graphemes = graphemes(layout->text); - - uiDrawTextLayoutSetWidth(layout, width); - - layout->attrs = new std::vector; - - return layout; -} - -void uiDrawFreeTextLayout(uiDrawTextLayout *layout) -{ - delete layout->attrs; - layout->format->Release(); - uiFree(layout->graphemes); - uiFree(layout->text); - uiFree(layout); -} - -static ID2D1SolidColorBrush *mkSolidBrush(ID2D1RenderTarget *rt, double r, double g, double b, double a) -{ - D2D1_BRUSH_PROPERTIES props; - D2D1_COLOR_F color; - ID2D1SolidColorBrush *brush; - HRESULT hr; - - ZeroMemory(&props, sizeof (D2D1_BRUSH_PROPERTIES)); - props.opacity = 1.0; - // identity matrix - props.transform._11 = 1; - props.transform._22 = 1; - color.r = r; - color.g = g; - color.b = b; - color.a = a; - hr = rt->CreateSolidColorBrush( - &color, - &props, - &brush); - if (hr != S_OK) - logHRESULT(L"error creating solid brush", hr); - return brush; -} - -IDWriteTextLayout *prepareLayout(uiDrawTextLayout *layout, ID2D1RenderTarget *rt) -{ - IDWriteTextLayout *dl; - DWRITE_TEXT_RANGE range; - IUnknown *unkBrush; - DWRITE_WORD_WRAPPING wrap; - FLOAT maxWidth; - HRESULT hr; - - hr = dwfactory->CreateTextLayout(layout->text, layout->textlen, - layout->format, - // FLOAT is float, not double, so this should work... TODO - FLT_MAX, FLT_MAX, - &dl); - if (hr != S_OK) - logHRESULT(L"error creating IDWriteTextLayout", hr); - - for (const struct layoutAttr &attr : *(layout->attrs)) { - range.startPosition = layout->graphemes[attr.start]; - range.length = layout->graphemes[attr.end] - layout->graphemes[attr.start]; - switch (attr.type) { - case layoutAttrColor: - if (rt == NULL) // determining extents, not drawing - break; - unkBrush = mkSolidBrush(rt, - attr.components[0], - attr.components[1], - attr.components[2], - attr.components[3]); - hr = dl->SetDrawingEffect(unkBrush, range); - unkBrush->Release(); // associated with dl - break; - default: - hr = E_FAIL; - logHRESULT(L"invalid text attribute type", hr); - } - if (hr != S_OK) - logHRESULT(L"error adding attribute to text layout", hr); - } - - // and set the width - // this is the only wrapping mode (apart from "no wrap") available prior to Windows 8.1 - wrap = DWRITE_WORD_WRAPPING_WRAP; - maxWidth = layout->width; - if (layout->width < 0) { - wrap = DWRITE_WORD_WRAPPING_NO_WRAP; - // setting the max width in this case technically isn't needed since the wrap mode will simply ignore the max width, but let's do it just to be safe - maxWidth = FLT_MAX; // see TODO above - } - hr = dl->SetWordWrapping(wrap); - if (hr != S_OK) - logHRESULT(L"error setting word wrapping mode", hr); - hr = dl->SetMaxWidth(maxWidth); - if (hr != S_OK) - logHRESULT(L"error setting max layout width", hr); - - return dl; -} - - -void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width) -{ - layout->width = width; -} - -// TODO for a single line the height includes the leading; it should not -void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height) -{ - IDWriteTextLayout *dl; - DWRITE_TEXT_METRICS metrics; - HRESULT hr; - - dl = prepareLayout(layout, NULL); - hr = dl->GetMetrics(&metrics); - if (hr != S_OK) - logHRESULT(L"error getting layout metrics", hr); - *width = metrics.width; - // TODO make sure the behavior of this on empty strings is the same on all platforms - *height = metrics.height; - dl->Release(); -} - -void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout) -{ - IDWriteTextLayout *dl; - D2D1_POINT_2F pt; - ID2D1Brush *black; - HRESULT hr; - - // TODO document that fully opaque black is the default text color; figure out whether this is upheld in various scenarios on other platforms - black = mkSolidBrush(c->rt, 0.0, 0.0, 0.0, 1.0); - - dl = prepareLayout(layout, c->rt); - pt.x = x; - pt.y = y; - // TODO D2D1_DRAW_TEXT_OPTIONS_NO_SNAP? - // TODO D2D1_DRAW_TEXT_OPTIONS_CLIP? - // TODO when setting 8.1 as minimum, D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT? - c->rt->DrawTextLayout(pt, dl, black, D2D1_DRAW_TEXT_OPTIONS_NONE); - dl->Release(); - - black->Release(); -} - -void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar, int endChar, double r, double g, double b, double a) -{ - struct layoutAttr attr; - - attr.type = layoutAttrColor; - attr.start = startChar; - attr.end = endChar; - attr.components[0] = r; - attr.components[1] = g; - attr.components[2] = b; - attr.components[3] = a; - layout->attrs->push_back(attr); -} diff --git a/src/libui_sdl/libui/windows/dwrite.cpp b/src/libui_sdl/libui/windows/dwrite.cpp deleted file mode 100644 index 9156f179..00000000 --- a/src/libui_sdl/libui/windows/dwrite.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// 14 april 2016 -#include "uipriv_windows.hpp" -// TODO really migrate? - -IDWriteFactory *dwfactory = NULL; - -HRESULT initDrawText(void) -{ - // TOOD use DWRITE_FACTORY_TYPE_ISOLATED instead? - return DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof (IDWriteFactory), - (IUnknown **) (&dwfactory)); -} - -void uninitDrawText(void) -{ - dwfactory->Release(); -} - -fontCollection *loadFontCollection(void) -{ - fontCollection *fc; - HRESULT hr; - - fc = uiNew(fontCollection); - // always get the latest available font information - hr = dwfactory->GetSystemFontCollection(&(fc->fonts), TRUE); - if (hr != S_OK) - logHRESULT(L"error getting system font collection", hr); - fc->userLocaleSuccess = GetUserDefaultLocaleName(fc->userLocale, LOCALE_NAME_MAX_LENGTH); - return fc; -} - -WCHAR *fontCollectionFamilyName(fontCollection *fc, IDWriteFontFamily *family) -{ - IDWriteLocalizedStrings *names; - WCHAR *str; - HRESULT hr; - - hr = family->GetFamilyNames(&names); - if (hr != S_OK) - logHRESULT(L"error getting names of font out", hr); - str = fontCollectionCorrectString(fc, names); - names->Release(); - return str; -} - -WCHAR *fontCollectionCorrectString(fontCollection *fc, IDWriteLocalizedStrings *names) -{ - UINT32 index; - BOOL exists; - UINT32 length; - WCHAR *wname; - HRESULT hr; - - // this is complex, but we ignore failure conditions to allow fallbacks - // 1) If the user locale name was successfully retrieved, try it - // 2) If the user locale name was not successfully retrieved, or that locale's string does not exist, or an error occurred, try L"en-us", the US English locale - // 3) And if that fails, assume the first one - // This algorithm is straight from MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/dd368214%28v=vs.85%29.aspx - // For step 2 to work, start by setting hr to S_OK and exists to FALSE. - // TODO does it skip step 2 entirely if step 1 fails? rewrite it to be a more pure conversion of the MSDN code? - hr = S_OK; - exists = FALSE; - if (fc->userLocaleSuccess != 0) - hr = names->FindLocaleName(fc->userLocale, &index, &exists); - if (hr != S_OK || (hr == S_OK && !exists)) - hr = names->FindLocaleName(L"en-us", &index, &exists); - if (!exists) - index = 0; - - hr = names->GetStringLength(index, &length); - if (hr != S_OK) - logHRESULT(L"error getting length of font name", hr); - // GetStringLength() does not include the null terminator, but GetString() does - wname = (WCHAR *) uiAlloc((length + 1) * sizeof (WCHAR), "WCHAR[]"); - hr = names->GetString(index, wname, length + 1); - if (hr != S_OK) - logHRESULT(L"error getting font name", hr); - - return wname; -} - -void fontCollectionFree(fontCollection *fc) -{ - fc->fonts->Release(); - uiFree(fc); -} diff --git a/src/libui_sdl/libui/windows/editablecombo.cpp b/src/libui_sdl/libui/windows/editablecombo.cpp deleted file mode 100644 index 9e1fdbfb..00000000 --- a/src/libui_sdl/libui/windows/editablecombo.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.hpp" - -// we as Common Controls 6 users don't need to worry about the height of comboboxes; see http://blogs.msdn.com/b/oldnewthing/archive/2006/03/10/548537.aspx - -struct uiEditableCombobox { - uiWindowsControl c; - HWND hwnd; - void (*onChanged)(uiEditableCombobox *, void *); - void *onChangedData; -}; - -static BOOL onWM_COMMAND(uiControl *cc, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiEditableCombobox *c = uiEditableCombobox(cc); - - if (code == CBN_SELCHANGE) { - // like on OS X, this is sent before the edit has been updated :( - if (PostMessage(parentOf(hwnd), - WM_COMMAND, - MAKEWPARAM(GetWindowLongPtrW(hwnd, GWLP_ID), CBN_EDITCHANGE), - (LPARAM) hwnd) == 0) - logLastError(L"error posting CBN_EDITCHANGE after CBN_SELCHANGE"); - *lResult = 0; - return TRUE; - } - if (code != CBN_EDITCHANGE) - return FALSE; - (*(c->onChanged))(c, c->onChangedData); - *lResult = 0; - return TRUE; -} - -void uiEditableComboboxDestroy(uiControl *cc) -{ - uiEditableCombobox *c = uiEditableCombobox(cc); - - uiWindowsUnregisterWM_COMMANDHandler(c->hwnd); - uiWindowsEnsureDestroyWindow(c->hwnd); - uiFreeControl(uiControl(c)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiEditableCombobox) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define comboboxWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary; LONGTERM */ -#define comboboxHeight 14 /* LONGTERM: is this too high? */ - -static void uiEditableComboboxMinimumSize(uiWindowsControl *cc, int *width, int *height) -{ - uiEditableCombobox *c = uiEditableCombobox(cc); - uiWindowsSizing sizing; - int x, y; - - x = comboboxWidth; - y = comboboxHeight; - uiWindowsGetSizing(c->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -static void defaultOnChanged(uiEditableCombobox *c, void *data) -{ - // do nothing -} - -void uiEditableComboboxAppend(uiEditableCombobox *c, const char *text) -{ - WCHAR *wtext; - LRESULT res; - - wtext = toUTF16(text); - res = SendMessageW(c->hwnd, CB_ADDSTRING, 0, (LPARAM) wtext); - if (res == (LRESULT) CB_ERR) - logLastError(L"error appending item to uiEditableCombobox"); - else if (res == (LRESULT) CB_ERRSPACE) - logLastError(L"memory exhausted appending item to uiEditableCombobox"); - uiFree(wtext); -} - -char *uiEditableComboboxText(uiEditableCombobox *c) -{ - return uiWindowsWindowText(c->hwnd); -} - -void uiEditableComboboxSetText(uiEditableCombobox *c, const char *text) -{ - // does not trigger any notifications - uiWindowsSetWindowText(c->hwnd, text); -} - -void uiEditableComboboxOnChanged(uiEditableCombobox *c, void (*f)(uiEditableCombobox *c, void *data), void *data) -{ - c->onChanged = f; - c->onChangedData = data; -} - -uiEditableCombobox *uiNewEditableCombobox(void) -{ - uiEditableCombobox *c; - - uiWindowsNewControl(uiEditableCombobox, c); - - c->hwnd = uiWindowsEnsureCreateControlHWND(WS_EX_CLIENTEDGE, - L"combobox", L"", - CBS_DROPDOWN | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_COMMANDHandler(c->hwnd, onWM_COMMAND, uiControl(c)); - uiEditableComboboxOnChanged(c, defaultOnChanged, NULL); - - return c; -} diff --git a/src/libui_sdl/libui/windows/entry.cpp b/src/libui_sdl/libui/windows/entry.cpp deleted file mode 100644 index a7a077f2..00000000 --- a/src/libui_sdl/libui/windows/entry.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// 8 april 2015 -#include "uipriv_windows.hpp" - -struct uiEntry { - uiWindowsControl c; - HWND hwnd; - void (*onChanged)(uiEntry *, void *); - void *onChangedData; - BOOL inhibitChanged; -}; - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiEntry *e = uiEntry(c); - - if (code != EN_CHANGE) - return FALSE; - if (e->inhibitChanged) - return FALSE; - (*(e->onChanged))(e, e->onChangedData); - *lResult = 0; - return TRUE; -} - -static void uiEntryDestroy(uiControl *c) -{ - uiEntry *e = uiEntry(c); - - uiWindowsUnregisterWM_COMMANDHandler(e->hwnd); - uiWindowsEnsureDestroyWindow(e->hwnd); - uiFreeControl(uiControl(e)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiEntry) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define entryWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */ -#define entryHeight 14 - -static void uiEntryMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiEntry *e = uiEntry(c); - uiWindowsSizing sizing; - int x, y; - - x = entryWidth; - y = entryHeight; - uiWindowsGetSizing(e->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -static void defaultOnChanged(uiEntry *e, void *data) -{ - // do nothing -} - -char *uiEntryText(uiEntry *e) -{ - return uiWindowsWindowText(e->hwnd); -} - -void uiEntrySetText(uiEntry *e, const char *text) -{ - // doing this raises an EN_CHANGED - e->inhibitChanged = TRUE; - uiWindowsSetWindowText(e->hwnd, text); - e->inhibitChanged = FALSE; - // don't queue the control for resize; entry sizes are independent of their contents -} - -void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *, void *), void *data) -{ - e->onChanged = f; - e->onChangedData = data; -} - -int uiEntryReadOnly(uiEntry *e) -{ - return (getStyle(e->hwnd) & ES_READONLY) != 0; -} - -void uiEntrySetReadOnly(uiEntry *e, int readonly) -{ - WPARAM ro; - - ro = (WPARAM) FALSE; - if (readonly) - ro = (WPARAM) TRUE; - if (SendMessage(e->hwnd, EM_SETREADONLY, ro, 0) == 0) - logLastError(L"error making uiEntry read-only"); -} - -static uiEntry *finishNewEntry(DWORD style) -{ - uiEntry *e; - - uiWindowsNewControl(uiEntry, e); - - e->hwnd = uiWindowsEnsureCreateControlHWND(WS_EX_CLIENTEDGE, - L"edit", L"", - style | ES_AUTOHSCROLL | ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_COMMANDHandler(e->hwnd, onWM_COMMAND, uiControl(e)); - uiEntryOnChanged(e, defaultOnChanged, NULL); - - return e; -} - -uiEntry *uiNewEntry(void) -{ - return finishNewEntry(0); -} - -uiEntry *uiNewPasswordEntry(void) -{ - return finishNewEntry(ES_PASSWORD); -} - -uiEntry *uiNewSearchEntry(void) -{ - uiEntry *e; - HRESULT hr; - - e = finishNewEntry(0); - // TODO this is from ThemeExplorer; is it documented anywhere? - // TODO SearchBoxEditComposited has no border - hr = SetWindowTheme(e->hwnd, L"SearchBoxEdit", NULL); - // TODO will hr be S_OK if themes are disabled? - return e; -} diff --git a/src/libui_sdl/libui/windows/events.cpp b/src/libui_sdl/libui/windows/events.cpp deleted file mode 100644 index 45e8d43d..00000000 --- a/src/libui_sdl/libui/windows/events.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.hpp" - -struct handler { - BOOL (*commandHandler)(uiControl *, HWND, WORD, LRESULT *); - BOOL (*notifyHandler)(uiControl *, HWND, NMHDR *, LRESULT *); - BOOL (*hscrollHandler)(uiControl *, HWND, WORD, LRESULT *); - uiControl *c; - - // just to ensure handlers[new HWND] initializes properly - // TODO gcc can't handle a struct keyword here? or is that a MSVC extension? - handler() - { - this->commandHandler = NULL; - this->notifyHandler = NULL; - this->hscrollHandler = NULL; - this->c = NULL; - } -}; - -static std::map handlers; - -void uiWindowsRegisterWM_COMMANDHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *), uiControl *c) -{ - if (handlers[hwnd].commandHandler != NULL) - implbug("already registered a WM_COMMAND handler to window handle %p", hwnd); - handlers[hwnd].commandHandler = handler; - handlers[hwnd].c = c; -} - -void uiWindowsRegisterWM_NOTIFYHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, NMHDR *, LRESULT *), uiControl *c) -{ - if (handlers[hwnd].notifyHandler != NULL) - implbug("already registered a WM_NOTIFY handler to window handle %p", hwnd); - handlers[hwnd].notifyHandler = handler; - handlers[hwnd].c = c; -} - -void uiWindowsRegisterWM_HSCROLLHandler(HWND hwnd, BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *), uiControl *c) -{ - if (handlers[hwnd].hscrollHandler != NULL) - implbug("already registered a WM_HSCROLL handler to window handle %p", hwnd); - handlers[hwnd].hscrollHandler = handler; - handlers[hwnd].c = c; -} - -void uiWindowsUnregisterWM_COMMANDHandler(HWND hwnd) -{ - if (handlers[hwnd].commandHandler == NULL) - implbug("window handle %p not registered to receive WM_COMMAND events", hwnd); - handlers[hwnd].commandHandler = NULL; -} - -void uiWindowsUnregisterWM_NOTIFYHandler(HWND hwnd) -{ - if (handlers[hwnd].notifyHandler == NULL) - implbug("window handle %p not registered to receive WM_NOTIFY events", hwnd); - handlers[hwnd].notifyHandler = NULL; -} - -void uiWindowsUnregisterWM_HSCROLLHandler(HWND hwnd) -{ - if (handlers[hwnd].hscrollHandler == NULL) - implbug("window handle %p not registered to receive WM_HSCROLL events", hwnd); - handlers[hwnd].hscrollHandler = NULL; -} - -template -static BOOL shouldRun(HWND hwnd, T method) -{ - // not from a window - if (hwnd == NULL) - return FALSE; - // don't bounce back if to the utility window, in which case act as if the message was ignored - if (IsChild(utilWindow, hwnd) != 0) - return FALSE; - // registered? - return method != NULL; -} - -BOOL runWM_COMMAND(WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - HWND hwnd; - WORD arg3; - BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *); - uiControl *c; - - hwnd = (HWND) lParam; - arg3 = HIWORD(wParam); - handler = handlers[hwnd].commandHandler; - c = handlers[hwnd].c; - if (shouldRun(hwnd, handler)) - return (*handler)(c, hwnd, arg3, lResult); - return FALSE; -} - -BOOL runWM_NOTIFY(WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - HWND hwnd; - NMHDR *arg3; - BOOL (*handler)(uiControl *, HWND, NMHDR *, LRESULT *); - uiControl *c; - - arg3 = (NMHDR *) lParam; - hwnd = arg3->hwndFrom; - handler = handlers[hwnd].notifyHandler; - c = handlers[hwnd].c; - if (shouldRun(hwnd, handler)) - return (*handler)(c, hwnd, arg3, lResult); - return FALSE; -} - -BOOL runWM_HSCROLL(WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - HWND hwnd; - WORD arg3; - BOOL (*handler)(uiControl *, HWND, WORD, LRESULT *); - uiControl *c; - - hwnd = (HWND) lParam; - arg3 = LOWORD(wParam); - handler = handlers[hwnd].hscrollHandler; - c = handlers[hwnd].c; - if (shouldRun(hwnd, handler)) - return (*handler)(c, hwnd, arg3, lResult); - return FALSE; -} - -static std::map wininichanges; - -void uiWindowsRegisterReceiveWM_WININICHANGE(HWND hwnd) -{ - if (wininichanges[hwnd]) - implbug("window handle %p already subscribed to receive WM_WINICHANGEs", hwnd); - wininichanges[hwnd] = true; -} - -void uiWindowsUnregisterReceiveWM_WININICHANGE(HWND hwnd) -{ - if (!wininichanges[hwnd]) - implbug("window handle %p not registered to receive WM_WININICHANGEs", hwnd); - wininichanges[hwnd] = false; -} - -void issueWM_WININICHANGE(WPARAM wParam, LPARAM lParam) -{ - struct wininichange *ch; - - for (const auto &iter : wininichanges) - SendMessageW(iter.first, WM_WININICHANGE, wParam, lParam); -} diff --git a/src/libui_sdl/libui/windows/fontbutton.cpp b/src/libui_sdl/libui/windows/fontbutton.cpp deleted file mode 100644 index d2d4dabf..00000000 --- a/src/libui_sdl/libui/windows/fontbutton.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// 14 april 2016 -#include "uipriv_windows.hpp" - -struct uiFontButton { - uiWindowsControl c; - HWND hwnd; - struct fontDialogParams params; - BOOL already; - void (*onChanged)(uiFontButton *, void *); - void *onChangedData; -}; - -static void uiFontButtonDestroy(uiControl *c) -{ - uiFontButton *b = uiFontButton(c); - - uiWindowsUnregisterWM_COMMANDHandler(b->hwnd); - destroyFontDialogParams(&(b->params)); - uiWindowsEnsureDestroyWindow(b->hwnd); - uiFreeControl(uiControl(b)); -} - -static void updateFontButtonLabel(uiFontButton *b) -{ - WCHAR *text; - - text = fontDialogParamsToString(&(b->params)); - setWindowText(b->hwnd, text); - uiFree(text); - - // changing the text might necessitate a change in the button's size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(b)); -} - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiFontButton *b = uiFontButton(c); - HWND parent; - - if (code != BN_CLICKED) - return FALSE; - - parent = parentToplevel(b->hwnd); - if (showFontDialog(parent, &(b->params))) { - updateFontButtonLabel(b); - (*(b->onChanged))(b, b->onChangedData); - } - - *lResult = 0; - return TRUE; -} - -uiWindowsControlAllDefaultsExceptDestroy(uiFontButton) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define buttonHeight 14 - -static void uiFontButtonMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiFontButton *b = uiFontButton(c); - SIZE size; - uiWindowsSizing sizing; - int y; - - // try the comctl32 version 6 way - size.cx = 0; // explicitly ask for ideal size - size.cy = 0; - if (SendMessageW(b->hwnd, BCM_GETIDEALSIZE, 0, (LPARAM) (&size)) != FALSE) { - *width = size.cx; - *height = size.cy; - return; - } - - // that didn't work; fall back to using Microsoft's metrics - // Microsoft says to use a fixed width for all buttons; this isn't good enough - // use the text width instead, with some edge padding - *width = uiWindowsWindowTextWidth(b->hwnd) + (2 * GetSystemMetrics(SM_CXEDGE)); - y = buttonHeight; - uiWindowsGetSizing(b->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y); - *height = y; -} - -static void defaultOnChanged(uiFontButton *b, void *data) -{ - // do nothing -} - -uiDrawTextFont *uiFontButtonFont(uiFontButton *b) -{ - // we don't own b->params.font; we have to add a reference - // we don't own b->params.familyName either; we have to copy it - return mkTextFont(b->params.font, TRUE, b->params.familyName, TRUE, b->params.size); -} - -void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data) -{ - b->onChanged = f; - b->onChangedData = data; -} - -uiFontButton *uiNewFontButton(void) -{ - uiFontButton *b; - - uiWindowsNewControl(uiFontButton, b); - - b->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"button", L"you should not be seeing this", - BS_PUSHBUTTON | WS_TABSTOP, - hInstance, NULL, - TRUE); - - loadInitialFontDialogParams(&(b->params)); - - uiWindowsRegisterWM_COMMANDHandler(b->hwnd, onWM_COMMAND, uiControl(b)); - uiFontButtonOnChanged(b, defaultOnChanged, NULL); - - updateFontButtonLabel(b); - - return b; -} diff --git a/src/libui_sdl/libui/windows/fontdialog.cpp b/src/libui_sdl/libui/windows/fontdialog.cpp deleted file mode 100644 index 603a17db..00000000 --- a/src/libui_sdl/libui/windows/fontdialog.cpp +++ /dev/null @@ -1,686 +0,0 @@ -// 14 april 2016 -#include "uipriv_windows.hpp" - -// TODOs -// - quote the Choose Font sample here for reference -// - the Choose Font sample defaults to Regular/Italic/Bold/Bold Italic in some case (no styles?); do we? find out what the case is -// - do we set initial family and style topmost as well? -// - this should probably just handle IDWriteFonts - -struct fontDialog { - HWND hwnd; - HWND familyCombobox; - HWND styleCombobox; - HWND sizeCombobox; - - struct fontDialogParams *params; - - fontCollection *fc; - - RECT sampleRect; - HWND sampleBox; - - // we store the current selections in case an invalid string is typed in (partial or nonexistent or invalid number) - // on OK, these are what are read - LRESULT curFamily; - LRESULT curStyle; - double curSize; - - // these are finding the style that's closest to the previous one (these fields) when changing a font - DWRITE_FONT_WEIGHT weight; - DWRITE_FONT_STYLE style; - DWRITE_FONT_STRETCH stretch; -}; - -static LRESULT cbAddString(HWND cb, const WCHAR *str) -{ - LRESULT lr; - - lr = SendMessageW(cb, CB_ADDSTRING, 0, (LPARAM) str); - if (lr == (LRESULT) CB_ERR || lr == (LRESULT) CB_ERRSPACE) - logLastError(L"error adding item to combobox"); - return lr; -} - -static LRESULT cbInsertString(HWND cb, const WCHAR *str, WPARAM pos) -{ - LRESULT lr; - - lr = SendMessageW(cb, CB_INSERTSTRING, pos, (LPARAM) str); - if (lr != (LRESULT) pos) - logLastError(L"error inserting item to combobox"); - return lr; -} - -static LRESULT cbGetItemData(HWND cb, WPARAM item) -{ - LRESULT data; - - data = SendMessageW(cb, CB_GETITEMDATA, item, 0); - if (data == (LRESULT) CB_ERR) - logLastError(L"error getting combobox item data for font dialog"); - return data; -} - -static void cbSetItemData(HWND cb, WPARAM item, LPARAM data) -{ - if (SendMessageW(cb, CB_SETITEMDATA, item, data) == (LRESULT) CB_ERR) - logLastError(L"error setting combobox item data"); -} - -static BOOL cbGetCurSel(HWND cb, LRESULT *sel) -{ - LRESULT n; - - n = SendMessageW(cb, CB_GETCURSEL, 0, 0); - if (n == (LRESULT) CB_ERR) - return FALSE; - if (sel != NULL) - *sel = n; - return TRUE; -} - -static void cbSetCurSel(HWND cb, WPARAM item) -{ - if (SendMessageW(cb, CB_SETCURSEL, item, 0) != (LRESULT) item) - logLastError(L"error selecting combobox item"); -} - -static LRESULT cbGetCount(HWND cb) -{ - LRESULT n; - - n = SendMessageW(cb, CB_GETCOUNT, 0, 0); - if (n == (LRESULT) CB_ERR) - logLastError(L"error getting combobox item count"); - return n; -} - -static void cbWipeAndReleaseData(HWND cb) -{ - IUnknown *obj; - LRESULT i, n; - - n = cbGetCount(cb); - for (i = 0; i < n; i++) { - obj = (IUnknown *) cbGetItemData(cb, (WPARAM) i); - obj->Release(); - } - SendMessageW(cb, CB_RESETCONTENT, 0, 0); -} - -static WCHAR *cbGetItemText(HWND cb, WPARAM item) -{ - LRESULT len; - WCHAR *text; - - // note: neither message includes the terminating L'\0' - len = SendMessageW(cb, CB_GETLBTEXTLEN, item, 0); - if (len == (LRESULT) CB_ERR) - logLastError(L"error getting item text length from combobox"); - text = (WCHAR *) uiAlloc((len + 1) * sizeof (WCHAR), "WCHAR[]"); - if (SendMessageW(cb, CB_GETLBTEXT, item, (LPARAM) text) != len) - logLastError(L"error getting item text from combobox"); - return text; -} - -static BOOL cbTypeToSelect(HWND cb, LRESULT *posOut, BOOL restoreAfter) -{ - WCHAR *text; - LRESULT pos; - DWORD selStart, selEnd; - - // start by saving the current selection as setting the item will change the selection - SendMessageW(cb, CB_GETEDITSEL, (WPARAM) (&selStart), (LPARAM) (&selEnd)); - text = windowText(cb); - pos = SendMessageW(cb, CB_FINDSTRINGEXACT, (WPARAM) (-1), (LPARAM) text); - if (pos == (LRESULT) CB_ERR) { - uiFree(text); - return FALSE; - } - cbSetCurSel(cb, (WPARAM) pos); - if (posOut != NULL) - *posOut = pos; - if (restoreAfter) - if (SendMessageW(cb, WM_SETTEXT, 0, (LPARAM) text) != (LRESULT) TRUE) - logLastError(L"error restoring old combobox text"); - uiFree(text); - // and restore the selection like above - // TODO isn't there a 32-bit version of this - if (SendMessageW(cb, CB_SETEDITSEL, 0, MAKELPARAM(selStart, selEnd)) != (LRESULT) TRUE) - logLastError(L"error restoring combobox edit selection"); - return TRUE; -} - -static void wipeStylesBox(struct fontDialog *f) -{ - cbWipeAndReleaseData(f->styleCombobox); -} - -static WCHAR *fontStyleName(struct fontCollection *fc, IDWriteFont *font) -{ - IDWriteLocalizedStrings *str; - WCHAR *wstr; - HRESULT hr; - - hr = font->GetFaceNames(&str); - if (hr != S_OK) - logHRESULT(L"error getting font style name for font dialog", hr); - wstr = fontCollectionCorrectString(fc, str); - str->Release(); - return wstr; -} - -static void queueRedrawSampleText(struct fontDialog *f) -{ - // TODO TRUE? - invalidateRect(f->sampleBox, NULL, TRUE); -} - -static void styleChanged(struct fontDialog *f) -{ - LRESULT pos; - BOOL selected; - IDWriteFont *font; - - selected = cbGetCurSel(f->styleCombobox, &pos); - if (!selected) // on deselect, do nothing - return; - f->curStyle = pos; - - font = (IDWriteFont *) cbGetItemData(f->styleCombobox, (WPARAM) (f->curStyle)); - // these are for the nearest match when changing the family; see below - f->weight = font->GetWeight(); - f->style = font->GetStyle(); - f->stretch = font->GetStretch(); - - queueRedrawSampleText(f); -} - -static void styleEdited(struct fontDialog *f) -{ - if (cbTypeToSelect(f->styleCombobox, &(f->curStyle), FALSE)) - styleChanged(f); -} - -static void familyChanged(struct fontDialog *f) -{ - LRESULT pos; - BOOL selected; - IDWriteFontFamily *family; - IDWriteFont *font, *matchFont; - DWRITE_FONT_WEIGHT weight; - DWRITE_FONT_STYLE style; - DWRITE_FONT_STRETCH stretch; - UINT32 i, n; - UINT32 matching; - WCHAR *label; - HRESULT hr; - - selected = cbGetCurSel(f->familyCombobox, &pos); - if (!selected) // on deselect, do nothing - return; - f->curFamily = pos; - - family = (IDWriteFontFamily *) cbGetItemData(f->familyCombobox, (WPARAM) (f->curFamily)); - - // for the nearest style match - // when we select a new family, we want the nearest style to the previously selected one to be chosen - // this is how the Choose Font sample does it - hr = family->GetFirstMatchingFont( - f->weight, - f->stretch, - f->style, - &matchFont); - if (hr != S_OK) - logHRESULT(L"error finding first matching font to previous style in font dialog", hr); - // we can't just compare pointers; a "newly created" object comes out - // the Choose Font sample appears to do this instead - weight = matchFont->GetWeight(); - style = matchFont->GetStyle(); - stretch = matchFont->GetStretch(); - matchFont->Release(); - - // TODO test mutliple streteches; all the fonts I have have only one stretch value? - wipeStylesBox(f); - n = family->GetFontCount(); - matching = 0; // a safe/suitable default just in case - for (i = 0; i < n; i++) { - hr = family->GetFont(i, &font); - if (hr != S_OK) - logHRESULT(L"error getting font for filling styles box", hr); - label = fontStyleName(f->fc, font); - pos = cbAddString(f->styleCombobox, label); - uiFree(label); - cbSetItemData(f->styleCombobox, (WPARAM) pos, (LPARAM) font); - if (font->GetWeight() == weight && - font->GetStyle() == style && - font->GetStretch() == stretch) - matching = i; - } - - // and now, load the match - cbSetCurSel(f->styleCombobox, (WPARAM) matching); - styleChanged(f); -} - -// TODO search language variants like the sample does -static void familyEdited(struct fontDialog *f) -{ - if (cbTypeToSelect(f->familyCombobox, &(f->curFamily), FALSE)) - familyChanged(f); -} - -static const struct { - const WCHAR *text; - double value; -} defaultSizes[] = { - { L"8", 8 }, - { L"9", 9 }, - { L"10", 10 }, - { L"11", 11 }, - { L"12", 12 }, - { L"14", 14 }, - { L"16", 16 }, - { L"18", 18 }, - { L"20", 20 }, - { L"22", 22 }, - { L"24", 24 }, - { L"26", 26 }, - { L"28", 28 }, - { L"36", 36 }, - { L"48", 48 }, - { L"72", 72 }, - { NULL, 0 }, -}; - -static void sizeChanged(struct fontDialog *f) -{ - LRESULT pos; - BOOL selected; - - selected = cbGetCurSel(f->sizeCombobox, &pos); - if (!selected) // on deselect, do nothing - return; - f->curSize = defaultSizes[pos].value; - queueRedrawSampleText(f); -} - -static void sizeEdited(struct fontDialog *f) -{ - WCHAR *wsize; - double size; - - // handle type-to-selection - if (cbTypeToSelect(f->sizeCombobox, NULL, FALSE)) { - sizeChanged(f); - return; - } - // selection not chosen, try to parse the typing - wsize = windowText(f->sizeCombobox); - // this is what the Choose Font dialog does; it swallows errors while the real ChooseFont() is not lenient (and only checks on OK) - size = wcstod(wsize, NULL); - if (size <= 0) // don't change on invalid size - return; - f->curSize = size; - queueRedrawSampleText(f); -} - -static void fontDialogDrawSampleText(struct fontDialog *f, ID2D1RenderTarget *rt) -{ - D2D1_COLOR_F color; - D2D1_BRUSH_PROPERTIES props; - ID2D1SolidColorBrush *black; - IDWriteFont *font; - IDWriteLocalizedStrings *sampleStrings; - BOOL exists; - WCHAR *sample; - WCHAR *family; - IDWriteTextFormat *format; - D2D1_RECT_F rect; - HRESULT hr; - - color.r = 0.0; - color.g = 0.0; - color.b = 0.0; - color.a = 1.0; - ZeroMemory(&props, sizeof (D2D1_BRUSH_PROPERTIES)); - props.opacity = 1.0; - // identity matrix - props.transform._11 = 1; - props.transform._22 = 1; - hr = rt->CreateSolidColorBrush( - &color, - &props, - &black); - if (hr != S_OK) - logHRESULT(L"error creating solid brush", hr); - - font = (IDWriteFont *) cbGetItemData(f->styleCombobox, (WPARAM) f->curStyle); - hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT, &sampleStrings, &exists); - if (hr != S_OK) - exists = FALSE; - if (exists) { - sample = fontCollectionCorrectString(f->fc, sampleStrings); - sampleStrings->Release(); - } else - sample = L"The quick brown fox jumps over the lazy dog."; - - // DirectWrite doesn't allow creating a text format from a font; we need to get this ourselves - family = cbGetItemText(f->familyCombobox, f->curFamily); - hr = dwfactory->CreateTextFormat(family, - NULL, - font->GetWeight(), - font->GetStyle(), - font->GetStretch(), - // typographic points are 1/72 inch; this parameter is 1/96 inch - // fortunately Microsoft does this too, in https://msdn.microsoft.com/en-us/library/windows/desktop/dd371554%28v=vs.85%29.aspx - f->curSize * (96.0 / 72.0), - // see http://stackoverflow.com/questions/28397971/idwritefactorycreatetextformat-failing and https://msdn.microsoft.com/en-us/library/windows/desktop/dd368203.aspx - // TODO use the current locale again? - L"", - &format); - if (hr != S_OK) - logHRESULT(L"error creating IDWriteTextFormat", hr); - uiFree(family); - - rect.left = 0; - rect.top = 0; - rect.right = realGetSize(rt).width; - rect.bottom = realGetSize(rt).height; - rt->DrawText(sample, wcslen(sample), - format, - &rect, - black, - // TODO really? - D2D1_DRAW_TEXT_OPTIONS_NONE, - DWRITE_MEASURING_MODE_NATURAL); - - format->Release(); - if (exists) - uiFree(sample); - black->Release(); -} - -static LRESULT CALLBACK fontDialogSampleSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - ID2D1RenderTarget *rt; - struct fontDialog *f; - - switch (uMsg) { - case msgD2DScratchPaint: - rt = (ID2D1RenderTarget *) lParam; - f = (struct fontDialog *) dwRefData; - fontDialogDrawSampleText(f, rt); - return 0; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, fontDialogSampleSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing font dialog sample text subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -static void setupInitialFontDialogState(struct fontDialog *f) -{ - WCHAR wsize[512]; // this should be way more than enough - LRESULT pos; - - // first let's load the size - // the real font dialog: - // - if the chosen font size is in the list, it selects that item AND makes it topmost - // - if the chosen font size is not in the list, don't bother - // we'll simulate it by setting the text to a %f representation, then pretending as if it was entered - // TODO is 512 the correct number to pass to _snwprintf()? - // TODO will this revert to scientific notation? - _snwprintf(wsize, 512, L"%g", f->params->size); - // TODO make this a setWindowText() - if (SendMessageW(f->sizeCombobox, WM_SETTEXT, 0, (LPARAM) wsize) != (LRESULT) TRUE) - logLastError(L"error setting size combobox to initial font size"); - sizeEdited(f); - if (cbGetCurSel(f->sizeCombobox, &pos)) - if (SendMessageW(f->sizeCombobox, CB_SETTOPINDEX, (WPARAM) pos, 0) != 0) - logLastError(L"error making chosen size topmost in the size combobox"); - - // now we set the family and style - // we do this by first setting the previous style attributes, then simulating a font entered - f->weight = f->params->font->GetWeight(); - f->style = f->params->font->GetStyle(); - f->stretch = f->params->font->GetStretch(); - if (SendMessageW(f->familyCombobox, WM_SETTEXT, 0, (LPARAM) (f->params->familyName)) != (LRESULT) TRUE) - logLastError(L"error setting family combobox to initial font family"); - familyEdited(f); -} - -static struct fontDialog *beginFontDialog(HWND hwnd, LPARAM lParam) -{ - struct fontDialog *f; - UINT32 i, nFamilies; - IDWriteFontFamily *family; - WCHAR *wname; - LRESULT pos; - HWND samplePlacement; - HRESULT hr; - - f = uiNew(struct fontDialog); - f->hwnd = hwnd; - f->params = (struct fontDialogParams *) lParam; - - f->familyCombobox = getDlgItem(f->hwnd, rcFontFamilyCombobox); - f->styleCombobox = getDlgItem(f->hwnd, rcFontStyleCombobox); - f->sizeCombobox = getDlgItem(f->hwnd, rcFontSizeCombobox); - - f->fc = loadFontCollection(); - nFamilies = f->fc->fonts->GetFontFamilyCount(); - for (i = 0; i < nFamilies; i++) { - hr = f->fc->fonts->GetFontFamily(i, &family); - if (hr != S_OK) - logHRESULT(L"error getting font family", hr); - wname = fontCollectionFamilyName(f->fc, family); - pos = cbAddString(f->familyCombobox, wname); - uiFree(wname); - cbSetItemData(f->familyCombobox, (WPARAM) pos, (LPARAM) family); - } - - for (i = 0; defaultSizes[i].text != NULL; i++) - cbInsertString(f->sizeCombobox, defaultSizes[i].text, (WPARAM) i); - - samplePlacement = getDlgItem(f->hwnd, rcFontSamplePlacement); - uiWindowsEnsureGetWindowRect(samplePlacement, &(f->sampleRect)); - mapWindowRect(NULL, f->hwnd, &(f->sampleRect)); - uiWindowsEnsureDestroyWindow(samplePlacement); - f->sampleBox = newD2DScratch(f->hwnd, &(f->sampleRect), (HMENU) rcFontSamplePlacement, fontDialogSampleSubProc, (DWORD_PTR) f); - - setupInitialFontDialogState(f); - return f; -} - -static void endFontDialog(struct fontDialog *f, INT_PTR code) -{ - wipeStylesBox(f); - cbWipeAndReleaseData(f->familyCombobox); - fontCollectionFree(f->fc); - if (EndDialog(f->hwnd, code) == 0) - logLastError(L"error ending font dialog"); - uiFree(f); -} - -static INT_PTR tryFinishDialog(struct fontDialog *f, WPARAM wParam) -{ - IDWriteFontFamily *family; - - // cancelling - if (LOWORD(wParam) != IDOK) { - endFontDialog(f, 1); - return TRUE; - } - - // OK - destroyFontDialogParams(f->params); - f->params->font = (IDWriteFont *) cbGetItemData(f->styleCombobox, f->curStyle); - // we need to save font from being destroyed with the combobox - f->params->font->AddRef(); - f->params->size = f->curSize; - family = (IDWriteFontFamily *) cbGetItemData(f->familyCombobox, f->curFamily); - f->params->familyName = fontCollectionFamilyName(f->fc, family); - f->params->styleName = fontStyleName(f->fc, f->params->font); - endFontDialog(f, 2); - return TRUE; -} - -static INT_PTR CALLBACK fontDialogDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - struct fontDialog *f; - - f = (struct fontDialog *) GetWindowLongPtrW(hwnd, DWLP_USER); - if (f == NULL) { - if (uMsg == WM_INITDIALOG) { - f = beginFontDialog(hwnd, lParam); - SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR) f); - return TRUE; - } - return FALSE; - } - - switch (uMsg) { - case WM_COMMAND: - SetWindowLongPtrW(f->hwnd, DWLP_MSGRESULT, 0); // just in case - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - if (HIWORD(wParam) != BN_CLICKED) - return FALSE; - return tryFinishDialog(f, wParam); - case rcFontFamilyCombobox: - if (HIWORD(wParam) == CBN_SELCHANGE) { - familyChanged(f); - return TRUE; - } - if (HIWORD(wParam) == CBN_EDITCHANGE) { - familyEdited(f); - return TRUE; - } - return FALSE; - case rcFontStyleCombobox: - if (HIWORD(wParam) == CBN_SELCHANGE) { - styleChanged(f); - return TRUE; - } - if (HIWORD(wParam) == CBN_EDITCHANGE) { - styleEdited(f); - return TRUE; - } - return FALSE; - case rcFontSizeCombobox: - if (HIWORD(wParam) == CBN_SELCHANGE) { - sizeChanged(f); - return TRUE; - } - if (HIWORD(wParam) == CBN_EDITCHANGE) { - sizeEdited(f); - return TRUE; - } - return FALSE; - } - return FALSE; - } - return FALSE; -} - -BOOL showFontDialog(HWND parent, struct fontDialogParams *params) -{ - switch (DialogBoxParamW(hInstance, MAKEINTRESOURCE(rcFontDialog), parent, fontDialogDlgProc, (LPARAM) params)) { - case 1: // cancel - return FALSE; - case 2: // ok - // make the compiler happy by putting the return after the switch - break; - default: - logLastError(L"error running font dialog"); - } - return TRUE; -} - -static IDWriteFontFamily *tryFindFamily(IDWriteFontCollection *fc, const WCHAR *name) -{ - UINT32 index; - BOOL exists; - IDWriteFontFamily *family; - HRESULT hr; - - hr = fc->FindFamilyName(name, &index, &exists); - if (hr != S_OK) - logHRESULT(L"error finding font family for font dialog", hr); - if (!exists) - return NULL; - hr = fc->GetFontFamily(index, &family); - if (hr != S_OK) - logHRESULT(L"error extracting found font family for font dialog", hr); - return family; -} - -void loadInitialFontDialogParams(struct fontDialogParams *params) -{ - struct fontCollection *fc; - IDWriteFontFamily *family; - IDWriteFont *font; - HRESULT hr; - - // Our preferred font is Arial 10 Regular. - // 10 comes from the official font dialog. - // Arial Regular is a reasonable, if arbitrary, default; it's similar to the defaults on other systems. - // If Arial isn't found, we'll use Helvetica and then MS Sans Serif as fallbacks, and if not, we'll just grab the first font family in the collection. - - // We need the correct localized name for Regular (and possibly Arial too? let's say yes to be safe), so let's grab the strings from DirectWrite instead of hardcoding them. - fc = loadFontCollection(); - family = tryFindFamily(fc->fonts, L"Arial"); - if (family == NULL) { - family = tryFindFamily(fc->fonts, L"Helvetica"); - if (family == NULL) { - family = tryFindFamily(fc->fonts, L"MS Sans Serif"); - if (family == NULL) { - hr = fc->fonts->GetFontFamily(0, &family); - if (hr != S_OK) - logHRESULT(L"error getting first font out of font collection (worst case scenario)", hr); - } - } - } - - // next part is simple: just get the closest match to regular - hr = family->GetFirstMatchingFont( - DWRITE_FONT_WEIGHT_NORMAL, - DWRITE_FONT_STRETCH_NORMAL, - DWRITE_FONT_STYLE_NORMAL, - &font); - if (hr != S_OK) - logHRESULT(L"error getting Regular font from Arial", hr); - - params->font = font; - params->size = 10; - params->familyName = fontCollectionFamilyName(fc, family); - params->styleName = fontStyleName(fc, font); - - // don't release font; we still need it - family->Release(); - fontCollectionFree(fc); -} - -void destroyFontDialogParams(struct fontDialogParams *params) -{ - params->font->Release(); - uiFree(params->familyName); - uiFree(params->styleName); -} - -WCHAR *fontDialogParamsToString(struct fontDialogParams *params) -{ - WCHAR *text; - - // TODO dynamically allocate - text = (WCHAR *) uiAlloc(512 * sizeof (WCHAR), "WCHAR[]"); - _snwprintf(text, 512, L"%s %s %g", - params->familyName, - params->styleName, - params->size); - return text; -} diff --git a/src/libui_sdl/libui/windows/form.cpp b/src/libui_sdl/libui/windows/form.cpp deleted file mode 100644 index 65ef5390..00000000 --- a/src/libui_sdl/libui/windows/form.cpp +++ /dev/null @@ -1,326 +0,0 @@ -// 8 june 2016 -#include "uipriv_windows.hpp" - -struct formChild { - uiControl *c; - HWND label; - int stretchy; - int height; -}; - -struct uiForm { - uiWindowsControl c; - HWND hwnd; - std::vector *controls; - int padded; -}; - -static void formPadding(uiForm *f, int *xpadding, int *ypadding) -{ - uiWindowsSizing sizing; - - *xpadding = 0; - *ypadding = 0; - if (f->padded) { - uiWindowsGetSizing(f->hwnd, &sizing); - uiWindowsSizingStandardPadding(&sizing, xpadding, ypadding); - } -} - -// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define labelHeight 8 -#define labelYOffset 3 - -static void formRelayout(uiForm *f) -{ - RECT r; - int x, y, width, height; - int xpadding, ypadding; - int nStretchy; - int labelwid, stretchyht; - int thiswid; - int i; - int minimumWidth, minimumHeight; - uiWindowsSizing sizing; - int labelht, labelyoff; - int nVisible; - - if (f->controls->size() == 0) - return; - - uiWindowsEnsureGetClientRect(f->hwnd, &r); - x = r.left; - y = r.top; - width = r.right - r.left; - height = r.bottom - r.top; - - // 0) get this Form's padding - formPadding(f, &xpadding, &ypadding); - - // 1) get width of labels and height of non-stretchy controls - // this will tell us how much space will be left for controls - labelwid = 0; - stretchyht = height; - nStretchy = 0; - nVisible = 0; - for (struct formChild &fc : *(f->controls)) { - if (!uiControlVisible(fc.c)) { - ShowWindow(fc.label, SW_HIDE); - continue; - } - ShowWindow(fc.label, SW_SHOW); - nVisible++; - thiswid = uiWindowsWindowTextWidth(fc.label); - if (labelwid < thiswid) - labelwid = thiswid; - if (fc.stretchy) { - nStretchy++; - continue; - } - uiWindowsControlMinimumSize(uiWindowsControl(fc.c), &minimumWidth, &minimumHeight); - fc.height = minimumHeight; - stretchyht -= minimumHeight; - } - if (nVisible == 0) // nothing to do - return; - - // 2) inset the available rect by the needed padding - width -= xpadding; - height -= (nVisible - 1) * ypadding; - stretchyht -= (nVisible - 1) * ypadding; - - // 3) now get the width of controls and the height of stretchy controls - width -= labelwid; - if (nStretchy != 0) { - stretchyht /= nStretchy; - for (struct formChild &fc : *(f->controls)) { - if (!uiControlVisible(fc.c)) - continue; - if (fc.stretchy) - fc.height = stretchyht; - } - } - - // 4) get the y offset - labelyoff = labelYOffset; - uiWindowsGetSizing(f->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &labelyoff); - - // 5) now we can position controls - // first, make relative to the top-left corner of the container - // also prefer left alignment on Windows - x = labelwid + xpadding; - y = 0; - for (const struct formChild &fc : *(f->controls)) { - if (!uiControlVisible(fc.c)) - continue; - labelht = labelHeight; - uiWindowsGetSizing(f->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &labelht); - uiWindowsEnsureMoveWindowDuringResize(fc.label, 0, y + labelyoff - sizing.InternalLeading, labelwid, labelht); - uiWindowsEnsureMoveWindowDuringResize((HWND) uiControlHandle(fc.c), x, y, width, fc.height); - y += fc.height + ypadding; - } -} - -static void uiFormDestroy(uiControl *c) -{ - uiForm *f = uiForm(c); - - for (const struct formChild &fc : *(f->controls)) { - uiControlSetParent(fc.c, NULL); - uiControlDestroy(fc.c); - uiWindowsEnsureDestroyWindow(fc.label); - } - delete f->controls; - uiWindowsEnsureDestroyWindow(f->hwnd); - uiFreeControl(uiControl(f)); -} - -uiWindowsControlDefaultHandle(uiForm) -uiWindowsControlDefaultParent(uiForm) -uiWindowsControlDefaultSetParent(uiForm) -uiWindowsControlDefaultToplevel(uiForm) -uiWindowsControlDefaultVisible(uiForm) -uiWindowsControlDefaultShow(uiForm) -uiWindowsControlDefaultHide(uiForm) -uiWindowsControlDefaultEnabled(uiForm) -uiWindowsControlDefaultEnable(uiForm) -uiWindowsControlDefaultDisable(uiForm) -uiWindowsControlDefaultSetFocus(uiForm) - -static void uiFormSyncEnableState(uiWindowsControl *c, int enabled) -{ - uiForm *f = uiForm(c); - - if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(f), enabled)) - return; - for (const struct formChild &fc : *(f->controls)) - uiWindowsControlSyncEnableState(uiWindowsControl(fc.c), enabled); -} - -uiWindowsControlDefaultSetParentHWND(uiForm) - -static void uiFormMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiForm *f = uiForm(c); - int xpadding, ypadding; - int nStretchy; - // these two contain the largest minimum width and height of all stretchy controls in the form - // all stretchy controls will use this value to determine the final minimum size - int maxLabelWidth, maxControlWidth; - int maxStretchyHeight; - int labelwid; - int i; - int minimumWidth, minimumHeight; - int nVisible; - uiWindowsSizing sizing; - - *width = 0; - *height = 0; - if (f->controls->size() == 0) - return; - - // 0) get this Form's padding - formPadding(f, &xpadding, &ypadding); - - // 1) determine the longest width of all controls and labels; add in the height of non-stretchy controls and get (but not add in) the largest heights of stretchy controls - // we still add in like direction of stretchy controls - nStretchy = 0; - maxLabelWidth = 0; - maxControlWidth = 0; - maxStretchyHeight = 0; - nVisible = 0; - for (const struct formChild &fc : *(f->controls)) { - if (!uiControlVisible(fc.c)) - continue; - nVisible++; - labelwid = uiWindowsWindowTextWidth(fc.label); - if (maxLabelWidth < labelwid) - maxLabelWidth = labelwid; - uiWindowsControlMinimumSize(uiWindowsControl(fc.c), &minimumWidth, &minimumHeight); - if (fc.stretchy) { - nStretchy++; - if (maxStretchyHeight < minimumHeight) - maxStretchyHeight = minimumHeight; - } - if (maxControlWidth < minimumWidth) - maxControlWidth = minimumWidth; - if (!fc.stretchy) - *height += minimumHeight; - } - if (nVisible == 0) // nothing to show; return 0x0 - return; - *width += maxLabelWidth + maxControlWidth; - - // 2) outset the desired rect with the needed padding - *width += xpadding; - *height += (nVisible - 1) * ypadding; - - // 3) and now we can add in stretchy controls - *height += nStretchy * maxStretchyHeight; -} - -static void uiFormMinimumSizeChanged(uiWindowsControl *c) -{ - uiForm *f = uiForm(c); - - if (uiWindowsControlTooSmall(uiWindowsControl(f))) { - uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(f)); - return; - } - formRelayout(f); -} - -static void uiFormSetMinSize(uiControl *c, int w, int h) -{ - // checkme - uiFormMinimumSizeChanged(uiWindowsControl(c)); -} - -uiWindowsControlDefaultLayoutRect(uiForm) -uiWindowsControlDefaultAssignControlIDZOrder(uiForm) - -static void uiFormChildVisibilityChanged(uiWindowsControl *c) -{ - // TODO eliminate the redundancy - uiWindowsControlMinimumSizeChanged(c); -} - -static void formArrangeChildren(uiForm *f) -{ - LONG_PTR controlID; - HWND insertAfter; - int i; - - controlID = 100; - insertAfter = NULL; - for (const struct formChild &fc : *(f->controls)) { - // TODO assign label ID and z-order - uiWindowsControlAssignControlIDZOrder(uiWindowsControl(fc.c), &controlID, &insertAfter); - } -} - -void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy) -{ - struct formChild fc; - WCHAR *wlabel; - - fc.c = c; - wlabel = toUTF16(label); - fc.label = uiWindowsEnsureCreateControlHWND(0, - L"STATIC", wlabel, - SS_LEFT | SS_NOPREFIX, - hInstance, NULL, - TRUE); - uiFree(wlabel); - uiWindowsEnsureSetParentHWND(fc.label, f->hwnd); - fc.stretchy = stretchy; - uiControlSetParent(fc.c, uiControl(f)); - uiWindowsControlSetParentHWND(uiWindowsControl(fc.c), f->hwnd); - f->controls->push_back(fc); - formArrangeChildren(f); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(f)); -} - -void uiFormDelete(uiForm *f, int index) -{ - struct formChild fc; - - fc = (*(f->controls))[index]; - uiControlSetParent(fc.c, NULL); - uiWindowsControlSetParentHWND(uiWindowsControl(fc.c), NULL); - uiWindowsEnsureDestroyWindow(fc.label); - f->controls->erase(f->controls->begin() + index); - formArrangeChildren(f); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(f)); -} - -int uiFormPadded(uiForm *f) -{ - return f->padded; -} - -void uiFormSetPadded(uiForm *f, int padded) -{ - f->padded = padded; - uiWindowsControlMinimumSizeChanged(uiWindowsControl(f)); -} - -static void onResize(uiWindowsControl *c) -{ - formRelayout(uiForm(c)); -} - -uiForm *uiNewForm(void) -{ - uiForm *f; - - uiWindowsNewControl(uiForm, f); - - f->hwnd = uiWindowsMakeContainer(uiWindowsControl(f), onResize); - - f->controls = new std::vector; - - return f; -} diff --git a/src/libui_sdl/libui/windows/gl.cpp b/src/libui_sdl/libui/windows/gl.cpp deleted file mode 100644 index 07ef19b1..00000000 --- a/src/libui_sdl/libui/windows/gl.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// 31 march 2019 -#include "uipriv_windows.hpp" -#include "area.hpp" - -#include -#include -#include - -struct uiGLContext -{ - uiArea* a; - - HWND hwnd; - HDC dc; - HGLRC rc; - - unsigned int version; -}; - - -uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor) -{ - uiGLContext* ctx; - BOOL res; - - ctx = uiNew(uiGLContext); - - ctx->a = a; - ctx->hwnd = a->hwnd; - - PIXELFORMATDESCRIPTOR pfd; - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; - pfd.cAlphaBits = 8; - pfd.cDepthBits = 24; - pfd.cStencilBits = 8; - pfd.iLayerType = PFD_MAIN_PLANE; - - ctx->dc = GetDC(ctx->hwnd); - if (!ctx->dc) - { - uiFree(ctx); - return NULL; - } - - int pixelformat = ChoosePixelFormat(ctx->dc, &pfd); - res = SetPixelFormat(ctx->dc, pixelformat, &pfd); - if (!res) - { - ReleaseDC(ctx->hwnd, ctx->dc); - uiFree(ctx); - return NULL; - } - - ctx->rc = wglCreateContext(ctx->dc); - if (!ctx->rc) - { - ReleaseDC(ctx->hwnd, ctx->dc); - uiFree(ctx); - return NULL; - } - - wglMakeCurrent(ctx->dc, ctx->rc); - - if (vermajor >= 3) - { - HGLRC (*wglCreateContextAttribsARB)(HDC,HGLRC,const int*); - HGLRC rc_better = NULL; - - wglCreateContextAttribsARB = (HGLRC(*)(HDC,HGLRC,const int*))wglGetProcAddress("wglCreateContextAttribsARB"); - if (wglCreateContextAttribsARB) - { - int attribs[15]; - int i = 0; - - attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB; - attribs[i++] = vermajor; - attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB; - attribs[i++] = verminor; - - attribs[i] = 0; - rc_better = wglCreateContextAttribsARB(ctx->dc, NULL, attribs); - } - - wglMakeCurrent(NULL, NULL); - wglDeleteContext(ctx->rc); - - if (!rc_better) - { - ReleaseDC(ctx->hwnd, ctx->dc); - uiFree(ctx); - return NULL; - } - - ctx->version = uiGLVersion(vermajor, verminor); - ctx->rc = rc_better; - wglMakeCurrent(ctx->dc, ctx->rc); - } - - return ctx; -} - -void freeGLContext(uiGLContext* ctx) -{ - if (ctx == NULL) return; - wglMakeCurrent(NULL, NULL); - wglDeleteContext(ctx->rc); - ReleaseDC(ctx->hwnd, ctx->dc); - uiFree(ctx); -} - -void uiGLMakeContextCurrent(uiGLContext* ctx) -{ - if (ctx == NULL) - { - wglMakeCurrent(NULL, NULL); - return; - } - - if (wglGetCurrentContext() == ctx->rc) return; - int res = wglMakeCurrent(ctx->dc, ctx->rc); -} - -unsigned int uiGLGetVersion(uiGLContext* ctx) -{ - if (ctx == NULL) return 0; - return ctx->version; -} - -void *uiGLGetProcAddress(const char* proc) -{ - return (void*)wglGetProcAddress(proc); -} - -void uiGLBegin(uiGLContext* ctx) -{ -} - -void uiGLEnd(uiGLContext* ctx) -{ -} - -void uiGLSwapBuffers(uiGLContext* ctx) -{ - if (ctx == NULL) return; - SwapBuffers(ctx->dc); -} - -int uiGLGetFramebuffer(uiGLContext* ctx) -{ - return 0; -} - -float uiGLGetFramebufferScale(uiGLContext* ctx) -{ - // TODO - return 1; -} - -void uiGLSetVSync(int sync) -{ - static PFNWGLSWAPINTERVALEXTPROC _wglSwapIntervalEXT = NULL; - static bool symloaded = false; - - if (!symloaded) - { - PFNGLGETSTRINGIPROC _glGetStringi = (PFNGLGETSTRINGIPROC)wglGetProcAddress("glGetStringi"); - if (_glGetStringi == NULL) return; - - GLint numext; - glGetIntegerv(GL_NUM_EXTENSIONS, &numext); - - bool hasswapctrl = false; - for (GLint i = 0; i < numext; i++) - { - const char* ext = (const char*)_glGetStringi(GL_EXTENSIONS, i); - if (!stricmp(ext, "WGL_EXT_swap_control")) - { - hasswapctrl = true; - break; - } - } - - if (hasswapctrl) - _wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); - - symloaded = true; - } - - if (_wglSwapIntervalEXT) - _wglSwapIntervalEXT(sync); -} diff --git a/src/libui_sdl/libui/windows/graphemes.cpp b/src/libui_sdl/libui/windows/graphemes.cpp deleted file mode 100644 index 355e4037..00000000 --- a/src/libui_sdl/libui/windows/graphemes.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// 25 may 2016 -#include "uipriv_windows.hpp" - -// We could use CharNext() to generate grapheme cluster boundaries, but it doesn't handle surrogate pairs properly (see http://archives.miloush.net/michkap/archive/2008/12/16/9223301.html). -// So let's use Uniscribe (see http://archives.miloush.net/michkap/archive/2005/01/14/352802.html) -// See also http://www.catch22.net/tuts/uniscribe-mysteries and http://www.catch22.net/tuts/keyboard-navigation for more details. - -static HRESULT itemize(WCHAR *msg, size_t len, SCRIPT_ITEM **out, int *outn) -{ - SCRIPT_CONTROL sc; - SCRIPT_STATE ss; - SCRIPT_ITEM *items; - size_t maxItems; - int n; - HRESULT hr; - - // make sure these are zero-initialized to avoid mangling the text - ZeroMemory(&sc, sizeof (SCRIPT_CONTROL)); - ZeroMemory(&ss, sizeof (SCRIPT_STATE)); - - maxItems = len + 2; - for (;;) { - items = new SCRIPT_ITEM[maxItems]; - hr = ScriptItemize(msg, len, - maxItems, - &sc, &ss, - items, &n); - if (hr == S_OK) - break; - // otherwise either an error or not enough room - delete[] items; - if (hr != E_OUTOFMEMORY) - return hr; - maxItems *= 2; // add some more and try again - } - - *out = items; - *outn = n; - return S_OK; -} - -size_t *graphemes(WCHAR *msg) -{ - size_t len; - SCRIPT_ITEM *items; - int i, n; - size_t *out; - size_t *op; - SCRIPT_LOGATTR *logattr; - int j, nn; - HRESULT hr; - - len = wcslen(msg); - hr = itemize(msg, len, &items, &n); - if (hr != S_OK) - logHRESULT(L"error itemizing string for finding grapheme cluster boundaries", hr); - - // should be enough; 2 more just to be safe - out = (size_t *) uiAlloc((len + 2) * sizeof (size_t), "size_t[]"); - op = out; - - // note that there are actually n + 1 elements in items - for (i = 0; i < n; i++) { - nn = items[i + 1].iCharPos - items[i].iCharPos; - logattr = new SCRIPT_LOGATTR[nn]; - hr = ScriptBreak(msg + items[i].iCharPos, nn, - &(items[i].a), logattr); - if (hr != S_OK) - logHRESULT(L"error breaking string for finding grapheme cluster boundaries", hr); - for (j = 0; j < nn; j++) - if (logattr[j].fCharStop != 0) - *op++ = items[i].iCharPos + j; - delete[] logattr; - } - // and handle the last item for the end of the string - *op++ = items[i].iCharPos; - - delete[] items; - return out; -} diff --git a/src/libui_sdl/libui/windows/grid.cpp b/src/libui_sdl/libui/windows/grid.cpp deleted file mode 100644 index 0a854c58..00000000 --- a/src/libui_sdl/libui/windows/grid.cpp +++ /dev/null @@ -1,665 +0,0 @@ -// 10 june 2016 -#include "uipriv_windows.hpp" - -// TODO compare with GTK+: -// - what happens if you call InsertAt() twice? -// - what happens if you call Append() twice? - -// TODOs -// - the Assorted page has clipping and repositioning issues - -struct gridChild { - uiControl *c; - int left; - int top; - int xspan; - int yspan; - int hexpand; - uiAlign halign; - int vexpand; - uiAlign valign; - - // have these here so they don't need to be reallocated each relayout - int finalx, finaly; - int finalwidth, finalheight; - int minwidth, minheight; -}; - -struct uiGrid { - uiWindowsControl c; - HWND hwnd; - std::vector *children; - std::map *indexof; - int padded; - - int xmin, ymin; - int xmax, ymax; -}; - -static bool gridRecomputeMinMax(uiGrid *g) -{ - bool first = true; - - for (struct gridChild *gc : *(g->children)) { - // this is important; we want g->xmin/g->ymin to satisfy gridLayoutData::visibleRow()/visibleColumn() - if (!uiControlVisible(gc->c)) - continue; - if (first) { - g->xmin = gc->left; - g->ymin = gc->top; - g->xmax = gc->left + gc->xspan; - g->ymax = gc->top + gc->yspan; - first = false; - continue; - } - if (g->xmin > gc->left) - g->xmin = gc->left; - if (g->ymin > gc->top) - g->ymin = gc->top; - if (g->xmax < (gc->left + gc->xspan)) - g->xmax = gc->left + gc->xspan; - if (g->ymax < (gc->top + gc->yspan)) - g->ymax = gc->top + gc->yspan; - } - return first != false; -} - -#define xcount(g) ((g)->xmax - (g)->xmin) -#define ycount(g) ((g)->ymax - (g)->ymin) -#define toxindex(g, x) ((x) - (g)->xmin) -#define toyindex(g, y) ((y) - (g)->ymin) - -class gridLayoutData { - int ycount; -public: - int **gg; // topological map gg[y][x] = control index - int *colwidths; - int *rowheights; - bool *hexpand; - bool *vexpand; - int nVisibleRows; - int nVisibleColumns; - - bool noVisible; - - gridLayoutData(uiGrid *g) - { - size_t i; - int x, y; - - this->noVisible = gridRecomputeMinMax(g); - - this->gg = new int *[ycount(g)]; - for (y = 0; y < ycount(g); y++) { - this->gg[y] = new int[xcount(g)]; - for (x = 0; x < xcount(g); x++) - this->gg[y][x] = -1; - } - - for (i = 0; i < g->children->size(); i++) { - struct gridChild *gc; - - gc = (*(g->children))[i]; - if (!uiControlVisible(gc->c)) - continue; - for (y = gc->top; y < gc->top + gc->yspan; y++) - for (x = gc->left; x < gc->left + gc->xspan; x++) - this->gg[toyindex(g, y)][toxindex(g, x)] = i; - } - - this->colwidths = new int[xcount(g)]; - ZeroMemory(this->colwidths, xcount(g) * sizeof (int)); - this->rowheights = new int[ycount(g)]; - ZeroMemory(this->rowheights, ycount(g) * sizeof (int)); - this->hexpand = new bool[xcount(g)]; - ZeroMemory(this->hexpand, xcount(g) * sizeof (bool)); - this->vexpand = new bool[ycount(g)]; - ZeroMemory(this->vexpand, ycount(g) * sizeof (bool)); - - this->ycount = ycount(g); - - // if a row or column only contains emptys and spanning cells of a opposite-direction spannings, it is invisible and should not be considered for padding amount calculations - // note that the first row and column will always be visible because gridRecomputeMinMax() computed a smallest fitting rectangle - if (this->noVisible) - return; - this->nVisibleRows = 0; - for (y = 0; y < this->ycount; y++) - if (this->visibleRow(g, y)) - this->nVisibleRows++; - this->nVisibleColumns = 0; - for (x = 0; x < xcount(g); x++) - if (this->visibleColumn(g, x)) - this->nVisibleColumns++; - } - - ~gridLayoutData() - { - size_t y; - - delete[] this->hexpand; - delete[] this->vexpand; - delete[] this->colwidths; - delete[] this->rowheights; - for (y = 0; y < this->ycount; y++) - delete[] this->gg[y]; - delete[] this->gg; - } - - bool visibleRow(uiGrid *g, int y) - { - int x; - struct gridChild *gc; - - for (x = 0; x < xcount(g); x++) - if (this->gg[y][x] != -1) { - gc = (*(g->children))[this->gg[y][x]]; - if (gc->yspan == 1 || gc->top - g->ymin == y) - return true; - } - return false; - } - - bool visibleColumn(uiGrid *g, int x) - { - int y; - struct gridChild *gc; - - for (y = 0; y < this->ycount; y++) - if (this->gg[y][x] != -1) { - gc = (*(g->children))[this->gg[y][x]]; - if (gc->xspan == 1 || gc->left - g->xmin == x) - return true; - } - return false; - } -}; - -static void gridPadding(uiGrid *g, int *xpadding, int *ypadding) -{ - uiWindowsSizing sizing; - - *xpadding = 0; - *ypadding = 0; - if (g->padded) { - uiWindowsGetSizing(g->hwnd, &sizing); - uiWindowsSizingStandardPadding(&sizing, xpadding, ypadding); - } -} - -static void gridRelayout(uiGrid *g) -{ - RECT r; - int x, y, width, height; - gridLayoutData *ld; - int xpadding, ypadding; - int ix, iy; - int iwidth, iheight; - int i; - struct gridChild *gc; - int nhexpand, nvexpand; - - if (g->children->size() == 0) - return; // nothing to do - - uiWindowsEnsureGetClientRect(g->hwnd, &r); - x = r.left; - y = r.top; - width = r.right - r.left; - height = r.bottom - r.top; - - gridPadding(g, &xpadding, &ypadding); - ld = new gridLayoutData(g); - if (ld->noVisible) { // nothing to do - delete ld; - return; - } - - // 0) discount padding from width/height - width -= (ld->nVisibleColumns - 1) * xpadding; - height -= (ld->nVisibleRows - 1) * ypadding; - - // 1) compute colwidths and rowheights before handling expansion - // we only count non-spanning controls to avoid weirdness - for (iy = 0; iy < ycount(g); iy++) - for (ix = 0; ix < xcount(g); ix++) { - i = ld->gg[iy][ix]; - if (i == -1) - continue; - gc = (*(g->children))[i]; - uiWindowsControlMinimumSize(uiWindowsControl(gc->c), &iwidth, &iheight); - if (gc->xspan == 1) - if (ld->colwidths[ix] < iwidth) - ld->colwidths[ix] = iwidth; - if (gc->yspan == 1) - if (ld->rowheights[iy] < iheight) - ld->rowheights[iy] = iheight; - // save these for step 6 - gc->minwidth = iwidth; - gc->minheight = iheight; - } - - // 2) figure out which rows/columns expand but not span - // we need to know which expanding rows/columns don't span before we can handle the ones that do - for (i = 0; i < g->children->size(); i++) { - gc = (*(g->children))[i]; - if (!uiControlVisible(gc->c)) - continue; - if (gc->hexpand && gc->xspan == 1) - ld->hexpand[toxindex(g, gc->left)] = true; - if (gc->vexpand && gc->yspan == 1) - ld->vexpand[toyindex(g, gc->top)] = true; - } - - // 3) figure out which rows/columns expand that do span - // the way we handle this is simple: if none of the spanned rows/columns expand, make all rows/columns expand - for (i = 0; i < g->children->size(); i++) { - gc = (*(g->children))[i]; - if (!uiControlVisible(gc->c)) - continue; - if (gc->hexpand && gc->xspan != 1) { - bool doit = true; - - for (ix = gc->left; ix < gc->left + gc->xspan; ix++) - if (ld->hexpand[toxindex(g, ix)]) { - doit = false; - break; - } - if (doit) - for (ix = gc->left; ix < gc->left + gc->xspan; ix++) - ld->hexpand[toxindex(g, ix)] = true; - } - if (gc->vexpand && gc->yspan != 1) { - bool doit = true; - - for (iy = gc->top; iy < gc->top + gc->yspan; iy++) - if (ld->vexpand[toyindex(g, iy)]) { - doit = false; - break; - } - if (doit) - for (iy = gc->top; iy < gc->top + gc->yspan; iy++) - ld->vexpand[toyindex(g, iy)] = true; - } - } - - // 4) compute and assign expanded widths/heights - nhexpand = 0; - nvexpand = 0; - for (i = 0; i < xcount(g); i++) - if (ld->hexpand[i]) - nhexpand++; - else - width -= ld->colwidths[i]; - for (i = 0; i < ycount(g); i++) - if (ld->vexpand[i]) - nvexpand++; - else - height -= ld->rowheights[i]; - for (i = 0; i < xcount(g); i++) - if (ld->hexpand[i]) - ld->colwidths[i] = width / nhexpand; - for (i = 0; i < ycount(g); i++) - if (ld->vexpand[i]) - ld->rowheights[i] = height / nvexpand; - - // 5) reset the final coordinates for the next step - for (i = 0; i < g->children->size(); i++) { - gc = (*(g->children))[i]; - if (!uiControlVisible(gc->c)) - continue; - gc->finalx = 0; - gc->finaly = 0; - gc->finalwidth = 0; - gc->finalheight = 0; - } - - // 6) compute cell positions and sizes - for (iy = 0; iy < ycount(g); iy++) { - int curx; - int prev; - - curx = 0; - prev = -1; - for (ix = 0; ix < xcount(g); ix++) { - if (!ld->visibleColumn(g, ix)) - continue; - i = ld->gg[iy][ix]; - if (i != -1) { - gc = (*(g->children))[i]; - if (iy == toyindex(g, gc->top)) { // don't repeat this step if the control spans vertically - if (i != prev) - gc->finalx = curx; - else - gc->finalwidth += xpadding; - gc->finalwidth += ld->colwidths[ix]; - } - } - curx += ld->colwidths[ix] + xpadding; - prev = i; - } - } - for (ix = 0; ix < xcount(g); ix++) { - int cury; - int prev; - - cury = 0; - prev = -1; - for (iy = 0; iy < ycount(g); iy++) { - if (!ld->visibleRow(g, iy)) - continue; - i = ld->gg[iy][ix]; - if (i != -1) { - gc = (*(g->children))[i]; - if (ix == toxindex(g, gc->left)) { // don't repeat this step if the control spans horizontally - if (i != prev) - gc->finaly = cury; - else - gc->finalheight += ypadding; - gc->finalheight += ld->rowheights[iy]; - } - } - cury += ld->rowheights[iy] + ypadding; - prev = i; - } - } - - // 7) everything as it stands now is set for xalign == Fill yalign == Fill; set the correct alignments - // this is why we saved minwidth/minheight above - for (i = 0; i < g->children->size(); i++) { - gc = (*(g->children))[i]; - if (!uiControlVisible(gc->c)) - continue; - if (gc->halign != uiAlignFill) { - switch (gc->halign) { - case uiAlignEnd: - gc->finalx += gc->finalwidth - gc->minwidth; - break; - case uiAlignCenter: - gc->finalx += (gc->finalwidth - gc->minwidth) / 2; - break; - } - gc->finalwidth = gc->minwidth; // for all three - } - if (gc->valign != uiAlignFill) { - switch (gc->valign) { - case uiAlignEnd: - gc->finaly += gc->finalheight - gc->minheight; - break; - case uiAlignCenter: - gc->finaly += (gc->finalheight - gc->minheight) / 2; - break; - } - gc->finalheight = gc->minheight; // for all three - } - } - - // 8) and FINALLY we resize - for (iy = 0; iy < ycount(g); iy++) - for (ix = 0; ix < xcount(g); ix++) { - i = ld->gg[iy][ix]; - if (i != -1) { // treat empty cells like spaces - gc = (*(g->children))[i]; - uiWindowsEnsureMoveWindowDuringResize( - (HWND) uiControlHandle(gc->c), - gc->finalx,//TODO + x, - gc->finaly,//TODO + y, - gc->finalwidth, - gc->finalheight); - } - } - - delete ld; -} - -static void uiGridDestroy(uiControl *c) -{ - uiGrid *g = uiGrid(c); - - for (struct gridChild *gc : *(g->children)) { - uiControlSetParent(gc->c, NULL); - uiControlDestroy(gc->c); - uiFree(gc); - } - delete g->indexof; - delete g->children; - uiWindowsEnsureDestroyWindow(g->hwnd); - uiFreeControl(uiControl(g)); -} - -uiWindowsControlDefaultHandle(uiGrid) -uiWindowsControlDefaultParent(uiGrid) -uiWindowsControlDefaultSetParent(uiGrid) -uiWindowsControlDefaultToplevel(uiGrid) -uiWindowsControlDefaultVisible(uiGrid) -uiWindowsControlDefaultShow(uiGrid) -uiWindowsControlDefaultHide(uiGrid) -uiWindowsControlDefaultEnabled(uiGrid) -uiWindowsControlDefaultEnable(uiGrid) -uiWindowsControlDefaultDisable(uiGrid) -uiWindowsControlDefaultSetFocus(uiGrid) - -static void uiGridSyncEnableState(uiWindowsControl *c, int enabled) -{ - uiGrid *g = uiGrid(c); - - if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(g), enabled)) - return; - for (const struct gridChild *gc : *(g->children)) - uiWindowsControlSyncEnableState(uiWindowsControl(gc->c), enabled); -} - -uiWindowsControlDefaultSetParentHWND(uiGrid) - -static void uiGridMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiGrid *g = uiGrid(c); - int xpadding, ypadding; - gridLayoutData *ld; - int x, y; - int i; - struct gridChild *gc; - int minwid, minht; - int colwidth, rowheight; - - *width = 0; - *height = 0; - if (g->children->size() == 0) - return; // nothing to do - - gridPadding(g, &xpadding, &ypadding); - ld = new gridLayoutData(g); - if (ld->noVisible) { // nothing to do; return 0x0 - delete ld; - return; - } - - // 1) compute colwidths and rowheights before handling expansion - // TODO put this in its own function (but careful about the spanning calculation in gridRelayout()) - for (y = 0; y < ycount(g); y++) - for (x = 0; x < xcount(g); x++) { - i = ld->gg[y][x]; - if (i == -1) - continue; - gc = (*(g->children))[i]; - uiWindowsControlMinimumSize(uiWindowsControl(gc->c), &minwid, &minht); - // allot equal space in the presence of spanning to keep things sane - if (ld->colwidths[x] < minwid / gc->xspan) - ld->colwidths[x] = minwid / gc->xspan; - if (ld->rowheights[y] < minht / gc->yspan) - ld->rowheights[y] = minht / gc->yspan; - // save these for step 6 - gc->minwidth = minwid; - gc->minheight = minht; - } - - // 2) compute total column width/row height - colwidth = 0; - rowheight = 0; - for (x = 0; x < xcount(g); x++) - colwidth += ld->colwidths[x]; - for (y = 0; y < ycount(g); y++) - rowheight += ld->rowheights[y]; - - // and that's it; just account for padding - *width = colwidth + (ld->nVisibleColumns - 1) * xpadding; - *height = rowheight + (ld->nVisibleRows - 1) * ypadding; -} - -static void uiGridMinimumSizeChanged(uiWindowsControl *c) -{ - uiGrid *g = uiGrid(c); - - if (uiWindowsControlTooSmall(uiWindowsControl(g))) { - uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(g)); - return; - } - gridRelayout(g); -} - -static void uiGridSetMinSize(uiControl *c, int w, int h) -{ - // checkme - uiGridMinimumSizeChanged(uiWindowsControl(c)); -} - -uiWindowsControlDefaultLayoutRect(uiGrid) -uiWindowsControlDefaultAssignControlIDZOrder(uiGrid) - -static void uiGridChildVisibilityChanged(uiWindowsControl *c) -{ - // TODO eliminate the redundancy - uiWindowsControlMinimumSizeChanged(c); -} - -// must have called gridRecomputeMinMax() first -static void gridArrangeChildren(uiGrid *g) -{ - LONG_PTR controlID; - HWND insertAfter; - gridLayoutData *ld; - bool *visited; - int x, y; - int i; - struct gridChild *gc; - - if (g->children->size() == 0) - return; // nothing to do - ld = new gridLayoutData(g); - controlID = 100; - insertAfter = NULL; - visited = new bool[g->children->size()]; - ZeroMemory(visited, g->children->size() * sizeof (bool)); - for (y = 0; y < ycount(g); y++) - for (x = 0; x < xcount(g); x++) { - i = ld->gg[y][x]; - if (i == -1) - continue; - if (visited[i]) - continue; - visited[i] = true; - gc = (*(g->children))[i]; - uiWindowsControlAssignControlIDZOrder(uiWindowsControl(gc->c), &controlID, &insertAfter); - } - delete[] visited; - delete ld; -} - -static struct gridChild *toChild(uiControl *c, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - struct gridChild *gc; - - if (xspan < 0) - userbug("You cannot have a negative xspan in a uiGrid cell."); - if (yspan < 0) - userbug("You cannot have a negative yspan in a uiGrid cell."); - gc = uiNew(struct gridChild); - gc->c = c; - gc->xspan = xspan; - gc->yspan = yspan; - gc->hexpand = hexpand; - gc->halign = halign; - gc->vexpand = vexpand; - gc->valign = valign; - return gc; -} - -static void add(uiGrid *g, struct gridChild *gc) -{ - uiControlSetParent(gc->c, uiControl(g)); - uiWindowsControlSetParentHWND(uiWindowsControl(gc->c), g->hwnd); - g->children->push_back(gc); - (*(g->indexof))[gc->c] = g->children->size() - 1; - gridRecomputeMinMax(g); - gridArrangeChildren(g); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(g)); -} - -void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - struct gridChild *gc; - - gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign); - gc->left = left; - gc->top = top; - add(g, gc); -} - -// TODO decide what happens if existing is NULL -void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign) -{ - struct gridChild *gc; - struct gridChild *other; - - gc = toChild(c, xspan, yspan, hexpand, halign, vexpand, valign); - other = (*(g->children))[(*(g->indexof))[existing]]; - switch (at) { - case uiAtLeading: - gc->left = other->left - gc->xspan; - gc->top = other->top; - break; - case uiAtTop: - gc->left = other->left; - gc->top = other->top - gc->yspan; - break; - case uiAtTrailing: - gc->left = other->left + other->xspan; - gc->top = other->top; - break; - case uiAtBottom: - gc->left = other->left; - gc->top = other->top + other->yspan; - break; - // TODO add error checks to ALL enums - } - add(g, gc); -} - -int uiGridPadded(uiGrid *g) -{ - return g->padded; -} - -void uiGridSetPadded(uiGrid *g, int padded) -{ - g->padded = padded; - uiWindowsControlMinimumSizeChanged(uiWindowsControl(g)); -} - -static void onResize(uiWindowsControl *c) -{ - gridRelayout(uiGrid(c)); -} - -uiGrid *uiNewGrid(void) -{ - uiGrid *g; - - uiWindowsNewControl(uiGrid, g); - - g->hwnd = uiWindowsMakeContainer(uiWindowsControl(g), onResize); - - g->children = new std::vector; - g->indexof = new std::map; - - return g; -} diff --git a/src/libui_sdl/libui/windows/group.cpp b/src/libui_sdl/libui/windows/group.cpp deleted file mode 100644 index 9c36da18..00000000 --- a/src/libui_sdl/libui/windows/group.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// 16 may 2015 -#include "uipriv_windows.hpp" - -struct uiGroup { - uiWindowsControl c; - HWND hwnd; - struct uiControl *child; - int margined; -}; - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define groupXMargin 6 -#define groupYMarginTop 11 /* note this value /includes/ the groupbox label */ -#define groupYMarginBottom 7 - -// unfortunately because the client area of a groupbox includes the frame and caption text, we have to apply some margins ourselves, even if we don't want "any" -// these were deduced by hand based on the standard DLU conversions; the X and Y top margins are the width and height, respectively, of one character cell -// they can be fine-tuned later -#define groupUnmarginedXMargin 4 -#define groupUnmarginedYMarginTop 8 -#define groupUnmarginedYMarginBottom 3 - -static void groupMargins(uiGroup *g, int *mx, int *mtop, int *mbottom) -{ - uiWindowsSizing sizing; - - *mx = groupUnmarginedXMargin; - *mtop = groupUnmarginedYMarginTop; - *mbottom = groupUnmarginedYMarginBottom; - if (g->margined) { - *mx = groupXMargin; - *mtop = groupYMarginTop; - *mbottom = groupYMarginBottom; - } - uiWindowsGetSizing(g->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, mx, mtop); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, mbottom); -} - -static void groupRelayout(uiGroup *g) -{ - RECT r; - int mx, mtop, mbottom; - - if (g->child == NULL) - return; - uiWindowsEnsureGetClientRect(g->hwnd, &r); - groupMargins(g, &mx, &mtop, &mbottom); - r.left += mx; - r.top += mtop; - r.right -= mx; - r.bottom -= mbottom; - uiWindowsEnsureMoveWindowDuringResize((HWND) uiControlHandle(g->child), r.left, r.top, r.right - r.left, r.bottom - r.top); -} - -static void uiGroupDestroy(uiControl *c) -{ - uiGroup *g = uiGroup(c); - - if (g->child != NULL) { - uiControlSetParent(g->child, NULL); - uiControlDestroy(g->child); - } - uiWindowsEnsureDestroyWindow(g->hwnd); - uiFreeControl(uiControl(g)); -} - -uiWindowsControlDefaultHandle(uiGroup) -uiWindowsControlDefaultParent(uiGroup) -uiWindowsControlDefaultSetParent(uiGroup) -uiWindowsControlDefaultToplevel(uiGroup) -uiWindowsControlDefaultVisible(uiGroup) -uiWindowsControlDefaultShow(uiGroup) -uiWindowsControlDefaultHide(uiGroup) -uiWindowsControlDefaultEnabled(uiGroup) -uiWindowsControlDefaultEnable(uiGroup) -uiWindowsControlDefaultDisable(uiGroup) -uiWindowsControlDefaultSetFocus(uiGroup) - -static void uiGroupSyncEnableState(uiWindowsControl *c, int enabled) -{ - uiGroup *g = uiGroup(c); - - if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(g), enabled)) - return; - EnableWindow(g->hwnd, enabled); - if (g->child != NULL) - uiWindowsControlSyncEnableState(uiWindowsControl(g->child), enabled); -} - -uiWindowsControlDefaultSetParentHWND(uiGroup) - -static void uiGroupMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiGroup *g = uiGroup(c); - int mx, mtop, mbottom; - int labelWidth; - - *width = 0; - *height = 0; - if (g->child != NULL) - uiWindowsControlMinimumSize(uiWindowsControl(g->child), width, height); - labelWidth = uiWindowsWindowTextWidth(g->hwnd); - if (*width < labelWidth) // don't clip the label; it doesn't ellipsize - *width = labelWidth; - groupMargins(g, &mx, &mtop, &mbottom); - *width += 2 * mx; - *height += mtop + mbottom; -} - -static void uiGroupMinimumSizeChanged(uiWindowsControl *c) -{ - uiGroup *g = uiGroup(c); - - if (uiWindowsControlTooSmall(uiWindowsControl(g))) { - uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(g)); - return; - } - groupRelayout(g); -} - -static void uiGroupSetMinSize(uiControl *c, int w, int h) -{ - // checkme - uiGroupMinimumSizeChanged(uiWindowsControl(c)); -} - -uiWindowsControlDefaultLayoutRect(uiGroup) -uiWindowsControlDefaultAssignControlIDZOrder(uiGroup) - -static void uiGroupChildVisibilityChanged(uiWindowsControl *c) -{ - // TODO eliminate the redundancy - uiWindowsControlMinimumSizeChanged(c); -} - -char *uiGroupTitle(uiGroup *g) -{ - return uiWindowsWindowText(g->hwnd); -} - -void uiGroupSetTitle(uiGroup *g, const char *text) -{ - uiWindowsSetWindowText(g->hwnd, text); - // changing the text might necessitate a change in the groupbox's size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(g)); -} - -void uiGroupSetChild(uiGroup *g, uiControl *child) -{ - if (g->child != NULL) { - uiControlSetParent(g->child, NULL); - uiWindowsControlSetParentHWND(uiWindowsControl(g->child), NULL); - } - g->child = child; - if (g->child != NULL) { - uiControlSetParent(g->child, uiControl(g)); - uiWindowsControlSetParentHWND(uiWindowsControl(g->child), g->hwnd); - uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl(g->child)); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(g)); - } -} - -int uiGroupMargined(uiGroup *g) -{ - return g->margined; -} - -void uiGroupSetMargined(uiGroup *g, int margined) -{ - g->margined = margined; - uiWindowsControlMinimumSizeChanged(uiWindowsControl(g)); -} - -static LRESULT CALLBACK groupSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - uiGroup *g = uiGroup(dwRefData); - WINDOWPOS *wp = (WINDOWPOS *) lParam; - MINMAXINFO *mmi = (MINMAXINFO *) lParam; - int minwid, minht; - LRESULT lResult; - - if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - switch (uMsg) { - case WM_WINDOWPOSCHANGED: - if ((wp->flags & SWP_NOSIZE) != 0) - break; - groupRelayout(g); - return 0; - case WM_GETMINMAXINFO: - lResult = DefWindowProcW(hwnd, uMsg, wParam, lParam); - uiWindowsControlMinimumSize(uiWindowsControl(g), &minwid, &minht); - mmi->ptMinTrackSize.x = minwid; - mmi->ptMinTrackSize.y = minht; - return lResult; - case WM_NCDESTROY: - if (RemoveWindowSubclass(hwnd, groupSubProc, uIdSubclass) == FALSE) - logLastError(L"error removing groupbox subclass"); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -uiGroup *uiNewGroup(const char *text) -{ - uiGroup *g; - WCHAR *wtext; - - uiWindowsNewControl(uiGroup, g); - - wtext = toUTF16(text); - g->hwnd = uiWindowsEnsureCreateControlHWND(WS_EX_CONTROLPARENT, - L"button", wtext, - BS_GROUPBOX, - hInstance, NULL, - TRUE); - uiFree(wtext); - - if (SetWindowSubclass(g->hwnd, groupSubProc, 0, (DWORD_PTR) g) == FALSE) - logLastError(L"error subclassing groupbox to handle parent messages"); - - return g; -} diff --git a/src/libui_sdl/libui/windows/init.cpp b/src/libui_sdl/libui/windows/init.cpp deleted file mode 100644 index 5b4fe1d0..00000000 --- a/src/libui_sdl/libui/windows/init.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// 6 april 2015 -#include "uipriv_windows.hpp" - -HINSTANCE hInstance; -int nCmdShow; - -HFONT hMessageFont; - -// LONGTERM needed? -HBRUSH hollowBrush; - -// the returned pointer is actually to the second character -// if the first character is - then free, otherwise don't -static const char *initerr(const char *message, const WCHAR *label, DWORD value) -{ - WCHAR *sysmsg; - BOOL hassysmsg; - WCHAR *wmessage; - WCHAR *wout; - char *out; - - hassysmsg = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, value, 0, (LPWSTR) (&sysmsg), 0, NULL) != 0; - if (!hassysmsg) - sysmsg = L""; - wmessage = toUTF16(message + 1); - wout = strf(L"-error initializing libui: %s; code %I32d (0x%08I32X) %s", - wmessage, - value, value, - sysmsg); - uiFree(wmessage); - if (hassysmsg) - LocalFree(sysmsg); // ignore error - out = toUTF8(wout); - uiFree(wout); - return out + 1; -} - -#define ieLastErr(msg) initerr("=" msg, L"GetLastError() ==", GetLastError()) -#define ieHRESULT(msg, hr) initerr("=" msg, L"HRESULT", (DWORD) hr) - -// LONGTERM make common -uiInitOptions options; - -#define wantedICCClasses ( \ - ICC_STANDARD_CLASSES | /* user32.dll controls */ \ - ICC_PROGRESS_CLASS | /* progress bars */ \ - ICC_TAB_CLASSES | /* tabs */ \ - ICC_LISTVIEW_CLASSES | /* table headers */ \ - ICC_UPDOWN_CLASS | /* spinboxes */ \ - ICC_BAR_CLASSES | /* trackbar */ \ - ICC_DATE_CLASSES | /* date/time picker */ \ - 0) - -const char *uiInit(uiInitOptions *o) -{ - STARTUPINFOW si; - const char *ce; - HICON hDefaultIcon; - HCURSOR hDefaultCursor; - NONCLIENTMETRICSW ncm; - INITCOMMONCONTROLSEX icc; - HRESULT hr; - - options = *o; - - initAlloc(); - - nCmdShow = SW_SHOWDEFAULT; - GetStartupInfoW(&si); - if ((si.dwFlags & STARTF_USESHOWWINDOW) != 0) - nCmdShow = si.wShowWindow; - - SetProcessDPIAware(); - - hDefaultIcon = LoadIconW(NULL, IDI_APPLICATION); - if (hDefaultIcon == NULL) - return ieLastErr("loading default icon for window classes"); - hDefaultCursor = LoadCursorW(NULL, IDC_ARROW); - if (hDefaultCursor == NULL) - return ieLastErr("loading default cursor for window classes"); - - ce = initUtilWindow(hDefaultIcon, hDefaultCursor); - if (ce != NULL) - return initerr(ce, L"GetLastError() ==", GetLastError()); - - if (registerWindowClass(hDefaultIcon, hDefaultCursor) == 0) - return ieLastErr("registering uiWindow window class"); - - ZeroMemory(&ncm, sizeof (NONCLIENTMETRICSW)); - ncm.cbSize = sizeof (NONCLIENTMETRICSW); - if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof (NONCLIENTMETRICSW), &ncm, sizeof (NONCLIENTMETRICSW)) == 0) - return ieLastErr("getting default fonts"); - hMessageFont = CreateFontIndirectW(&(ncm.lfMessageFont)); - if (hMessageFont == NULL) - return ieLastErr("loading default messagebox font; this is the default UI font"); - - if (initContainer(hDefaultIcon, hDefaultCursor) == 0) - return ieLastErr("initializing uiWindowsMakeContainer() window class"); - - hollowBrush = (HBRUSH) GetStockObject(HOLLOW_BRUSH); - if (hollowBrush == NULL) - return ieLastErr("getting hollow brush"); - - ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX)); - icc.dwSize = sizeof (INITCOMMONCONTROLSEX); - icc.dwICC = wantedICCClasses; - if (InitCommonControlsEx(&icc) == 0) - return ieLastErr("initializing Common Controls"); - - hr = CoInitialize(NULL); - if (hr != S_OK && hr != S_FALSE) - return ieHRESULT("initializing COM", hr); - // LONGTERM initialize COM security - // LONGTERM (windows vista) turn off COM exception handling - - hr = initDraw(); - if (hr != S_OK) - return ieHRESULT("initializing Direct2D", hr); - - hr = initDrawText(); - if (hr != S_OK) - return ieHRESULT("initializing DirectWrite", hr); - - if (registerAreaClass(hDefaultIcon, hDefaultCursor) == 0) - return ieLastErr("registering uiArea window class"); - - if (registerMessageFilter() == 0) - return ieLastErr("registering libui message filter"); - - if (registerD2DScratchClass(hDefaultIcon, hDefaultCursor) == 0) - return ieLastErr("initializing D2D scratch window class"); - - return NULL; -} - -void uiUninit(void) -{ - uninitMenus(); - unregisterD2DScratchClass(); - unregisterMessageFilter(); - unregisterArea(); - uninitDrawText(); - uninitDraw(); - CoUninitialize(); - if (DeleteObject(hollowBrush) == 0) - logLastError(L"error freeing hollow brush"); - uninitContainer(); - if (DeleteObject(hMessageFont) == 0) - logLastError(L"error deleting control font"); - unregisterWindowClass(); - // no need to delete the default icon or cursor; see http://stackoverflow.com/questions/30603077/ - uninitUtilWindow(); - uninitAlloc(); -} - -void uiFreeInitError(const char *err) -{ - if (*(err - 1) == '-') - uiFree((void *) (err - 1)); -} - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - if (fdwReason == DLL_PROCESS_ATTACH) - hInstance = hinstDLL; - return TRUE; -} diff --git a/src/libui_sdl/libui/windows/label.cpp b/src/libui_sdl/libui/windows/label.cpp deleted file mode 100644 index d74b7d18..00000000 --- a/src/libui_sdl/libui/windows/label.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// 11 april 2015 -#include "uipriv_windows.hpp" - -struct uiLabel { - uiWindowsControl c; - HWND hwnd; -}; - -uiWindowsControlAllDefaults(uiLabel) - -// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define labelHeight 8 - -static void uiLabelMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiLabel *l = uiLabel(c); - uiWindowsSizing sizing; - int y; - - *width = uiWindowsWindowTextWidth(l->hwnd); - y = labelHeight; - uiWindowsGetSizing(l->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &y); - *height = y; -} - -char *uiLabelText(uiLabel *l) -{ - return uiWindowsWindowText(l->hwnd); -} - -void uiLabelSetText(uiLabel *l, const char *text) -{ - uiWindowsSetWindowText(l->hwnd, text); - // changing the text might necessitate a change in the label's size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(l)); -} - -uiLabel *uiNewLabel(const char *text) -{ - uiLabel *l; - WCHAR *wtext; - - uiWindowsNewControl(uiLabel, l); - - wtext = toUTF16(text); - l->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"static", wtext, - // SS_LEFTNOWORDWRAP clips text past the end; SS_NOPREFIX avoids accelerator translation - // controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi) - SS_LEFTNOWORDWRAP | SS_NOPREFIX, - hInstance, NULL, - TRUE); - uiFree(wtext); - - return l; -} diff --git a/src/libui_sdl/libui/windows/libui.manifest b/src/libui_sdl/libui/windows/libui.manifest deleted file mode 100644 index 8beb6cfc..00000000 --- a/src/libui_sdl/libui/windows/libui.manifest +++ /dev/null @@ -1,31 +0,0 @@ - - - -Your application description here. - - - - - - - - - - - - - - - diff --git a/src/libui_sdl/libui/windows/main.cpp b/src/libui_sdl/libui/windows/main.cpp deleted file mode 100644 index eb6d8492..00000000 --- a/src/libui_sdl/libui/windows/main.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// 6 april 2015 -#include "uipriv_windows.hpp" - -static HHOOK filter; - -static LRESULT CALLBACK filterProc(int code, WPARAM wParam, LPARAM lParam) -{ - MSG *msg = (MSG *) lParam; - - if (code < 0) - goto callNext; - - if (areaFilter(msg)) // don't continue to our IsDialogMessage() hack if the area handled it - goto discard; - - // TODO IsDialogMessage() hack here - - // otherwise keep going - goto callNext; - -discard: - // we handled it; discard the message so the dialog manager doesn't see it - return 1; - -callNext: - return CallNextHookEx(filter, code, wParam, lParam); -} - -int registerMessageFilter(void) -{ - filter = SetWindowsHookExW(WH_MSGFILTER, - filterProc, - hInstance, - GetCurrentThreadId()); - return filter != NULL; -} - -void unregisterMessageFilter(void) -{ - if (UnhookWindowsHookEx(filter) == 0) - logLastError(L"error unregistering libui message filter"); -} - -// LONGTERM http://blogs.msdn.com/b/oldnewthing/archive/2005/04/08/406509.aspx when adding accelerators, TranslateAccelerators() before IsDialogMessage() - -static void processMessage(MSG *msg) -{ - HWND correctParent; - - if (msg->hwnd != NULL) - correctParent = parentToplevel(msg->hwnd); - else // just to be safe - correctParent = GetActiveWindow(); - if (correctParent != NULL) - // this calls our mesage filter above for us - if (IsDialogMessage(correctParent, msg) != 0) - return; - TranslateMessage(msg); - DispatchMessageW(msg); -} - -static int waitMessage(MSG *msg) -{ - int res; - - res = GetMessageW(msg, NULL, 0, 0); - if (res < 0) { - logLastError(L"error calling GetMessage()"); - return 0; // bail out on error - } - return res != 0; // returns false on WM_QUIT -} - -void uiMain(void) -{ - while (uiMainStep(1)) - ; -} - -void uiMainSteps(void) -{ - // don't need to do anything here -} - -static int peekMessage(MSG *msg) -{ - BOOL res; - - res = PeekMessageW(msg, NULL, 0, 0, PM_REMOVE); - if (res == 0) - return 2; // no message available - if (msg->message != WM_QUIT) - return 1; // a message - return 0; // WM_QUIT -} - -int uiMainStep(int wait) -{ - MSG msg; - - if (wait) { - if (!waitMessage(&msg)) - return 0; - processMessage(&msg); - return 1; - } - - // don't wait for a message - switch (peekMessage(&msg)) { - case 0: // quit - // TODO PostQuitMessage() again? - return 0; - case 1: // process a message - processMessage(&msg); - // fall out to the case for no message - } - return 1; // no message -} - -void uiQuit(void) -{ - PostQuitMessage(0); -} - -void uiQueueMain(void (*f)(void *data), void *data) -{ - if (PostMessageW(utilWindow, msgQueued, (WPARAM) f, (LPARAM) data) == 0) - // LONGTERM this is likely not safe to call across threads (allocates memory) - logLastError(L"error queueing function to run on main thread"); -} diff --git a/src/libui_sdl/libui/windows/menu.cpp b/src/libui_sdl/libui/windows/menu.cpp deleted file mode 100644 index ccf5c9c8..00000000 --- a/src/libui_sdl/libui/windows/menu.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// 24 april 2015 -#include "uipriv_windows.hpp" - -// LONGTERM migrate to std::vector - -static uiMenu **menus = NULL; -static size_t len = 0; -static size_t cap = 0; -static BOOL menusFinalized = FALSE; -static WORD curID = 100; // start somewhere safe -static BOOL hasQuit = FALSE; -static BOOL hasPreferences = FALSE; -static BOOL hasAbout = FALSE; - -struct uiMenu { - WCHAR *name; - HMENU handle; - uiMenuItem **items; - BOOL ischild; - size_t len; - size_t cap; -}; - -struct uiMenuItem { - WCHAR *name; - int type; - WORD id; - void (*onClicked)(uiMenuItem *, uiWindow *, void *); - void *onClickedData; - BOOL disabled; // template for new instances; kept in sync with everything else - BOOL checked; - HMENU *hmenus; - uiMenu* popupchild; - size_t len; - size_t cap; -}; - -enum { - typeRegular, - typeCheckbox, - typeQuit, - typePreferences, - typeAbout, - typeSeparator, - typeSubmenu, -}; - -#define grow 32 - -static void sync(uiMenuItem *item) -{ - size_t i; - MENUITEMINFOW mi; - - ZeroMemory(&mi, sizeof (MENUITEMINFOW)); - mi.cbSize = sizeof (MENUITEMINFOW); - mi.fMask = MIIM_STATE; - if (item->disabled) - mi.fState |= MFS_DISABLED; - if (item->checked) - mi.fState |= MFS_CHECKED; - - for (i = 0; i < item->len; i++) - if (SetMenuItemInfo(item->hmenus[i], item->id, FALSE, &mi) == 0) - logLastError(L"error synchronizing menu items"); -} - -static void defaultOnClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - // do nothing -} - -static void onQuitClicked(uiMenuItem *item, uiWindow *w, void *data) -{ - if (shouldQuit()) - uiQuit(); -} - -void uiMenuItemEnable(uiMenuItem *i) -{ - i->disabled = FALSE; - sync(i); -} - -void uiMenuItemDisable(uiMenuItem *i) -{ - i->disabled = TRUE; - sync(i); -} - -void uiMenuItemOnClicked(uiMenuItem *i, void (*f)(uiMenuItem *, uiWindow *, void *), void *data) -{ - if (i->type == typeQuit) - userbug("You can not call uiMenuItemOnClicked() on a Quit item; use uiOnShouldQuit() instead."); - i->onClicked = f; - i->onClickedData = data; -} - -int uiMenuItemChecked(uiMenuItem *i) -{ - return i->checked != FALSE; -} - -void uiMenuItemSetChecked(uiMenuItem *i, int checked) -{ - // use explicit values - i->checked = FALSE; - if (checked) - i->checked = TRUE; - sync(i); -} - -static uiMenuItem *newItem(uiMenu *m, int type, const char *name) -{ - uiMenuItem *item; - - if (menusFinalized) - userbug("You can not create a new menu item after menus have been finalized."); - - if (m->len >= m->cap) { - m->cap += grow; - m->items = (uiMenuItem **) uiRealloc(m->items, m->cap * sizeof (uiMenuItem *), "uiMenuitem *[]"); - } - - item = uiNew(uiMenuItem); - - m->items[m->len] = item; - m->len++; - - item->type = type; - switch (item->type) { - case typeQuit: - item->name = toUTF16("Quit"); - break; - case typePreferences: - item->name = toUTF16("Preferences..."); - break; - case typeAbout: - item->name = toUTF16("About"); - break; - case typeSeparator: - break; - default: - item->name = toUTF16(name); - break; - } - item->popupchild = NULL; - - if (item->type != typeSeparator) { - item->id = curID; - curID++; - } - - if (item->type == typeQuit) { - // can't call uiMenuItemOnClicked() here - item->onClicked = onQuitClicked; - item->onClickedData = NULL; - } else - uiMenuItemOnClicked(item, defaultOnClicked, NULL); - - return item; -} - -uiMenuItem *uiMenuAppendSubmenu(uiMenu *m, uiMenu* child) -{ - uiMenuItem *item; - - if (menusFinalized) - userbug("You can not create a new menu item after menus have been finalized."); - - if (m->len >= m->cap) { - m->cap += grow; - m->items = (uiMenuItem **) uiRealloc(m->items, m->cap * sizeof (uiMenuItem *), "uiMenuitem *[]"); - } - - item = uiNew(uiMenuItem); - - m->items[m->len] = item; - m->len++; - - item->type = typeSubmenu; - item->name = child->name; - - item->popupchild = child; - child->ischild = TRUE; - - uiMenuItemOnClicked(item, defaultOnClicked, NULL); - - return item; -} - -uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name) -{ - return newItem(m, typeRegular, name); -} - -uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name) -{ - return newItem(m, typeCheckbox, name); -} - -uiMenuItem *uiMenuAppendQuitItem(uiMenu *m) -{ - if (hasQuit) - userbug("You can not have multiple Quit menu items in a program."); - hasQuit = TRUE; - newItem(m, typeSeparator, NULL); - return newItem(m, typeQuit, NULL); -} - -uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m) -{ - if (hasPreferences) - userbug("You can not have multiple Preferences menu items in a program."); - hasPreferences = TRUE; - newItem(m, typeSeparator, NULL); - return newItem(m, typePreferences, NULL); -} - -uiMenuItem *uiMenuAppendAboutItem(uiMenu *m) -{ - if (hasAbout) - // TODO place these userbug strings in a header - userbug("You can not have multiple About menu items in a program."); - hasAbout = TRUE; - newItem(m, typeSeparator, NULL); - return newItem(m, typeAbout, NULL); -} - -void uiMenuAppendSeparator(uiMenu *m) -{ - newItem(m, typeSeparator, NULL); -} - -uiMenu *uiNewMenu(const char *name) -{ - uiMenu *m; - - if (menusFinalized) - userbug("You can not create a new menu after menus have been finalized."); - if (len >= cap) { - cap += grow; - menus = (uiMenu **) uiRealloc(menus, cap * sizeof (uiMenu *), "uiMenu *[]"); - } - - m = uiNew(uiMenu); - - menus[len] = m; - len++; - - m->name = toUTF16(name); - m->ischild = FALSE; - - return m; -} - -static HMENU makeMenu(uiMenu *m); - -static void appendMenuItem(HMENU menu, uiMenuItem *item) -{ - UINT uFlags; - UINT_PTR id = item->id; - - uFlags = MF_SEPARATOR; - if (item->type != typeSeparator) { - uFlags = MF_STRING; - if (item->disabled) - uFlags |= MF_DISABLED | MF_GRAYED; - if (item->checked) - uFlags |= MF_CHECKED; - if (item->popupchild) - { - uFlags |= MF_POPUP; - id = (UINT_PTR)makeMenu(item->popupchild); - } - } - if (AppendMenuW(menu, uFlags, id, item->name) == 0) - logLastError(L"error appending menu item"); - - if (item->len >= item->cap) { - item->cap += grow; - item->hmenus = (HMENU *) uiRealloc(item->hmenus, item->cap * sizeof (HMENU), "HMENU[]"); - } - item->hmenus[item->len] = menu; - item->len++; -} - -static HMENU makeMenu(uiMenu *m) -{ - HMENU menu; - size_t i; - - menu = CreatePopupMenu(); - if (menu == NULL) - logLastError(L"error creating menu"); - m->handle = menu; - for (i = 0; i < m->len; i++) - appendMenuItem(menu, m->items[i]); - return menu; -} - -HMENU makeMenubar(void) -{ - HMENU menubar; - HMENU menu; - size_t i; - - menusFinalized = TRUE; - - menubar = CreateMenu(); - if (menubar == NULL) - logLastError(L"error creating menubar"); - - for (i = 0; i < len; i++) { - if (menus[i]->ischild) continue; - menu = makeMenu(menus[i]); - if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, menus[i]->name) == 0) - logLastError(L"error appending menu to menubar"); - } - - return menubar; -} - -void runMenuEvent(WORD id, uiWindow *w) -{ - uiMenu *m; - uiMenuItem *item; - size_t i, j; - - // this isn't optimal, but it works, and it should be just fine for most cases - for (i = 0; i < len; i++) { - m = menus[i]; - for (j = 0; j < m->len; j++) { - item = m->items[j]; - if (item->id == id) - goto found; - } - } - // no match - implbug("unknown menu ID %hu in runMenuEvent()", id); - -found: - // first toggle checkboxes, if any - if (item->type == typeCheckbox) - uiMenuItemSetChecked(item, !uiMenuItemChecked(item)); - - // then run the event - (*(item->onClicked))(item, w, item->onClickedData); -} - -static void freeMenu(uiMenu *m, HMENU submenu) -{ - size_t i; - uiMenuItem *item; - size_t j; - - for (i = 0; i < m->len; i++) { - item = m->items[i]; - for (j = 0; j < item->len; j++) - if (item->hmenus[j] == submenu) - break; - if (j >= item->len) - implbug("submenu handle %p not found in freeMenu()", submenu); - for (; j < item->len - 1; j++) - item->hmenus[j] = item->hmenus[j + 1]; - item->hmenus[j] = NULL; - item->len--; - - if (item->popupchild) - freeMenu(item->popupchild, item->popupchild->handle); - } -} - -void freeMenubar(HMENU menubar) -{ - size_t i; - size_t j = 0; - MENUITEMINFOW mi; - - for (i = 0; i < len; i++) - { - if (menus[i]->ischild) continue; - ZeroMemory(&mi, sizeof (MENUITEMINFOW)); - mi.cbSize = sizeof (MENUITEMINFOW); - mi.fMask = MIIM_SUBMENU; - if (GetMenuItemInfoW(menubar, j, TRUE, &mi) == 0) - logLastError(L"error getting menu to delete item references from"); - freeMenu(menus[i], mi.hSubMenu); - j++; - } - // no need to worry about destroying any menus; destruction of the window they're in will do it for us -} - -void uninitMenus(void) -{ - uiMenu *m; - uiMenuItem *item; - size_t i, j; - - for (i = 0; i < len; i++) { - m = menus[i]; - uiFree(m->name); - for (j = 0; j < m->len; j++) { - item = m->items[j]; - if (item->len != 0) - // LONGTERM userbug()? - implbug("menu item %p (%ws) still has uiWindows attached; did you forget to destroy some windows?", item, item->name); - if (item->type != typeSubmenu && item->name != NULL) - uiFree(item->name); - if (item->hmenus != NULL) - uiFree(item->hmenus); - uiFree(item); - } - if (m->items != NULL) - uiFree(m->items); - uiFree(m); - } - if (menus != NULL) - uiFree(menus); -} diff --git a/src/libui_sdl/libui/windows/multilineentry.cpp b/src/libui_sdl/libui/windows/multilineentry.cpp deleted file mode 100644 index a32960cb..00000000 --- a/src/libui_sdl/libui/windows/multilineentry.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// 8 april 2015 -#include "uipriv_windows.hpp" - -// TODO there's alpha darkening of text going on in read-only ones; something is up in our parent logic - -struct uiMultilineEntry { - uiWindowsControl c; - HWND hwnd; - void (*onChanged)(uiMultilineEntry *, void *); - void *onChangedData; - BOOL inhibitChanged; -}; - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiMultilineEntry *e = uiMultilineEntry(c); - - if (code != EN_CHANGE) - return FALSE; - if (e->inhibitChanged) - return FALSE; - (*(e->onChanged))(e, e->onChangedData); - *lResult = 0; - return TRUE; -} - -static void uiMultilineEntryDestroy(uiControl *c) -{ - uiMultilineEntry *e = uiMultilineEntry(c); - - uiWindowsUnregisterWM_COMMANDHandler(e->hwnd); - uiWindowsEnsureDestroyWindow(e->hwnd); - uiFreeControl(uiControl(e)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiMultilineEntry) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define entryWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */ -// LONGTERM change this for multiline text boxes (longterm because how?) -#define entryHeight 14 - -static void uiMultilineEntryMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiMultilineEntry *e = uiMultilineEntry(c); - uiWindowsSizing sizing; - int x, y; - - x = entryWidth; - y = entryHeight; - uiWindowsGetSizing(e->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -static void defaultOnChanged(uiMultilineEntry *e, void *data) -{ - // do nothing -} - -char *uiMultilineEntryText(uiMultilineEntry *e) -{ - char *out; - - out = uiWindowsWindowText(e->hwnd); - CRLFtoLF(out); - return out; -} - -void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text) -{ - char *crlf; - - // doing this raises an EN_CHANGED - e->inhibitChanged = TRUE; - crlf = LFtoCRLF(text); - uiWindowsSetWindowText(e->hwnd, text); - uiFree(crlf); - e->inhibitChanged = FALSE; - // don't queue the control for resize; entry sizes are independent of their contents -} - -void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text) -{ - LRESULT n; - char *crlf; - WCHAR *wtext; - - // doing this raises an EN_CHANGED - e->inhibitChanged = TRUE; - // TODO preserve selection? caret? what if caret used to be at end? - // TODO scroll to bottom? - n = SendMessageW(e->hwnd, WM_GETTEXTLENGTH, 0, 0); - SendMessageW(e->hwnd, EM_SETSEL, n, n); - crlf = LFtoCRLF(text); - wtext = toUTF16(crlf); - uiFree(crlf); - SendMessageW(e->hwnd, EM_REPLACESEL, FALSE, (LPARAM) wtext); - uiFree(wtext); - e->inhibitChanged = FALSE; -} - -void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *, void *), void *data) -{ - e->onChanged = f; - e->onChangedData = data; -} - -int uiMultilineEntryReadOnly(uiMultilineEntry *e) -{ - return (getStyle(e->hwnd) & ES_READONLY) != 0; -} - -void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly) -{ - WPARAM ro; - - ro = (WPARAM) FALSE; - if (readonly) - ro = (WPARAM) TRUE; - if (SendMessage(e->hwnd, EM_SETREADONLY, ro, 0) == 0) - logLastError(L"error making uiMultilineEntry read-only"); -} - -static uiMultilineEntry *finishMultilineEntry(DWORD style) -{ - uiMultilineEntry *e; - - uiWindowsNewControl(uiMultilineEntry, e); - - e->hwnd = uiWindowsEnsureCreateControlHWND(WS_EX_CLIENTEDGE, - L"edit", L"", - ES_AUTOVSCROLL | ES_LEFT | ES_MULTILINE | ES_NOHIDESEL | ES_WANTRETURN | WS_TABSTOP | WS_VSCROLL | style, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_COMMANDHandler(e->hwnd, onWM_COMMAND, uiControl(e)); - uiMultilineEntryOnChanged(e, defaultOnChanged, NULL); - - return e; -} - -uiMultilineEntry *uiNewMultilineEntry(void) -{ - return finishMultilineEntry(0); -} - -uiMultilineEntry *uiNewNonWrappingMultilineEntry(void) -{ - return finishMultilineEntry(WS_HSCROLL | ES_AUTOHSCROLL); -} diff --git a/src/libui_sdl/libui/windows/notes b/src/libui_sdl/libui/windows/notes deleted file mode 100644 index f554dd28..00000000 --- a/src/libui_sdl/libui/windows/notes +++ /dev/null @@ -1,3 +0,0 @@ -DIALOGS -do not accelerate OK and Cancel buttons in dialogs - http://blogs.msdn.com/b/oldnewthing/archive/2008/05/08/8467905.aspx diff --git a/src/libui_sdl/libui/windows/parent.cpp b/src/libui_sdl/libui/windows/parent.cpp deleted file mode 100644 index bde6fb94..00000000 --- a/src/libui_sdl/libui/windows/parent.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// 26 april 2015 -#include "uipriv_windows.hpp" - -// This contains code used by all uiControls that contain other controls. -// It also contains the code to draw the background of a container.c container, as that is a variant of the WM_CTLCOLORxxx handler code. - -static HBRUSH parentBrush = NULL; - -static HWND parentWithBackground(HWND hwnd) -{ - HWND parent; - int cls; - - parent = hwnd; - for (;;) { - parent = parentOf(parent); - // skip groupboxes; they're (supposed to be) transparent - // skip uiContainers; they don't draw anything - cls = windowClassOf(parent, L"button", containerClass, NULL); - if (cls != 0 && cls != 1) - break; - } - return parent; -} - -struct parentDraw { - HDC cdc; - HBITMAP bitmap; - HBITMAP prevbitmap; -}; - -static HRESULT parentDraw(HDC dc, HWND parent, struct parentDraw *pd) -{ - RECT r; - - uiWindowsEnsureGetClientRect(parent, &r); - pd->cdc = CreateCompatibleDC(dc); - if (pd->cdc == NULL) - return logLastError(L"error creating compatible DC"); - pd->bitmap = CreateCompatibleBitmap(dc, r.right - r.left, r.bottom - r.top); - if (pd->bitmap == NULL) - return logLastError(L"error creating compatible bitmap"); - pd->prevbitmap = (HBITMAP) SelectObject(pd->cdc, pd->bitmap); - if (pd->prevbitmap == NULL) - return logLastError(L"error selecting bitmap into compatible DC"); - SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) (pd->cdc), PRF_CLIENT); - return S_OK; -} - -static void endParentDraw(struct parentDraw *pd) -{ - // continue in case of any error - if (pd->prevbitmap != NULL) - if (((HBITMAP) SelectObject(pd->cdc, pd->prevbitmap)) != pd->bitmap) - logLastError(L"error selecting previous bitmap back into compatible DC"); - if (pd->bitmap != NULL) - if (DeleteObject(pd->bitmap) == 0) - logLastError(L"error deleting compatible bitmap"); - if (pd->cdc != NULL) - if (DeleteDC(pd->cdc) == 0) - logLastError(L"error deleting compatible DC"); -} - -// see http://www.codeproject.com/Articles/5978/Correctly-drawn-themed-dialogs-in-WinXP -static HBRUSH getControlBackgroundBrush(HWND hwnd, HDC dc) -{ - HWND parent; - RECT hwndScreenRect; - struct parentDraw pd; - HBRUSH brush; - HRESULT hr; - - parent = parentWithBackground(hwnd); - - hr = parentDraw(dc, parent, &pd); - if (hr != S_OK) - return NULL; - brush = CreatePatternBrush(pd.bitmap); - if (brush == NULL) { - logLastError(L"error creating pattern brush"); - endParentDraw(&pd); - return NULL; - } - endParentDraw(&pd); - - // now figure out where the control is relative to the parent so we can align the brush properly - // if anything fails, give up and return the brush as-is - uiWindowsEnsureGetWindowRect(hwnd, &hwndScreenRect); - // this will be in screen coordinates; convert to parent coordinates - mapWindowRect(NULL, parent, &hwndScreenRect); - if (SetBrushOrgEx(dc, -hwndScreenRect.left, -hwndScreenRect.top, NULL) == 0) - logLastError(L"error setting brush origin"); - - return brush; -} - -void paintContainerBackground(HWND hwnd, HDC dc, RECT *paintRect) -{ - HWND parent; - RECT paintRectParent; - struct parentDraw pd; - HRESULT hr; - - parent = parentWithBackground(hwnd); - hr = parentDraw(dc, parent, &pd); - if (hr != S_OK) // we couldn't get it; draw nothing - return; - - paintRectParent = *paintRect; - mapWindowRect(hwnd, parent, &paintRectParent); - if (BitBlt(dc, paintRect->left, paintRect->top, paintRect->right - paintRect->left, paintRect->bottom - paintRect->top, - pd.cdc, paintRectParent.left, paintRectParent.top, - SRCCOPY) == 0) - logLastError(L"error drawing parent background over uiContainer"); - - endParentDraw(&pd); -} - -// TODO make this public if we want custom containers -// why have this to begin with? http://blogs.msdn.com/b/oldnewthing/archive/2010/03/16/9979112.aspx -BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - switch (uMsg) { - case WM_COMMAND: - return runWM_COMMAND(wParam, lParam, lResult); - case WM_NOTIFY: - return runWM_NOTIFY(wParam, lParam, lResult); - case WM_HSCROLL: - return runWM_HSCROLL(wParam, lParam, lResult); - case WM_CTLCOLORSTATIC: - case WM_CTLCOLORBTN: - if (parentBrush != NULL) - if (DeleteObject(parentBrush) == 0) - logLastError(L"error deleting old background brush()"); // but continue anyway; we will leak a brush but whatever - if (SetBkMode((HDC) wParam, TRANSPARENT) == 0) - logLastError(L"error setting transparent background mode to controls"); // but continue anyway; text will be wrong - parentBrush = getControlBackgroundBrush((HWND) lParam, (HDC) wParam); - if (parentBrush == NULL) // failed; just do default behavior - return FALSE; - *lResult = (LRESULT) parentBrush; - return TRUE; - } - return FALSE; -} diff --git a/src/libui_sdl/libui/windows/progressbar.cpp b/src/libui_sdl/libui/windows/progressbar.cpp deleted file mode 100644 index 3750eb6a..00000000 --- a/src/libui_sdl/libui/windows/progressbar.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// 19 may 2015 -#include "uipriv_windows.hpp" - -struct uiProgressBar { - uiWindowsControl c; - HWND hwnd; -}; - -uiWindowsControlAllDefaults(uiProgressBar) - -// via http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define pbarWidth 237 -#define pbarHeight 8 - -static void uiProgressBarMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiProgressBar *p = uiProgressBar(c); - uiWindowsSizing sizing; - int x, y; - - x = pbarWidth; - y = pbarHeight; - uiWindowsGetSizing(p->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -#define indeterminate(p) ((getStyle(p->hwnd) & PBS_MARQUEE) != 0) - -int uiProgressBarValue(uiProgressBar *p) -{ - if (indeterminate(p)) - return -1; - return SendMessage(p->hwnd, PBM_GETPOS, 0, 0); -} - -// unfortunately, as of Vista progress bars have a forced animation on increase -// we have to set the progress bar to value + 1 and decrease it back to value if we want an "instant" change -// see http://stackoverflow.com/questions/2217688/windows-7-aero-theme-progress-bar-bug -// it's not ideal/perfect, but it will have to do -void uiProgressBarSetValue(uiProgressBar *p, int value) -{ - if (value == -1) { - if (!indeterminate(p)) { - setStyle(p->hwnd, getStyle(p->hwnd) | PBS_MARQUEE); - SendMessageW(p->hwnd, PBM_SETMARQUEE, (WPARAM) TRUE, 0); - } - return; - } - if (indeterminate(p)) { - SendMessageW(p->hwnd, PBM_SETMARQUEE, (WPARAM) FALSE, 0); - setStyle(p->hwnd, getStyle(p->hwnd) & ~PBS_MARQUEE); - } - - if (value < 0 || value > 100) - userbug("Value %d is out of range for uiProgressBars.", value); - - if (value == 100) { // because we can't 101 - SendMessageW(p->hwnd, PBM_SETRANGE32, 0, 101); - SendMessageW(p->hwnd, PBM_SETPOS, 101, 0); - SendMessageW(p->hwnd, PBM_SETPOS, 100, 0); - SendMessageW(p->hwnd, PBM_SETRANGE32, 0, 100); - return; - } - SendMessageW(p->hwnd, PBM_SETPOS, (WPARAM) (value + 1), 0); - SendMessageW(p->hwnd, PBM_SETPOS, (WPARAM) value, 0); -} - -uiProgressBar *uiNewProgressBar(void) -{ - uiProgressBar *p; - - uiWindowsNewControl(uiProgressBar, p); - - p->hwnd = uiWindowsEnsureCreateControlHWND(0, - PROGRESS_CLASSW, L"", - PBS_SMOOTH, - hInstance, NULL, - FALSE); - - return p; -} diff --git a/src/libui_sdl/libui/windows/radiobuttons.cpp b/src/libui_sdl/libui/windows/radiobuttons.cpp deleted file mode 100644 index 29cd2e66..00000000 --- a/src/libui_sdl/libui/windows/radiobuttons.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.hpp" - -// desired behavior: -// - tab moves between the radio buttons and the adjacent controls -// - arrow keys navigate between radio buttons -// - arrow keys do not leave the radio buttons (this is done in control.c) -// - arrow keys wrap around bare groups (if the previous control has WS_GROUP but the first radio button doesn't, then it doesn't; since our radio buttons are all in their own child window we can't do that) -// - clicking on a radio button draws a focus rect (TODO) - -struct uiRadioButtons { - uiWindowsControl c; - HWND hwnd; // of the container - std::vector *hwnds; // of the buttons - void (*onSelected)(uiRadioButtons *, void *); - void *onSelectedData; -}; - -static BOOL onWM_COMMAND(uiControl *c, HWND clicked, WORD code, LRESULT *lResult) -{ - uiRadioButtons *r = uiRadioButtons(c); - WPARAM check; - - if (code != BN_CLICKED) - return FALSE; - for (const HWND &hwnd : *(r->hwnds)) { - check = BST_UNCHECKED; - if (clicked == hwnd) - check = BST_CHECKED; - SendMessage(hwnd, BM_SETCHECK, check, 0); - } - (*(r->onSelected))(r, r->onSelectedData); - *lResult = 0; - return TRUE; -} - -static void defaultOnSelected(uiRadioButtons *r, void *data) -{ - // do nothing -} - -static void uiRadioButtonsDestroy(uiControl *c) -{ - uiRadioButtons *r = uiRadioButtons(c); - - for (const HWND &hwnd : *(r->hwnds)) { - uiWindowsUnregisterWM_COMMANDHandler(hwnd); - uiWindowsEnsureDestroyWindow(hwnd); - } - delete r->hwnds; - uiWindowsEnsureDestroyWindow(r->hwnd); - uiFreeControl(uiControl(r)); -} - -// TODO SyncEnableState -uiWindowsControlAllDefaultsExceptDestroy(uiRadioButtons) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define radiobuttonHeight 10 -// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx -#define radiobuttonXFromLeftOfBoxToLeftOfLabel 12 - -static void uiRadioButtonsMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiRadioButtons *r = uiRadioButtons(c); - int wid, maxwid; - uiWindowsSizing sizing; - int x, y; - - if (r->hwnds->size() == 0) { - *width = 0; - *height = 0; - return; - } - maxwid = 0; - for (const HWND &hwnd : *(r->hwnds)) { - wid = uiWindowsWindowTextWidth(hwnd); - if (maxwid < wid) - maxwid = wid; - } - - x = radiobuttonXFromLeftOfBoxToLeftOfLabel; - y = radiobuttonHeight; - uiWindowsGetSizing((*(r->hwnds))[0], &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - - *width = x + maxwid; - *height = y * r->hwnds->size(); -} - -static void radiobuttonsRelayout(uiRadioButtons *r) -{ - RECT client; - int x, y, width, height; - int height1; - uiWindowsSizing sizing; - - if (r->hwnds->size() == 0) - return; - uiWindowsEnsureGetClientRect(r->hwnd, &client); - x = client.left; - y = client.top; - width = client.right - client.left; - height1 = radiobuttonHeight; - uiWindowsGetSizing((*(r->hwnds))[0], &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, NULL, &height1); - height = height1; - for (const HWND &hwnd : *(r->hwnds)) { - uiWindowsEnsureMoveWindowDuringResize(hwnd, x, y, width, height); - y += height; - } -} - -static void radiobuttonsArrangeChildren(uiRadioButtons *r) -{ - LONG_PTR controlID; - HWND insertAfter; - - controlID = 100; - insertAfter = NULL; - for (const HWND &hwnd : *(r->hwnds)) - uiWindowsEnsureAssignControlIDZOrder(hwnd, &controlID, &insertAfter); -} - -void uiRadioButtonsAppend(uiRadioButtons *r, const char *text) -{ - HWND hwnd; - WCHAR *wtext; - DWORD groupTabStop; - - // the first radio button gets both WS_GROUP and WS_TABSTOP - // successive radio buttons get *neither* - groupTabStop = 0; - if (r->hwnds->size() == 0) - groupTabStop = WS_GROUP | WS_TABSTOP; - - wtext = toUTF16(text); - hwnd = uiWindowsEnsureCreateControlHWND(0, - L"button", wtext, - BS_RADIOBUTTON | groupTabStop, - hInstance, NULL, - TRUE); - uiFree(wtext); - uiWindowsEnsureSetParentHWND(hwnd, r->hwnd); - uiWindowsRegisterWM_COMMANDHandler(hwnd, onWM_COMMAND, uiControl(r)); - r->hwnds->push_back(hwnd); - radiobuttonsArrangeChildren(r); - uiWindowsControlMinimumSizeChanged(uiWindowsControl(r)); -} - -int uiRadioButtonsSelected(uiRadioButtons *r) -{ - size_t i; - - for (i = 0; i < r->hwnds->size(); i++) - if (SendMessage((*(r->hwnds))[i], BM_GETCHECK, 0, 0) == BST_CHECKED) - return i; - return -1; -} - -void uiRadioButtonsSetSelected(uiRadioButtons *r, int n) -{ - int m; - - m = uiRadioButtonsSelected(r); - if (m != -1) - SendMessage((*(r->hwnds))[m], BM_SETCHECK, BST_UNCHECKED, 0); - if (n != -1) - SendMessage((*(r->hwnds))[n], BM_SETCHECK, BST_CHECKED, 0); -} - -void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data) -{ - r->onSelected = f; - r->onSelectedData = data; -} - -static void onResize(uiWindowsControl *c) -{ - radiobuttonsRelayout(uiRadioButtons(c)); -} - -uiRadioButtons *uiNewRadioButtons(void) -{ - uiRadioButtons *r; - - uiWindowsNewControl(uiRadioButtons, r); - - r->hwnd = uiWindowsMakeContainer(uiWindowsControl(r), onResize); - - r->hwnds = new std::vector; - - uiRadioButtonsOnSelected(r, defaultOnSelected, NULL); - - return r; -} diff --git a/src/libui_sdl/libui/windows/resources.hpp b/src/libui_sdl/libui/windows/resources.hpp deleted file mode 100644 index 4ae54725..00000000 --- a/src/libui_sdl/libui/windows/resources.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// 30 may 2015 - -#define rcTabPageDialog 29000 -#define rcFontDialog 29001 -#define rcColorDialog 29002 - -// TODO normalize these - -#define rcFontFamilyCombobox 1000 -#define rcFontStyleCombobox 1001 -#define rcFontSizeCombobox 1002 -#define rcFontSamplePlacement 1003 - -#define rcColorSVChooser 1100 -#define rcColorHSlider 1101 -#define rcPreview 1102 -#define rcOpacitySlider 1103 -#define rcH 1104 -#define rcS 1105 -#define rcV 1106 -#define rcRDouble 1107 -#define rcRInt 1108 -#define rcGDouble 1109 -#define rcGInt 1110 -#define rcBDouble 1111 -#define rcBInt 1112 -#define rcADouble 1113 -#define rcAInt 1114 -#define rcHex 1115 -#define rcHLabel 1116 -#define rcSLabel 1117 -#define rcVLabel 1118 -#define rcRLabel 1119 -#define rcGLabel 1120 -#define rcBLabel 1121 -#define rcALabel 1122 -#define rcHexLabel 1123 diff --git a/src/libui_sdl/libui/windows/resources.rc b/src/libui_sdl/libui/windows/resources.rc deleted file mode 100644 index 989dfc91..00000000 --- a/src/libui_sdl/libui/windows/resources.rc +++ /dev/null @@ -1,96 +0,0 @@ -// 30 may 2015 -#include "winapi.hpp" -#include "resources.hpp" - -// this is a UTF-8 file -#pragma code_page(65001) - -// this is the Common Controls 6 manifest -// we only define it in a shared build; static builds have to include the appropriate parts of the manifest in the output executable -// LONGTERM set up the string values here -#ifndef _UI_STATIC -ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "libui.manifest" -#endif - -// this is the dialog template used by tab pages; see windows/tabpage.c for details -rcTabPageDialog DIALOGEX 0, 0, 100, 100 -STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE -EXSTYLE WS_EX_CONTROLPARENT -BEGIN - // nothing -END - -// this is for our custom DirectWrite-based font dialog (see fontdialog.cpp) -// this is based on the "New Font Dialog with Syslink" in Microsoft's font.dlg -// LONGTERM look at localization -// LONGTERM make it look tighter and nicer like the real one, including the actual heights of the font family and style comboboxes -rcFontDialog DIALOGEX 13, 54, 243, 200 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_3DLOOK -CAPTION "Font" -FONT 9, "Segoe UI" -BEGIN - LTEXT "&Font:", -1, 7, 7, 98, 9 - COMBOBOX rcFontFamilyCombobox, 7, 16, 98, 76, - CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL | - CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS - - LTEXT "Font st&yle:", -1, 114, 7, 74, 9 - COMBOBOX rcFontStyleCombobox, 114, 16, 74, 76, - CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL | - WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS - - LTEXT "&Size:", -1, 198, 7, 36, 9 - COMBOBOX rcFontSizeCombobox, 198, 16, 36, 76, - CBS_SIMPLE | CBS_AUTOHSCROLL | CBS_DISABLENOSCROLL | - CBS_SORT | WS_VSCROLL | WS_TABSTOP | CBS_HASSTRINGS - - GROUPBOX "Sample", -1, 7, 97, 227, 70, WS_GROUP - CTEXT "AaBbYyZz", rcFontSamplePlacement, 9, 106, 224, 60, SS_NOPREFIX | NOT WS_VISIBLE - - DEFPUSHBUTTON "OK", IDOK, 141, 181, 45, 14, WS_GROUP - PUSHBUTTON "Cancel", IDCANCEL, 190, 181, 45, 14, WS_GROUP -END - -rcColorDialog DIALOGEX 13, 54, 344, 209 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_3DLOOK -CAPTION "Color" -FONT 9, "Segoe UI" -BEGIN - // this size should be big enough to get at least 256x256 on font sizes >= 8 pt - CTEXT "AaBbYyZz", rcColorSVChooser, 7, 7, 195, 195, SS_NOPREFIX | SS_BLACKRECT - - // width is the suggested slider height since this is vertical - CTEXT "AaBbYyZz", rcColorHSlider, 206, 7, 15, 195, SS_NOPREFIX | SS_BLACKRECT - - LTEXT "Preview:", -1, 230, 7, 107, 9, SS_NOPREFIX - CTEXT "AaBbYyZz", rcPreview, 230, 16, 107, 20, SS_NOPREFIX | SS_BLACKRECT - - LTEXT "Opacity:", -1, 230, 45, 107, 9, SS_NOPREFIX - CTEXT "AaBbYyZz", rcOpacitySlider, 230, 54, 107, 15, SS_NOPREFIX | SS_BLACKRECT - - LTEXT "&H:", rcHLabel, 230, 81, 8, 8 - EDITTEXT rcH, 238, 78, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - LTEXT "&S:", rcSLabel, 230, 95, 8, 8 - EDITTEXT rcS, 238, 92, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - LTEXT "&V:", rcVLabel, 230, 109, 8, 8 - EDITTEXT rcV, 238, 106, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - - LTEXT "&R:", rcRLabel, 277, 81, 8, 8 - EDITTEXT rcRDouble, 285, 78, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - EDITTEXT rcRInt, 315, 78, 20, 14, ES_LEFT | ES_AUTOHSCROLL | ES_NUMBER | WS_TABSTOP, WS_EX_CLIENTEDGE - LTEXT "&G:", rcGLabel, 277, 95, 8, 8 - EDITTEXT rcGDouble, 285, 92, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - EDITTEXT rcGInt, 315, 92, 20, 14, ES_LEFT | ES_AUTOHSCROLL | ES_NUMBER | WS_TABSTOP, WS_EX_CLIENTEDGE - LTEXT "&B:", rcBLabel, 277, 109, 8, 8 - EDITTEXT rcBDouble, 285, 106, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - EDITTEXT rcBInt, 315, 106, 20, 14, ES_LEFT | ES_AUTOHSCROLL | ES_NUMBER | WS_TABSTOP, WS_EX_CLIENTEDGE - LTEXT "&A:", rcALabel, 277, 123, 8, 8 - EDITTEXT rcADouble, 285, 120, 30, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - EDITTEXT rcAInt, 315, 120, 20, 14, ES_LEFT | ES_AUTOHSCROLL | ES_NUMBER | WS_TABSTOP, WS_EX_CLIENTEDGE - - LTEXT "He&x:", rcHexLabel, 269, 146, 16, 8 - EDITTEXT rcHex, 285, 143, 50, 14, ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP, WS_EX_CLIENTEDGE - - DEFPUSHBUTTON "OK", IDOK, 243, 188, 45, 14, WS_GROUP - PUSHBUTTON "Cancel", IDCANCEL, 292, 188, 45, 14, WS_GROUP -END diff --git a/src/libui_sdl/libui/windows/separator.cpp b/src/libui_sdl/libui/windows/separator.cpp deleted file mode 100644 index e123e275..00000000 --- a/src/libui_sdl/libui/windows/separator.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.hpp" - -// references: -// - http://stackoverflow.com/questions/2892703/how-do-i-draw-separators -// - https://msdn.microsoft.com/en-us/library/windows/desktop/dn742405%28v=vs.85%29.aspx - -struct uiSeparator { - uiWindowsControl c; - HWND hwnd; - BOOL vertical; -}; - -uiWindowsControlAllDefaults(uiSeparator) - -// via https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx -#define separatorHeight 1 - -// TODO -#define separatorWidth 1 - -static void uiSeparatorMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiSeparator *s = uiSeparator(c); - uiWindowsSizing sizing; - int x, y; - - *width = 1; // TODO - *height = 1; - x = separatorWidth; - y = separatorHeight; - uiWindowsGetSizing(s->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - if (s->vertical) - *width = x; - else - *height = y; -} - -uiSeparator *uiNewHorizontalSeparator(void) -{ - uiSeparator *s; - - uiWindowsNewControl(uiSeparator, s); - - s->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"static", L"", - SS_ETCHEDHORZ, - hInstance, NULL, - TRUE); - - return s; -} - -uiSeparator *uiNewVerticalSeparator(void) -{ - uiSeparator *s; - - uiWindowsNewControl(uiSeparator, s); - - s->hwnd = uiWindowsEnsureCreateControlHWND(0, - L"static", L"", - SS_ETCHEDHORZ, - hInstance, NULL, - TRUE); - s->vertical = TRUE; - - return s; -} diff --git a/src/libui_sdl/libui/windows/sizing.cpp b/src/libui_sdl/libui/windows/sizing.cpp deleted file mode 100644 index a6d25d6e..00000000 --- a/src/libui_sdl/libui/windows/sizing.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// 14 may 2015 -#include "uipriv_windows.hpp" - -// TODO rework the error handling -void getSizing(HWND hwnd, uiWindowsSizing *sizing, HFONT font) -{ - HDC dc; - HFONT prevfont; - TEXTMETRICW tm; - SIZE size; - - dc = GetDC(hwnd); - if (dc == NULL) - logLastError(L"error getting DC"); - prevfont = (HFONT) SelectObject(dc, font); - if (prevfont == NULL) - logLastError(L"error loading control font into device context"); - - ZeroMemory(&tm, sizeof (TEXTMETRICW)); - if (GetTextMetricsW(dc, &tm) == 0) - logLastError(L"error getting text metrics"); - if (GetTextExtentPoint32W(dc, L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &size) == 0) - logLastError(L"error getting text extent point"); - - sizing->BaseX = (int) ((size.cx / 26 + 1) / 2); - sizing->BaseY = (int) tm.tmHeight; - sizing->InternalLeading = tm.tmInternalLeading; - - if (SelectObject(dc, prevfont) != font) - logLastError(L"error restoring previous font into device context"); - if (ReleaseDC(hwnd, dc) == 0) - logLastError(L"error releasing DC"); -} - -void uiWindowsGetSizing(HWND hwnd, uiWindowsSizing *sizing) -{ - return getSizing(hwnd, sizing, hMessageFont); -} - -#define dlgUnitsToX(dlg, baseX) MulDiv((dlg), (baseX), 4) -#define dlgUnitsToY(dlg, baseY) MulDiv((dlg), (baseY), 8) - -void uiWindowsSizingDlgUnitsToPixels(uiWindowsSizing *sizing, int *x, int *y) -{ - if (x != NULL) - *x = dlgUnitsToX(*x, sizing->BaseX); - if (y != NULL) - *y = dlgUnitsToY(*y, sizing->BaseY); -} - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing and https://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx -// this X value is really only for buttons but I don't see a better one :/ -#define winXPadding 4 -#define winYPadding 4 - -void uiWindowsSizingStandardPadding(uiWindowsSizing *sizing, int *x, int *y) -{ - if (x != NULL) - *x = dlgUnitsToX(winXPadding, sizing->BaseX); - if (y != NULL) - *y = dlgUnitsToY(winYPadding, sizing->BaseY); -} diff --git a/src/libui_sdl/libui/windows/slider.cpp b/src/libui_sdl/libui/windows/slider.cpp deleted file mode 100644 index 5c671dda..00000000 --- a/src/libui_sdl/libui/windows/slider.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// 20 may 2015 -#include "uipriv_windows.hpp" - -struct uiSlider { - uiWindowsControl c; - HWND hwnd; - void (*onChanged)(uiSlider *, void *); - void *onChangedData; -}; - -static BOOL onWM_HSCROLL(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiSlider *s = uiSlider(c); - - (*(s->onChanged))(s, s->onChangedData); - *lResult = 0; - return TRUE; -} - -static void uiSliderDestroy(uiControl *c) -{ - uiSlider *s = uiSlider(c); - - uiWindowsUnregisterWM_HSCROLLHandler(s->hwnd); - uiWindowsEnsureDestroyWindow(s->hwnd); - uiFreeControl(uiControl(s)); -} - -uiWindowsControlAllDefaultsExceptDestroy(uiSlider); - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define sliderWidth 107 /* this is actually the shorter progress bar width, but Microsoft doesn't indicate a width */ -#define sliderHeight 15 - -static void uiSliderMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiSlider *s = uiSlider(c); - uiWindowsSizing sizing; - int x, y; - - x = sliderWidth; - y = sliderHeight; - uiWindowsGetSizing(s->hwnd, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -static void defaultOnChanged(uiSlider *s, void *data) -{ - // do nothing -} - -int uiSliderValue(uiSlider *s) -{ - return SendMessageW(s->hwnd, TBM_GETPOS, 0, 0); -} - -void uiSliderSetValue(uiSlider *s, int value) -{ - // don't use TBM_SETPOSNOTIFY; that triggers an event - SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) value); -} - -void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *, void *), void *data) -{ - s->onChanged = f; - s->onChangedData = data; -} - -uiSlider *uiNewSlider(int min, int max) -{ - uiSlider *s; - int temp; - - if (min >= max) { - temp = min; - min = max; - max = temp; - } - - uiWindowsNewControl(uiSlider, s); - - s->hwnd = uiWindowsEnsureCreateControlHWND(0, - TRACKBAR_CLASSW, L"", - TBS_HORZ | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND | WS_TABSTOP, - hInstance, NULL, - TRUE); - - uiWindowsRegisterWM_HSCROLLHandler(s->hwnd, onWM_HSCROLL, uiControl(s)); - uiSliderOnChanged(s, defaultOnChanged, NULL); - - SendMessageW(s->hwnd, TBM_SETRANGEMIN, (WPARAM) TRUE, (LPARAM) min); - SendMessageW(s->hwnd, TBM_SETRANGEMAX, (WPARAM) TRUE, (LPARAM) max); - SendMessageW(s->hwnd, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) min); - - return s; -} diff --git a/src/libui_sdl/libui/windows/spinbox.cpp b/src/libui_sdl/libui/windows/spinbox.cpp deleted file mode 100644 index 2b6af66d..00000000 --- a/src/libui_sdl/libui/windows/spinbox.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// 8 april 2015 -#include "uipriv_windows.hpp" - -struct uiSpinbox { - uiWindowsControl c; - HWND hwnd; - HWND edit; - HWND updown; - void (*onChanged)(uiSpinbox *, void *); - void *onChangedData; - BOOL inhibitChanged; -}; - -// utility functions - -static int value(uiSpinbox *s) -{ - BOOL neededCap = FALSE; - LRESULT val; - - // This verifies the value put in, capping it automatically. - // We don't need to worry about checking for an error; that flag should really be called "did we have to cap?". - // We DO need to set the value in case of a cap though. - val = SendMessageW(s->updown, UDM_GETPOS32, 0, (LPARAM) (&neededCap)); - if (neededCap) { - s->inhibitChanged = TRUE; - SendMessageW(s->updown, UDM_SETPOS32, 0, (LPARAM) val); - s->inhibitChanged = FALSE; - } - return val; -} - -// control implementation - -static BOOL onWM_COMMAND(uiControl *c, HWND hwnd, WORD code, LRESULT *lResult) -{ - uiSpinbox *s = (uiSpinbox *) c; - WCHAR *wtext; - - if (code != EN_CHANGE) - return FALSE; - if (s->inhibitChanged) - return FALSE; - // We want to allow typing negative numbers; the natural way to do so is to start with a -. - // However, if we just have the code below, the up-down will catch the bare - and reject it. - // Let's fix that. - // This won't handle leading spaces, but spaces aren't allowed *anyway*. - wtext = windowText(s->edit); - if (wcscmp(wtext, L"-") == 0) { - uiFree(wtext); - return TRUE; - } - uiFree(wtext); - // value() does the work for us - value(s); - (*(s->onChanged))(s, s->onChangedData); - return TRUE; -} - -static void uiSpinboxDestroy(uiControl *c) -{ - uiSpinbox *s = uiSpinbox(c); - - uiWindowsUnregisterWM_COMMANDHandler(s->edit); - uiWindowsEnsureDestroyWindow(s->updown); - uiWindowsEnsureDestroyWindow(s->edit); - uiWindowsEnsureDestroyWindow(s->hwnd); - uiFreeControl(uiControl(s)); -} - -// TODO SyncEnableState -uiWindowsControlAllDefaultsExceptDestroy(uiSpinbox) - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -// TODO reduce this? -#define entryWidth 107 /* this is actually the shorter progress bar width, but Microsoft only indicates as wide as necessary */ -#define entryHeight 14 - -static void uiSpinboxMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiSpinbox *s = uiSpinbox(c); - uiWindowsSizing sizing; - int x, y; - - x = entryWidth; - y = entryHeight; - // note that we go by the edit here - uiWindowsGetSizing(s->edit, &sizing); - uiWindowsSizingDlgUnitsToPixels(&sizing, &x, &y); - *width = x; - *height = y; -} - -static void spinboxArrangeChildren(uiSpinbox *s) -{ - LONG_PTR controlID; - HWND insertAfter; - - controlID = 100; - insertAfter = NULL; - uiWindowsEnsureAssignControlIDZOrder(s->edit, &controlID, &insertAfter); - uiWindowsEnsureAssignControlIDZOrder(s->updown, &controlID, &insertAfter); -} - -// an up-down control will only properly position itself the first time -// stupidly, there are no messages to force a size calculation, nor can I seem to reset the buddy window to force a new position -// alas, we have to make a new up/down control each time :( -static void recreateUpDown(uiSpinbox *s) -{ - BOOL preserve = FALSE; - int current; - // Microsoft's commctrl.h says to use this type - INT min, max; - - if (s->updown != NULL) { - preserve = TRUE; - current = value(s); - SendMessageW(s->updown, UDM_GETRANGE32, (WPARAM) (&min), (LPARAM) (&max)); - uiWindowsEnsureDestroyWindow(s->updown); - } - s->inhibitChanged = TRUE; - s->updown = CreateWindowExW(0, - UPDOWN_CLASSW, L"", - // no WS_VISIBLE; we set visibility ourselves - // up-down control should not be a tab stop - WS_CHILD | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_HOTTRACK | UDS_NOTHOUSANDS | UDS_SETBUDDYINT, - // this is important; it's necessary for autosizing to work - 0, 0, 0, 0, - s->hwnd, NULL, hInstance, NULL); - if (s->updown == NULL) - logLastError(L"error creating updown"); - SendMessageW(s->updown, UDM_SETBUDDY, (WPARAM) (s->edit), 0); - if (preserve) { - SendMessageW(s->updown, UDM_SETRANGE32, (WPARAM) min, (LPARAM) max); - SendMessageW(s->updown, UDM_SETPOS32, 0, (LPARAM) current); - } - // preserve the Z-order - spinboxArrangeChildren(s); - // TODO properly show/enable - ShowWindow(s->updown, SW_SHOW); - s->inhibitChanged = FALSE; -} - -static void spinboxRelayout(uiSpinbox *s) -{ - RECT r; - - // make the edit fill the container first; the new updown will resize it - uiWindowsEnsureGetClientRect(s->hwnd, &r); - uiWindowsEnsureMoveWindowDuringResize(s->edit, r.left, r.top, r.right - r.left, r.bottom - r.top); - recreateUpDown(s); -} - -static void defaultOnChanged(uiSpinbox *s, void *data) -{ - // do nothing -} - -int uiSpinboxValue(uiSpinbox *s) -{ - return value(s); -} - -void uiSpinboxSetValue(uiSpinbox *s, int value) -{ - s->inhibitChanged = TRUE; - SendMessageW(s->updown, UDM_SETPOS32, 0, (LPARAM) value); - s->inhibitChanged = FALSE; -} - -void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *, void *), void *data) -{ - s->onChanged = f; - s->onChangedData = data; -} - -static void onResize(uiWindowsControl *c) -{ - spinboxRelayout(uiSpinbox(c)); -} - -uiSpinbox *uiNewSpinbox(int min, int max) -{ - uiSpinbox *s; - int temp; - - if (min >= max) { - temp = min; - min = max; - max = temp; - } - - uiWindowsNewControl(uiSpinbox, s); - - s->hwnd = uiWindowsMakeContainer(uiWindowsControl(s), onResize); - - s->edit = uiWindowsEnsureCreateControlHWND(WS_EX_CLIENTEDGE, - L"edit", L"", - // don't use ES_NUMBER; it doesn't allow typing in a leading - - ES_AUTOHSCROLL | ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, - hInstance, NULL, - TRUE); - uiWindowsEnsureSetParentHWND(s->edit, s->hwnd); - - uiWindowsRegisterWM_COMMANDHandler(s->edit, onWM_COMMAND, uiControl(s)); - uiSpinboxOnChanged(s, defaultOnChanged, NULL); - - recreateUpDown(s); - s->inhibitChanged = TRUE; - SendMessageW(s->updown, UDM_SETRANGE32, (WPARAM) min, (LPARAM) max); - SendMessageW(s->updown, UDM_SETPOS32, 0, (LPARAM) min); - s->inhibitChanged = FALSE; - - return s; -} diff --git a/src/libui_sdl/libui/windows/stddialogs.cpp b/src/libui_sdl/libui/windows/stddialogs.cpp deleted file mode 100644 index d0fd506a..00000000 --- a/src/libui_sdl/libui/windows/stddialogs.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// 22 may 2015 -#include "uipriv_windows.hpp" - -// TODO document all this is what we want -// TODO do the same for font and color buttons - -// notes: -// - FOS_SUPPORTSTREAMABLEITEMS doesn't seem to be supported on windows vista, or at least not with the flags we use -// - even with FOS_NOVALIDATE the dialogs will reject invalid filenames (at least on Vista, anyway) -// - lack of FOS_NOREADONLYRETURN doesn't seem to matter on Windows 7 - -// TODO -// - http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx -// - when a dialog is active, tab navigation in other windows stops working -// - when adding uiOpenFolder(), use IFileDialog as well - https://msdn.microsoft.com/en-us/library/windows/desktop/bb762115%28v=vs.85%29.aspx - -#define windowHWND(w) (w ? (HWND) uiControlHandle(uiControl(w)) : NULL) - -char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, const char* filter, const char* initpath, FILEOPENDIALOGOPTIONS optsadd) -{ - IFileDialog *d = NULL; - FILEOPENDIALOGOPTIONS opts; - IShellItem *result = NULL; - WCHAR *wname = NULL; - char *name = NULL; - HRESULT hr; - - hr = CoCreateInstance(clsid, - NULL, CLSCTX_INPROC_SERVER, - iid, (LPVOID *) (&d)); - if (hr != S_OK) { - logHRESULT(L"error creating common item dialog", hr); - // always return NULL on error - goto out; - } - hr = d->GetOptions(&opts); - if (hr != S_OK) { - logHRESULT(L"error getting current options", hr); - goto out; - } - opts |= optsadd; - // the other platforms don't check read-only; we won't either - opts &= ~FOS_NOREADONLYRETURN; - hr = d->SetOptions(opts); - if (hr != S_OK) { - logHRESULT(L"error setting options", hr); - goto out; - } - - // filters - { - COMDLG_FILTERSPEC filterspec[8]; - wchar_t _filter[256]; - wchar_t* fp = &_filter[0]; int s = 0; - wchar_t* fname; - for (int i = 0; i < 255; i++) - { - if (filter[i] == '|' || filter[i] == '\0') - { - _filter[i] = '\0'; - if (s & 1) - { - filterspec[s>>1].pszName = fname; - filterspec[s>>1].pszSpec = fp; - } - else - { - fname = fp; - } - fp = &_filter[i+1]; - s++; - if (s >= 8) break; - if (filter[i] == '\0') break; - } - else - _filter[i] = filter[i]; - } - d->SetFileTypes(s>>1, filterspec); - } - - hr = d->Show(parent); - if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) - // cancelled; return NULL like we have ready - goto out; - if (hr != S_OK) { - logHRESULT(L"error showing dialog", hr); - goto out; - } - hr = d->GetResult(&result); - if (hr != S_OK) { - logHRESULT(L"error getting dialog result", hr); - goto out; - } - hr = result->GetDisplayName(SIGDN_FILESYSPATH, &wname); - if (hr != S_OK) { - logHRESULT(L"error getting filename", hr); - goto out; - } - name = toUTF8(wname); - -out: - if (wname != NULL) - CoTaskMemFree(wname); - if (result != NULL) - result->Release(); - if (d != NULL) - d->Release(); - return name; -} - -char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath) -{ - char *res; - - disableAllWindowsExcept(parent); - res = commonItemDialog(windowHWND(parent), - CLSID_FileOpenDialog, IID_IFileOpenDialog, - filter, initpath, - FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); - enableAllWindowsExcept(parent); - return res; -} - -char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath) -{ - char *res; - - disableAllWindowsExcept(parent); - res = commonItemDialog(windowHWND(parent), - CLSID_FileSaveDialog, IID_IFileSaveDialog, - filter, initpath, - FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE); - enableAllWindowsExcept(parent); - return res; -} - -// TODO switch to TaskDialogIndirect()? - -static void msgbox(HWND parent, const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon) -{ - WCHAR *wtitle, *wdescription; - HRESULT hr; - - wtitle = toUTF16(title); - wdescription = toUTF16(description); - - hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, NULL); - if (hr != S_OK) - logHRESULT(L"error showing task dialog", hr); - - uiFree(wdescription); - uiFree(wtitle); -} - -void uiMsgBox(uiWindow *parent, const char *title, const char *description) -{ - disableAllWindowsExcept(parent); - msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, NULL); - enableAllWindowsExcept(parent); -} - -void uiMsgBoxError(uiWindow *parent, const char *title, const char *description) -{ - disableAllWindowsExcept(parent); - msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, TD_ERROR_ICON); - enableAllWindowsExcept(parent); -} diff --git a/src/libui_sdl/libui/windows/tab.cpp b/src/libui_sdl/libui/windows/tab.cpp deleted file mode 100644 index 93373b0a..00000000 --- a/src/libui_sdl/libui/windows/tab.cpp +++ /dev/null @@ -1,294 +0,0 @@ -// 16 may 2015 -#include "uipriv_windows.hpp" - -// You don't add controls directly to a tab control on Windows; instead you make them siblings and swap between them on a TCN_SELCHANGING/TCN_SELCHANGE notification pair. -// In addition, you use dialogs because they can be textured properly; other controls cannot. (Things will look wrong if the tab background in the current theme is fancy if you just use the tab background by itself; see http://stackoverflow.com/questions/30087540/why-are-my-programss-tab-controls-rendering-their-background-in-a-blocky-way-b.) - -struct uiTab { - uiWindowsControl c; - HWND hwnd; // of the outer container - HWND tabHWND; // of the tab control itself - std::vector *pages; - HWND parent; -}; - -// utility functions - -static LRESULT curpage(uiTab *t) -{ - return SendMessageW(t->tabHWND, TCM_GETCURSEL, 0, 0); -} - -static struct tabPage *tabPage(uiTab *t, int i) -{ - return (*(t->pages))[i]; -} - -static void tabPageRect(uiTab *t, RECT *r) -{ - // this rect needs to be in parent window coordinates, but TCM_ADJUSTRECT wants a window rect, which is screen coordinates - // because we have each page as a sibling of the tab, use the tab's own rect as the input rect - uiWindowsEnsureGetWindowRect(t->tabHWND, r); - SendMessageW(t->tabHWND, TCM_ADJUSTRECT, (WPARAM) FALSE, (LPARAM) r); - // and get it in terms of the container instead of the screen - mapWindowRect(NULL, t->hwnd, r); -} - -static void tabRelayout(uiTab *t) -{ - struct tabPage *page; - RECT r; - - // first move the tab control itself - uiWindowsEnsureGetClientRect(t->hwnd, &r); - uiWindowsEnsureMoveWindowDuringResize(t->tabHWND, r.left, r.top, r.right - r.left, r.bottom - r.top); - - // then the current page - if (t->pages->size() == 0) - return; - page = tabPage(t, curpage(t)); - tabPageRect(t, &r); - uiWindowsEnsureMoveWindowDuringResize(page->hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top); -} - -static void showHidePage(uiTab *t, LRESULT which, int hide) -{ - struct tabPage *page; - - if (which == (LRESULT) (-1)) - return; - page = tabPage(t, which); - if (hide) - ShowWindow(page->hwnd, SW_HIDE); - else { - ShowWindow(page->hwnd, SW_SHOW); - // we only resize the current page, so we have to resize it; before we can do that, we need to make sure we are of the right size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(t)); - } -} - -// control implementation - -static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nm, LRESULT *lResult) -{ - uiTab *t = uiTab(c); - - if (nm->code != TCN_SELCHANGING && nm->code != TCN_SELCHANGE) - return FALSE; - showHidePage(t, curpage(t), nm->code == TCN_SELCHANGING); - *lResult = 0; - if (nm->code == TCN_SELCHANGING) - *lResult = FALSE; - return TRUE; -} - -static void uiTabDestroy(uiControl *c) -{ - uiTab *t = uiTab(c); - uiControl *child; - - for (struct tabPage *&page : *(t->pages)) { - child = page->child; - tabPageDestroy(page); - if (child != NULL) { - uiControlSetParent(child, NULL); - uiControlDestroy(child); - } - } - delete t->pages; - uiWindowsUnregisterWM_NOTIFYHandler(t->tabHWND); - uiWindowsEnsureDestroyWindow(t->tabHWND); - uiWindowsEnsureDestroyWindow(t->hwnd); - uiFreeControl(uiControl(t)); -} - -uiWindowsControlDefaultHandle(uiTab) -uiWindowsControlDefaultParent(uiTab) -uiWindowsControlDefaultSetParent(uiTab) -uiWindowsControlDefaultToplevel(uiTab) -uiWindowsControlDefaultVisible(uiTab) -uiWindowsControlDefaultShow(uiTab) -uiWindowsControlDefaultHide(uiTab) -uiWindowsControlDefaultEnabled(uiTab) -uiWindowsControlDefaultEnable(uiTab) -uiWindowsControlDefaultDisable(uiTab) -uiWindowsControlDefaultSetFocus(uiTab) - -static void uiTabSyncEnableState(uiWindowsControl *c, int enabled) -{ - uiTab *t = uiTab(c); - - if (uiWindowsShouldStopSyncEnableState(uiWindowsControl(t), enabled)) - return; - EnableWindow(t->tabHWND, enabled); - for (struct tabPage *&page : *(t->pages)) - if (page->child != NULL) - uiWindowsControlSyncEnableState(uiWindowsControl(page->child), enabled); -} - -uiWindowsControlDefaultSetParentHWND(uiTab) - -static void uiTabMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiTab *t = uiTab(c); - int pagewid, pageht; - struct tabPage *page; - RECT r; - - // only consider the current page - pagewid = 0; - pageht = 0; - if (t->pages->size() != 0) { - page = tabPage(t, curpage(t)); - tabPageMinimumSize(page, &pagewid, &pageht); - } - - r.left = 0; - r.top = 0; - r.right = pagewid; - r.bottom = pageht; - // this also includes the tabs themselves - SendMessageW(t->tabHWND, TCM_ADJUSTRECT, (WPARAM) TRUE, (LPARAM) (&r)); - *width = r.right - r.left; - *height = r.bottom - r.top; -} - -static void uiTabMinimumSizeChanged(uiWindowsControl *c) -{ - uiTab *t = uiTab(c); - - if (uiWindowsControlTooSmall(uiWindowsControl(t))) { - uiWindowsControlContinueMinimumSizeChanged(uiWindowsControl(t)); - return; - } - tabRelayout(t); -} - -static void uiTabSetMinSize(uiControl *c, int w, int h) -{ - // checkme - uiTabMinimumSizeChanged(uiWindowsControl(c)); -} - -uiWindowsControlDefaultLayoutRect(uiTab) -uiWindowsControlDefaultAssignControlIDZOrder(uiTab) - -static void uiTabChildVisibilityChanged(uiWindowsControl *c) -{ - // TODO eliminate the redundancy - uiWindowsControlMinimumSizeChanged(c); -} - -static void tabArrangePages(uiTab *t) -{ - LONG_PTR controlID = 100; - HWND insertAfter = NULL; - - // TODO is this first or last? - uiWindowsEnsureAssignControlIDZOrder(t->tabHWND, &controlID, &insertAfter); - for (struct tabPage *&page : *(t->pages)) - uiWindowsEnsureAssignControlIDZOrder(page->hwnd, &controlID, &insertAfter); -} - -void uiTabAppend(uiTab *t, const char *name, uiControl *child) -{ - uiTabInsertAt(t, name, t->pages->size(), child); -} - -void uiTabInsertAt(uiTab *t, const char *name, int n, uiControl *child) -{ - struct tabPage *page; - LRESULT hide, show; - TCITEMW item; - WCHAR *wname; - - // see below - hide = curpage(t); - - if (child != NULL) - uiControlSetParent(child, uiControl(t)); - - page = newTabPage(child); - uiWindowsEnsureSetParentHWND(page->hwnd, t->hwnd); - t->pages->insert(t->pages->begin() + n, page); - tabArrangePages(t); - - ZeroMemory(&item, sizeof (TCITEMW)); - item.mask = TCIF_TEXT; - wname = toUTF16(name); - item.pszText = wname; - if (SendMessageW(t->tabHWND, TCM_INSERTITEM, (WPARAM) n, (LPARAM) (&item)) == (LRESULT) -1) - logLastError(L"error adding tab to uiTab"); - uiFree(wname); - - // we need to do this because adding the first tab doesn't send a TCN_SELCHANGE; it just shows the page - show = curpage(t); - if (show != hide) { - showHidePage(t, hide, 1); - showHidePage(t, show, 0); - } -} - -void uiTabDelete(uiTab *t, int n) -{ - struct tabPage *page; - - // first delete the tab from the tab control - // if this is the current tab, no tab will be selected, which is good - if (SendMessageW(t->tabHWND, TCM_DELETEITEM, (WPARAM) n, 0) == FALSE) - logLastError(L"error deleting uiTab tab"); - - // now delete the page itself - page = tabPage(t, n); - if (page->child != NULL) - uiControlSetParent(page->child, NULL); - tabPageDestroy(page); - t->pages->erase(t->pages->begin() + n); -} - -int uiTabNumPages(uiTab *t) -{ - return t->pages->size(); -} - -int uiTabMargined(uiTab *t, int n) -{ - return tabPage(t, n)->margined; -} - -void uiTabSetMargined(uiTab *t, int n, int margined) -{ - struct tabPage *page; - - page = tabPage(t, n); - page->margined = margined; - // even if the page doesn't have a child it might still have a new minimum size with margins; this is the easiest way to verify it - uiWindowsControlMinimumSizeChanged(uiWindowsControl(t)); -} - -static void onResize(uiWindowsControl *c) -{ - tabRelayout(uiTab(c)); -} - -uiTab *uiNewTab(void) -{ - uiTab *t; - - uiWindowsNewControl(uiTab, t); - - t->hwnd = uiWindowsMakeContainer(uiWindowsControl(t), onResize); - - t->tabHWND = uiWindowsEnsureCreateControlHWND(0, - WC_TABCONTROLW, L"", - TCS_TOOLTIPS | WS_TABSTOP, - hInstance, NULL, - TRUE); - uiWindowsEnsureSetParentHWND(t->tabHWND, t->hwnd); - - uiWindowsRegisterWM_NOTIFYHandler(t->tabHWND, onWM_NOTIFY, uiControl(t)); - - t->pages = new std::vector; - - return t; -} diff --git a/src/libui_sdl/libui/windows/tabpage.cpp b/src/libui_sdl/libui/windows/tabpage.cpp deleted file mode 100644 index 5283ce79..00000000 --- a/src/libui_sdl/libui/windows/tabpage.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// 30 may 2015 -#include "uipriv_windows.hpp" - -// TODO refine error handling - -// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb226818%28v=vs.85%29.aspx -#define tabMargin 7 - -static void tabPageMargins(struct tabPage *tp, int *mx, int *my) -{ - uiWindowsSizing sizing; - - *mx = 0; - *my = 0; - if (!tp->margined) - return; - uiWindowsGetSizing(tp->hwnd, &sizing); - *mx = tabMargin; - *my = tabMargin; - uiWindowsSizingDlgUnitsToPixels(&sizing, mx, my); -} - -static void tabPageRelayout(struct tabPage *tp) -{ - RECT r; - int mx, my; - HWND child; - - if (tp->child == NULL) - return; - uiWindowsEnsureGetClientRect(tp->hwnd, &r); - tabPageMargins(tp, &mx, &my); - r.left += mx; - r.top += my; - r.right -= mx; - r.bottom -= my; - child = (HWND) uiControlHandle(tp->child); - uiWindowsEnsureMoveWindowDuringResize(child, r.left, r.top, r.right - r.left, r.bottom - r.top); -} - -// dummy dialog procedure; see below for details -// let's handle parent messages here to avoid needing to subclass -// TODO do we need to handle DM_GETDEFID/DM_SETDEFID here too because of the ES_WANTRETURN stuff at http://blogs.msdn.com/b/oldnewthing/archive/2007/08/20/4470527.aspx? what about multiple default buttons (TODO)? -// TODO we definitely need to do something about edit message handling; it does a fake close of our parent on pressing escape, causing uiWindow to stop responding to maximizes but still respond to events and then die horribly on destruction -static INT_PTR CALLBACK dlgproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - struct tabPage *tp; - LRESULT lResult; - - if (uMsg == WM_INITDIALOG) { - tp = (struct tabPage *) lParam; - tp->hwnd = hwnd; - SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR) tp); - return TRUE; - } - if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) { - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONG_PTR) lResult); - return TRUE; - } - if (uMsg == WM_WINDOWPOSCHANGED) { - tp = (struct tabPage *) GetWindowLongPtrW(hwnd, DWLP_USER); - tabPageRelayout(tp); - // pretend the dialog hasn't handled this just in case it needs to do something special - return FALSE; - } - - // unthemed dialogs don't respond to WM_PRINTCLIENT - // fortunately they don't have any special painting - if (uMsg == WM_PRINTCLIENT) { - // don't worry about the return value; hopefully DefWindowProcW() caught it (if not the dialog procedure itself) - // we COULD paint the dialog background brush ourselves but meh, it works - SendMessageW(hwnd, WM_ERASEBKGND, wParam, lParam); - // and pretend we did nothing just so the themed dialog can still paint its content - // TODO see if w ecan avoid erasing the background in this case in the first place, or if we even need to - return FALSE; - } - - return FALSE; -} - -struct tabPage *newTabPage(uiControl *child) -{ - struct tabPage *tp; - HRESULT hr; - - tp = uiNew(struct tabPage); - - // unfortunately this needs to be a proper dialog for EnableThemeDialogTexture() to work; CreateWindowExW() won't suffice - if (CreateDialogParamW(hInstance, MAKEINTRESOURCE(rcTabPageDialog), - utilWindow, dlgproc, (LPARAM) tp) == NULL) - logLastError(L"error creating tab page"); - - tp->child = child; - if (tp->child != NULL) { - uiWindowsEnsureSetParentHWND((HWND) uiControlHandle(tp->child), tp->hwnd); - uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl(tp->child)); - } - - hr = EnableThemeDialogTexture(tp->hwnd, ETDT_ENABLE | ETDT_USETABTEXTURE | ETDT_ENABLETAB); - if (hr != S_OK) - logHRESULT(L"error setting tab page background", hr); - // continue anyway; it'll look wrong but eh - - // and start the tab page hidden - ShowWindow(tp->hwnd, SW_HIDE); - - return tp; -} - -void tabPageDestroy(struct tabPage *tp) -{ - // don't destroy the child with the page - if (tp->child != NULL) - uiWindowsControlSetParentHWND(uiWindowsControl(tp->child), NULL); - // don't call EndDialog(); that's for the DialogBox() family of functions instead of CreateDialog() - uiWindowsEnsureDestroyWindow(tp->hwnd); - uiFree(tp); -} - -void tabPageMinimumSize(struct tabPage *tp, int *width, int *height) -{ - int mx, my; - - *width = 0; - *height = 0; - if (tp->child != NULL) - uiWindowsControlMinimumSize(uiWindowsControl(tp->child), width, height); - tabPageMargins(tp, &mx, &my); - *width += 2 * mx; - *height += 2 * my; -} diff --git a/src/libui_sdl/libui/windows/text.cpp b/src/libui_sdl/libui/windows/text.cpp deleted file mode 100644 index a52af103..00000000 --- a/src/libui_sdl/libui/windows/text.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// 9 april 2015 -#include "uipriv_windows.hpp" - -WCHAR *windowTextAndLen(HWND hwnd, LRESULT *len) -{ - LRESULT n; - WCHAR *text; - - n = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0); - if (len != NULL) - *len = n; - // WM_GETTEXTLENGTH does not include the null terminator - text = (WCHAR *) uiAlloc((n + 1) * sizeof (WCHAR), "WCHAR[]"); - // note the comparison: the size includes the null terminator, but the return does not - if (GetWindowTextW(hwnd, text, n + 1) != n) { - logLastError(L"error getting window text"); - // on error, return an empty string to be safe - *text = L'\0'; - if (len != NULL) - *len = 0; - } - return text; -} - -WCHAR *windowText(HWND hwnd) -{ - return windowTextAndLen(hwnd, NULL); -} - -void setWindowText(HWND hwnd, WCHAR *wtext) -{ - SetWindowTextW(hwnd, wtext); -} - -void uiFreeText(char *text) -{ - uiFree(text); -} - -int uiWindowsWindowTextWidth(HWND hwnd) -{ - LRESULT len; - WCHAR *text; - HDC dc; - HFONT prevfont; - SIZE size; - - size.cx = 0; - size.cy = 0; - - text = windowTextAndLen(hwnd, &len); - if (len == 0) // no text; nothing to do - goto noTextOrError; - - // now we can do the calculations - dc = GetDC(hwnd); - if (dc == NULL) { - logLastError(L"error getting DC"); - // on any error, assume no text - goto noTextOrError; - } - prevfont = (HFONT) SelectObject(dc, hMessageFont); - if (prevfont == NULL) { - logLastError(L"error loading control font into device context"); - ReleaseDC(hwnd, dc); - goto noTextOrError; - } - if (GetTextExtentPoint32W(dc, text, len, &size) == 0) { - logLastError(L"error getting text extent point"); - // continue anyway, assuming size is 0 - size.cx = 0; - size.cy = 0; - } - // continue on errors; we got what we want - if (SelectObject(dc, prevfont) != hMessageFont) - logLastError(L"error restoring previous font into device context"); - if (ReleaseDC(hwnd, dc) == 0) - logLastError(L"error releasing DC"); - - uiFree(text); - return size.cx; - -noTextOrError: - uiFree(text); - return 0; -} - -char *uiWindowsWindowText(HWND hwnd) -{ - WCHAR *wtext; - char *text; - - wtext = windowText(hwnd); - text = toUTF8(wtext); - uiFree(wtext); - return text; -} - -void uiWindowsSetWindowText(HWND hwnd, const char *text) -{ - WCHAR *wtext; - - wtext = toUTF16(text); - setWindowText(hwnd, wtext); - uiFree(wtext); -} diff --git a/src/libui_sdl/libui/windows/uipriv_windows.hpp b/src/libui_sdl/libui/windows/uipriv_windows.hpp deleted file mode 100644 index 6ffe09f1..00000000 --- a/src/libui_sdl/libui/windows/uipriv_windows.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// 21 april 2016 -#include "winapi.hpp" -#include "../ui.h" -#include "../ui_windows.h" -#include "../common/uipriv.h" -#include "resources.hpp" -#include "compilerver.hpp" - -// ui internal window messages -enum { - // redirected WM_COMMAND and WM_NOTIFY - msgCOMMAND = WM_APP + 0x40, // start offset just to be safe - msgNOTIFY, - msgHSCROLL, - msgQueued, - msgD2DScratchPaint, - msgD2DScratchLButtonDown, -}; - -// alloc.cpp -extern void initAlloc(void); -extern void uninitAlloc(void); - -// events.cpp -extern BOOL runWM_COMMAND(WPARAM wParam, LPARAM lParam, LRESULT *lResult); -extern BOOL runWM_NOTIFY(WPARAM wParam, LPARAM lParam, LRESULT *lResult); -extern BOOL runWM_HSCROLL(WPARAM wParam, LPARAM lParam, LRESULT *lResult); -extern void issueWM_WININICHANGE(WPARAM wParam, LPARAM lParam); - -// utf16.cpp -#define emptyUTF16() ((WCHAR *) uiAlloc(1 * sizeof (WCHAR), "WCHAR[]")) -#define emptyUTF8() ((char *) uiAlloc(1 * sizeof (char), "char[]")) -extern WCHAR *toUTF16(const char *str); -extern char *toUTF8(const WCHAR *wstr); -extern WCHAR *utf16dup(const WCHAR *orig); -extern WCHAR *strf(const WCHAR *format, ...); -extern WCHAR *vstrf(const WCHAR *format, va_list ap); -extern char *LFtoCRLF(const char *lfonly); -extern void CRLFtoLF(char *s); -extern WCHAR *ftoutf16(double d); -extern WCHAR *itoutf16(int i); - -// debug.cpp -// see http://stackoverflow.com/questions/14421656/is-there-widely-available-wide-character-variant-of-file -// we turn __LINE__ into a string because PRIiMAX can't be converted to a wide string in MSVC (it seems to be defined as "ll" "i" according to the compiler errors) -// also note the use of __FUNCTION__ here; __func__ doesn't seem to work for some reason -#define _ws2(m) L ## m -#define _ws(m) _ws2(m) -#define _ws2n(m) L ## #m -#define _wsn(m) _ws2n(m) -#define debugargs const WCHAR *file, const WCHAR *line, const WCHAR *func -extern HRESULT _logLastError(debugargs, const WCHAR *s); -#ifdef _MSC_VER -#define logLastError(s) _logLastError(_ws(__FILE__), _wsn(__LINE__), _ws(__FUNCTION__), s) -#else -#define logLastError(s) _logLastError(_ws(__FILE__), _wsn(__LINE__), L"TODO none of the function name macros are macros in MinGW", s) -#endif -extern HRESULT _logHRESULT(debugargs, const WCHAR *s, HRESULT hr); -#ifdef _MSC_VER -#define logHRESULT(s, hr) _logHRESULT(_ws(__FILE__), _wsn(__LINE__), _ws(__FUNCTION__), s, hr) -#else -#define logHRESULT(s, hr) _logHRESULT(_ws(__FILE__), _wsn(__LINE__), L"TODO none of the function name macros are macros in MinGW", s, hr) -#endif - -// winutil.cpp -extern int windowClassOf(HWND hwnd, ...); -extern void mapWindowRect(HWND from, HWND to, RECT *r); -extern DWORD getStyle(HWND hwnd); -extern void setStyle(HWND hwnd, DWORD style); -extern DWORD getExStyle(HWND hwnd); -extern void setExStyle(HWND hwnd, DWORD exstyle); -extern void clientSizeToWindowSize(HWND hwnd, int *width, int *height, BOOL hasMenubar); -extern HWND parentOf(HWND child); -extern HWND parentToplevel(HWND child); -extern void setWindowInsertAfter(HWND hwnd, HWND insertAfter); -extern HWND getDlgItem(HWND hwnd, int id); -extern void invalidateRect(HWND hwnd, RECT *r, BOOL erase); - -// text.cpp -extern WCHAR *windowTextAndLen(HWND hwnd, LRESULT *len); -extern WCHAR *windowText(HWND hwnd); -extern void setWindowText(HWND hwnd, WCHAR *wtext); - -// init.cpp -extern HINSTANCE hInstance; -extern int nCmdShow; -extern HFONT hMessageFont; -extern HBRUSH hollowBrush; -extern uiInitOptions options; - -// utilwin.cpp -extern HWND utilWindow; -extern const char *initUtilWindow(HICON hDefaultIcon, HCURSOR hDefaultCursor); -extern void uninitUtilWindow(void); - -// main.cpp -extern int registerMessageFilter(void); -extern void unregisterMessageFilter(void); - -// parent.cpp -extern void paintContainerBackground(HWND hwnd, HDC dc, RECT *paintRect); -extern BOOL handleParentMessages(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult); - -// d2dscratch.cpp -extern ATOM registerD2DScratchClass(HICON hDefaultIcon, HCURSOR hDefaultCursor); -extern void unregisterD2DScratchClass(void); -extern HWND newD2DScratch(HWND parent, RECT *rect, HMENU controlID, SUBCLASSPROC subclass, DWORD_PTR subclassData); - -// area.cpp -#define areaClass L"libui_uiAreaClass" -extern ATOM registerAreaClass(HICON, HCURSOR); -extern void unregisterArea(void); - -// areaevents.cpp -extern BOOL areaFilter(MSG *); - -// window.cpp -extern ATOM registerWindowClass(HICON, HCURSOR); -extern void unregisterWindowClass(void); -extern void ensureMinimumWindowSize(uiWindow *); -extern void disableAllWindowsExcept(uiWindow *which); -extern void enableAllWindowsExcept(uiWindow *which); - -// container.cpp -#define containerClass L"libui_uiContainerClass" -extern ATOM initContainer(HICON, HCURSOR); -extern void uninitContainer(void); - -// tabpage.cpp -struct tabPage { - HWND hwnd; - uiControl *child; - BOOL margined; -}; -extern struct tabPage *newTabPage(uiControl *child); -extern void tabPageDestroy(struct tabPage *tp); -extern void tabPageMinimumSize(struct tabPage *tp, int *width, int *height); - -// colordialog.cpp -struct colorDialogRGBA { - double r; - double g; - double b; - double a; -}; -extern BOOL showColorDialog(HWND parent, struct colorDialogRGBA *c); - -// sizing.cpp -extern void getSizing(HWND hwnd, uiWindowsSizing *sizing, HFONT font); - -// graphemes.cpp -extern size_t *graphemes(WCHAR *msg); - -// TODO move into a dedicated file abibugs.cpp when we rewrite the drawing code -extern D2D1_SIZE_F realGetSize(ID2D1RenderTarget *rt); - - - - -// TODO -#include "_uipriv_migrate.hpp" - -// draw.cpp -extern ID2D1DCRenderTarget *makeHDCRenderTarget(HDC dc, RECT *r); diff --git a/src/libui_sdl/libui/windows/utf16.cpp b/src/libui_sdl/libui/windows/utf16.cpp deleted file mode 100644 index 98954d0a..00000000 --- a/src/libui_sdl/libui/windows/utf16.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// 21 april 2016 -#include "uipriv_windows.hpp" - -// see http://stackoverflow.com/a/29556509/3408572 - -#define MBTWC(str, wstr, bufsiz) MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, bufsiz) - -WCHAR *toUTF16(const char *str) -{ - WCHAR *wstr; - int n; - - if (*str == '\0') // empty string - return emptyUTF16(); - n = MBTWC(str, NULL, 0); - if (n == 0) { - logLastError(L"error figuring out number of characters to convert to"); - return emptyUTF16(); - } - wstr = (WCHAR *) uiAlloc(n * sizeof (WCHAR), "WCHAR[]"); - if (MBTWC(str, wstr, n) != n) { - logLastError(L"error converting from UTF-8 to UTF-16"); - // and return an empty string - *wstr = L'\0'; - } - return wstr; -} - -#define WCTMB(wstr, str, bufsiz) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, bufsiz, NULL, NULL) - -char *toUTF8(const WCHAR *wstr) -{ - char *str; - int n; - - if (*wstr == L'\0') // empty string - return emptyUTF8(); - n = WCTMB(wstr, NULL, 0); - if (n == 0) { - logLastError(L"error figuring out number of characters to convert to"); - return emptyUTF8(); - } - str = (char *) uiAlloc(n * sizeof (char), "char[]"); - if (WCTMB(wstr, str, n) != n) { - logLastError(L"error converting from UTF-16 to UTF-8"); - // and return an empty string - *str = '\0'; - } - return str; -} - -WCHAR *utf16dup(const WCHAR *orig) -{ - WCHAR *out; - size_t len; - - len = wcslen(orig); - out = (WCHAR *) uiAlloc((len + 1) * sizeof (WCHAR), "WCHAR[]"); - wcscpy_s(out, len + 1, orig); - return out; -} - -WCHAR *strf(const WCHAR *format, ...) -{ - va_list ap; - WCHAR *str; - - va_start(ap, format); - str = vstrf(format, ap); - va_end(ap); - return str; -} - -WCHAR *vstrf(const WCHAR *format, va_list ap) -{ - va_list ap2; - WCHAR *buf; - size_t n; - - if (*format == L'\0') - return emptyUTF16(); - - va_copy(ap2, ap); - n = _vscwprintf(format, ap2); - va_end(ap2); - n++; // terminating L'\0' - - buf = (WCHAR *) uiAlloc(n * sizeof (WCHAR), "WCHAR[]"); - // includes terminating L'\0' according to example in https://msdn.microsoft.com/en-us/library/xa1a1a6z.aspx - vswprintf_s(buf, n, format, ap); - - return buf; -} - -// Let's shove these utility routines here too. -// Prerequisite: lfonly is UTF-8. -char *LFtoCRLF(const char *lfonly) -{ - char *crlf; - size_t i, len; - char *out; - - len = strlen(lfonly); - crlf = (char *) uiAlloc((len * 2 + 1) * sizeof (char), "char[]"); - out = crlf; - for (i = 0; i < len; i++) { - if (*lfonly == '\n') - *crlf++ = '\r'; - *crlf++ = *lfonly++; - } - *crlf = '\0'; - return out; -} - -// Prerequisite: s is UTF-8. -void CRLFtoLF(char *s) -{ - char *t = s; - - for (; *s != '\0'; s++) { - // be sure to preserve \rs that are genuinely there - if (*s == '\r' && *(s + 1) == '\n') - continue; - *t++ = *s; - } - *t = '\0'; - // pad out the rest of t, just to be safe - while (t != s) - *t++ = '\0'; -} - -// std::to_string() always uses %f; we want %g -// fortunately std::iostream seems to use %g by default so -WCHAR *ftoutf16(double d) -{ - std::wostringstream ss; - std::wstring s; - - ss << d; - s = ss.str(); // to be safe - return utf16dup(s.c_str()); -} - -// to complement the above -WCHAR *itoutf16(int i) -{ - std::wostringstream ss; - std::wstring s; - - ss << i; - s = ss.str(); // to be safe - return utf16dup(s.c_str()); -} diff --git a/src/libui_sdl/libui/windows/utilwin.cpp b/src/libui_sdl/libui/windows/utilwin.cpp deleted file mode 100644 index 414ae83a..00000000 --- a/src/libui_sdl/libui/windows/utilwin.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// 14 may 2015 -#include "uipriv_windows.hpp" - -// The utility window is a special window that performs certain tasks internal to libui. -// It is not a message-only window, and it is always hidden and disabled. -// Its roles: -// - It is the initial parent of all controls. When a control loses its parent, it also becomes that control's parent. -// - It handles WM_QUERYENDSESSION and console end session requests. -// - It handles WM_WININICHANGE and forwards the message to any child windows that request it. -// - It handles executing functions queued to run by uiQueueMain(). - -#define utilWindowClass L"libui_utilWindowClass" - -HWND utilWindow; - -static LRESULT CALLBACK utilWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - void (*qf)(void *); - LRESULT lResult; - - if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - switch (uMsg) { - case WM_QUERYENDSESSION: - // TODO block handler - if (shouldQuit()) { - uiQuit(); - return TRUE; - } - return FALSE; - case WM_WININICHANGE: - issueWM_WININICHANGE(wParam, lParam); - return 0; - case msgQueued: - qf = (void (*)(void *)) wParam; - (*qf)((void *) lParam); - return 0; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -const char *initUtilWindow(HICON hDefaultIcon, HCURSOR hDefaultCursor) -{ - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = utilWindowClass; - wc.lpfnWndProc = utilWindowWndProc; - wc.hInstance = hInstance; - wc.hIcon = hDefaultIcon; - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - if (RegisterClass(&wc) == 0) - // see init.cpp for an explanation of the =s - return "=registering utility window class"; - - utilWindow = CreateWindowExW(0, - utilWindowClass, L"libui utility window", - WS_OVERLAPPEDWINDOW, - 0, 0, 100, 100, - NULL, NULL, hInstance, NULL); - if (utilWindow == NULL) - return "=creating utility window"; - // and just to be safe - EnableWindow(utilWindow, FALSE); - - return NULL; -} - -void uninitUtilWindow(void) -{ - if (DestroyWindow(utilWindow) == 0) - logLastError(L"error destroying utility window"); - if (UnregisterClass(utilWindowClass, hInstance) == 0) - logLastError(L"error unregistering utility window class"); -} diff --git a/src/libui_sdl/libui/windows/winapi.hpp b/src/libui_sdl/libui/windows/winapi.hpp deleted file mode 100644 index d31547ad..00000000 --- a/src/libui_sdl/libui/windows/winapi.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// 31 may 2015 -#define UNICODE -#define _UNICODE -#define STRICT -#define STRICT_TYPED_ITEMIDS - -// see https://github.com/golang/go/issues/9916#issuecomment-74812211 -// TODO get rid of this -#define INITGUID - -// for the manifest -#ifndef _UI_STATIC -#define ISOLATION_AWARE_ENABLED 1 -#endif - -// get Windows version right; right now Windows Vista -// unless otherwise stated, all values from Microsoft's sdkddkver.h -// TODO is all of this necessary? how is NTDDI_VERSION used? -// TODO plaform update sp2 -#define WINVER 0x0600 /* from Microsoft's winnls.h */ -#define _WIN32_WINNT 0x0600 -#define _WIN32_WINDOWS 0x0600 /* from Microsoft's pdh.h */ -#define _WIN32_IE 0x0700 -#define NTDDI_VERSION 0x06000000 - -#include - -// Microsoft's resource compiler will segfault if we feed it headers it was not designed to handle -#ifndef RC_INVOKED -#include -#include -#include -#include -// workaround for MinGW builds -> https://stackoverflow.com/questions/27888109/rendertarget-getsize-not-working -#ifdef __MINGW32__ -#define WIDL_EXPLICIT_AGGREGATE_RETURNS -#endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#endif diff --git a/src/libui_sdl/libui/windows/window.cpp b/src/libui_sdl/libui/windows/window.cpp deleted file mode 100644 index a8f7f234..00000000 --- a/src/libui_sdl/libui/windows/window.cpp +++ /dev/null @@ -1,665 +0,0 @@ -// 27 april 2015 -#include "uipriv_windows.hpp" - -#define windowClass L"libui_uiWindowClass" - -struct uiWindow { - uiWindowsControl c; - HWND hwnd; - HMENU menubar; - uiControl *child; - BOOL shownOnce; - int visible; - int margined; - BOOL hasMenubar; - BOOL changingSize; - int maximized; - int fullscreen; - WINDOWPLACEMENT fsPrevPlacement; - int borderless; - - int (*onClosing)(uiWindow *, void *); - void *onClosingData; - void (*onContentSizeChanged)(uiWindow *, void *); - void *onContentSizeChangedData; - void (*onDropFile)(uiWindow *, char *, void *); - void *onDropFileData; - void (*onGetFocus)(uiWindow *, void *); - void *onGetFocusData; - void (*onLoseFocus)(uiWindow *, void *); - void *onLoseFocusData; -}; - -// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing -#define windowMargin 7 - -static void windowMargins(uiWindow *w, int *mx, int *my) -{ - uiWindowsSizing sizing; - - *mx = 0; - *my = 0; - if (!w->margined) - return; - uiWindowsGetSizing(w->hwnd, &sizing); - *mx = windowMargin; - *my = windowMargin; - uiWindowsSizingDlgUnitsToPixels(&sizing, mx, my); -} - -static void windowRelayout(uiWindow *w) -{ - int x, y, width, height; - RECT r; - int mx, my; - HWND child; - - if (w->child == NULL) - return; - x = 0; - y = 0; - uiWindowsEnsureGetClientRect(w->hwnd, &r); - width = r.right - r.left; - height = r.bottom - r.top; - windowMargins(w, &mx, &my); - x += mx; - y += my; - width -= 2 * mx; - height -= 2 * my; - child = (HWND) uiControlHandle(w->child); - uiWindowsEnsureMoveWindowDuringResize(child, x, y, width, height); -} - -static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - LONG_PTR ww; - uiWindow *w; - CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; - WINDOWPOS *wp = (WINDOWPOS *) lParam; - MINMAXINFO *mmi = (MINMAXINFO *) lParam; - int width, height; - LRESULT lResult; - - ww = GetWindowLongPtrW(hwnd, GWLP_USERDATA); - if (ww == 0) { - if (uMsg == WM_CREATE) - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) (cs->lpCreateParams)); - // fall through to DefWindowProc() anyway - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } - w = uiWindow((void *) ww); - if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE) - return lResult; - switch (uMsg) { - case WM_COMMAND: - // not a menu - if (lParam != 0) - break; - if (HIWORD(wParam) != 0 || LOWORD(wParam) <= IDCANCEL) - break; - runMenuEvent(LOWORD(wParam), uiWindow(w)); - return 0; - case WM_WINDOWPOSCHANGED: - if ((wp->flags & SWP_NOSIZE) != 0) - break; - if (w->onContentSizeChanged != NULL) // TODO figure out why this is happening too early - if (!w->changingSize) - (*(w->onContentSizeChanged))(w, w->onContentSizeChangedData); - windowRelayout(w); - return 0; - case WM_GETMINMAXINFO: - // ensure the user cannot resize the window smaller than its minimum size - lResult = DefWindowProcW(hwnd, uMsg, wParam, lParam); - uiWindowsControlMinimumSize(uiWindowsControl(w), &width, &height); - // width and height are in client coordinates; ptMinTrackSize is in window coordinates - clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar); - mmi->ptMinTrackSize.x = width; - mmi->ptMinTrackSize.y = height; - return lResult; - - case WM_DROPFILES: - if (w->onDropFile) - { - HDROP eggdrop = (HDROP)wParam; - WCHAR filename[1024]; - DragQueryFile(eggdrop, 0, filename, 1024); - - char* filename8 = toUTF8(filename); - w->onDropFile(w, filename8, w->onDropFileData); - uiFreeText(filename8); - - DragFinish(eggdrop); - } - break; - - case WM_SETFOCUS: - if (w->onGetFocus) - { - w->onGetFocus(w, w->onGetFocusData); - return 0; - } - break; - case WM_KILLFOCUS: - if (w->onLoseFocus) - { - w->onLoseFocus(w, w->onLoseFocusData); - return 0; - } - break; - - case WM_PRINTCLIENT: - // we do no special painting; just erase the background - // don't worry about the return value; we let DefWindowProcW() handle this message - SendMessageW(hwnd, WM_ERASEBKGND, wParam, lParam); - return 0; - case WM_CLOSE: - if ((*(w->onClosing))(w, w->onClosingData)) - uiControlDestroy(uiControl(w)); - return 0; // we destroyed it already - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -ATOM registerWindowClass(HICON hDefaultIcon, HCURSOR hDefaultCursor) -{ - WNDCLASSW wc; - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = windowClass; - wc.lpfnWndProc = windowWndProc; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(100)); - wc.hCursor = hDefaultCursor; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - return RegisterClassW(&wc); -} - -void unregisterWindowClass(void) -{ - if (UnregisterClassW(windowClass, hInstance) == 0) - logLastError(L"error unregistering uiWindow window class"); -} - -static int defaultOnClosing(uiWindow *w, void *data) -{ - return 0; -} - -static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data) -{ - // do nothing -} - -static std::map windows; - -static void uiWindowDestroy(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - // first hide ourselves - ShowWindow(w->hwnd, SW_HIDE); - // now destroy the child - if (w->child != NULL) { - uiControlSetParent(w->child, NULL); - uiControlDestroy(w->child); - } - // now free the menubar, if any - if (w->menubar != NULL) - freeMenubar(w->menubar); - // and finally free ourselves - windows.erase(w); - uiWindowsEnsureDestroyWindow(w->hwnd); - uiFreeControl(uiControl(w)); -} - -uiWindowsControlDefaultHandle(uiWindow) - -uiControl *uiWindowParent(uiControl *c) -{ - return NULL; -} - -void uiWindowSetParent(uiControl *c, uiControl *parent) -{ - uiUserBugCannotSetParentOnToplevel("uiWindow"); -} - -static int uiWindowToplevel(uiControl *c) -{ - return 1; -} - -// TODO initial state of windows is hidden; ensure this here and make it so on other platforms -static int uiWindowVisible(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - return w->visible; -} - -static void uiWindowShow(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - w->visible = 1; - // just in case the window's minimum size wasn't recalculated already - ensureMinimumWindowSize(w); - if (w->shownOnce) { - ShowWindow(w->hwnd, SW_SHOW); - return; - } - w->shownOnce = TRUE; - - int cmd; - if (w->maximized) - cmd = SW_SHOWMAXIMIZED; - else - cmd = SW_SHOWDEFAULT; - - // make sure the child is the correct size - uiWindowsControlMinimumSizeChanged(uiWindowsControl(w)); - ShowWindow(w->hwnd, cmd);//nCmdShow); - if (UpdateWindow(w->hwnd) == 0) - logLastError(L"error calling UpdateWindow() after showing uiWindow for the first time"); -} - -static void uiWindowHide(uiControl *c) -{ - uiWindow *w = uiWindow(c); - - w->visible = 0; - ShowWindow(w->hwnd, SW_HIDE); -} - -// TODO we don't want the window to be disabled completely; that would prevent it from being moved! ...would it? -uiWindowsControlDefaultEnabled(uiWindow) -uiWindowsControlDefaultEnable(uiWindow) -uiWindowsControlDefaultDisable(uiWindow) -uiWindowsControlDefaultSetFocus(uiWindow) -// TODO we need to do something about undocumented fields in the OS control types -uiWindowsControlDefaultSyncEnableState(uiWindow) -// TODO -uiWindowsControlDefaultSetParentHWND(uiWindow) - -static void uiWindowMinimumSize(uiWindowsControl *c, int *width, int *height) -{ - uiWindow *w = uiWindow(c); - int mx, my; - - *width = 0; - *height = 0; - if (w->child != NULL) - uiWindowsControlMinimumSize(uiWindowsControl(w->child), width, height); - windowMargins(w, &mx, &my); - *width += 2 * mx; - *height += 2 * my; -} - -static void uiWindowMinimumSizeChanged(uiWindowsControl *c) -{ - uiWindow *w = uiWindow(c); - - if (uiWindowsControlTooSmall(uiWindowsControl(w))) { - // TODO figure out what to do with this function - // maybe split it into two so WM_GETMINMAXINFO can use it? - ensureMinimumWindowSize(w); - return; - } - // otherwise we only need to re-layout everything - windowRelayout(w); -} - -static void uiWindowLayoutRect(uiWindowsControl *c, RECT *r) -{ - uiWindow *w = uiWindow(c); - - // the layout rect is the client rect in this case - uiWindowsEnsureGetClientRect(w->hwnd, r); -} - -static void uiWindowSetMinSize(uiControl *c, int w, int h) -{ - // TODO: relayout, eventually -} - -uiWindowsControlDefaultAssignControlIDZOrder(uiWindow) - -static void uiWindowChildVisibilityChanged(uiWindowsControl *c) -{ - // TODO eliminate the redundancy - uiWindowsControlMinimumSizeChanged(c); -} - -char *uiWindowTitle(uiWindow *w) -{ - return uiWindowsWindowText(w->hwnd); -} - -void uiWindowSetTitle(uiWindow *w, const char *title) -{ - uiWindowsSetWindowText(w->hwnd, title); - // don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long) -} - -// this is used for both fullscreening and centering -// see also https://blogs.msdn.microsoft.com/oldnewthing/20100412-00/?p=14353 and https://blogs.msdn.microsoft.com/oldnewthing/20050505-04/?p=35703 -static void windowMonitorRect(HWND hwnd, RECT *r) -{ - HMONITOR monitor; - MONITORINFO mi; - - monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); - ZeroMemory(&mi, sizeof (MONITORINFO)); - mi.cbSize = sizeof (MONITORINFO); - if (GetMonitorInfoW(monitor, &mi) == 0) { - logLastError(L"error getting window monitor rect"); - // default to SM_CXSCREEN x SM_CYSCREEN to be safe - r->left = 0; - r->top = 0; - r->right = GetSystemMetrics(SM_CXSCREEN); - r->bottom = GetSystemMetrics(SM_CYSCREEN); - return; - } - *r = mi.rcMonitor; -} - -void uiWindowPosition(uiWindow *w, int *x, int *y) -{ - RECT rect; - if (GetWindowRect(w->hwnd, &rect) == 0) - logLastError(L"error getting window position"); - *x = rect.left; - *y = rect.top; -} - -void uiWindowSetPosition(uiWindow *w, int x, int y) -{ - if (SetWindowPos(w->hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) - logLastError(L"error moving window"); -} - -void uiWindowContentSize(uiWindow *w, int *width, int *height) -{ - RECT r; - - uiWindowsEnsureGetClientRect(w->hwnd, &r); - *width = r.right - r.left; - *height = r.bottom - r.top; -} - -// TODO should this disallow too small? -void uiWindowSetContentSize(uiWindow *w, int width, int height) -{ - w->changingSize = TRUE; - clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar); - if (SetWindowPos(w->hwnd, NULL, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) - logLastError(L"error resizing window"); - w->changingSize = FALSE; -} - -int uiWindowMinimized(uiWindow *w) -{ - return IsIconic(w->hwnd); -} - -void uiWindowSetMinimized(uiWindow *w, int minimized) -{ - if (minimized) - ShowWindow(w->hwnd, SW_MINIMIZE); - else if (w->maximized) - ShowWindow(w->hwnd, SW_MAXIMIZE); - else - ShowWindow(w->hwnd, SW_RESTORE); -} - -int uiWindowMaximized(uiWindow *w) -{ - return IsZoomed(w->hwnd); -} - -void uiWindowSetMaximized(uiWindow *w, int maximized) -{ - w->maximized = maximized; - if (maximized) - ShowWindow(w->hwnd, SW_MAXIMIZE); - else - ShowWindow(w->hwnd, SW_RESTORE); -} - - -int uiWindowFullscreen(uiWindow *w) -{ - return w->fullscreen; -} - -void uiWindowSetFullscreen(uiWindow *w, int fullscreen) -{ - RECT r; - - if (w->fullscreen && fullscreen) - return; - if (!w->fullscreen && !fullscreen) - return; - w->fullscreen = fullscreen; - w->changingSize = TRUE; - if (w->fullscreen) { - ZeroMemory(&(w->fsPrevPlacement), sizeof (WINDOWPLACEMENT)); - w->fsPrevPlacement.length = sizeof (WINDOWPLACEMENT); - if (GetWindowPlacement(w->hwnd, &(w->fsPrevPlacement)) == 0) - logLastError(L"error getting old window placement"); - windowMonitorRect(w->hwnd, &r); - setStyle(w->hwnd, getStyle(w->hwnd) & ~WS_OVERLAPPEDWINDOW); - if (SetWindowPos(w->hwnd, HWND_TOP, - r.left, r.top, - r.right - r.left, r.bottom - r.top, - SWP_FRAMECHANGED | SWP_NOOWNERZORDER) == 0) - logLastError(L"error making window fullscreen"); - } else { - if (!w->borderless) // keep borderless until that is turned off - setStyle(w->hwnd, getStyle(w->hwnd) | WS_OVERLAPPEDWINDOW); - if (SetWindowPlacement(w->hwnd, &(w->fsPrevPlacement)) == 0) - logLastError(L"error leaving fullscreen"); - if (SetWindowPos(w->hwnd, NULL, - 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER) == 0) - logLastError(L"error restoring window border after fullscreen"); - } - w->changingSize = FALSE; -} - -void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onContentSizeChanged = f; - w->onContentSizeChangedData = data; -} - -void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data) -{ - w->onClosing = f; - w->onClosingData = data; -} - -void uiWindowOnDropFile(uiWindow *w, void (*f)(uiWindow *, char *, void *), void *data) -{ - w->onDropFile = f; - w->onDropFileData = data; -} - -void uiWindowOnGetFocus(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onGetFocus = f; - w->onGetFocusData = data; -} - -void uiWindowOnLoseFocus(uiWindow *w, void (*f)(uiWindow *, void *), void *data) -{ - w->onLoseFocus = f; - w->onLoseFocusData = data; -} - -int uiWindowBorderless(uiWindow *w) -{ - return w->borderless; -} - -// TODO window should move to the old client position and should not have the extra space the borders left behind -// TODO extract the relevant styles from WS_OVERLAPPEDWINDOW? -void uiWindowSetBorderless(uiWindow *w, int borderless) -{ - w->borderless = borderless; - if (w->borderless) - setStyle(w->hwnd, getStyle(w->hwnd) & ~WS_OVERLAPPEDWINDOW); - else - if (!w->fullscreen) // keep borderless until leaving fullscreen - setStyle(w->hwnd, getStyle(w->hwnd) | WS_OVERLAPPEDWINDOW); -} - -void uiWindowSetChild(uiWindow *w, uiControl *child) -{ - if (w->child != NULL) { - uiControlSetParent(w->child, NULL); - uiWindowsControlSetParentHWND(uiWindowsControl(w->child), NULL); - } - w->child = child; - if (w->child != NULL) { - uiControlSetParent(w->child, uiControl(w)); - uiWindowsControlSetParentHWND(uiWindowsControl(w->child), w->hwnd); - uiWindowsControlAssignSoleControlIDZOrder(uiWindowsControl(w->child)); - windowRelayout(w); - } -} - -int uiWindowMargined(uiWindow *w) -{ - return w->margined; -} - -void uiWindowSetMargined(uiWindow *w, int margined) -{ - w->margined = margined; - windowRelayout(w); -} - - -void uiWindowSetDropTarget(uiWindow* w, int drop) -{ - DragAcceptFiles(w->hwnd, drop?TRUE:FALSE); -} - -// see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/09/13/54917.aspx -// TODO use clientSizeToWindowSize() -static void setClientSize(uiWindow *w, int width, int height, BOOL hasMenubar, DWORD style, DWORD exstyle) -{ - RECT window; - - window.left = 0; - window.top = 0; - window.right = width; - window.bottom = height; - if (AdjustWindowRectEx(&window, style, hasMenubar, exstyle) == 0) - logLastError(L"error getting real window coordinates"); - if (hasMenubar) { - RECT temp; - - temp = window; - temp.bottom = 0x7FFF; // infinite height - SendMessageW(w->hwnd, WM_NCCALCSIZE, (WPARAM) FALSE, (LPARAM) (&temp)); - window.bottom += temp.top; - } - if (SetWindowPos(w->hwnd, NULL, 0, 0, window.right - window.left, window.bottom - window.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) - logLastError(L"error resizing window"); -} - -uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, int hasMenubar, int resizable) -{ - uiWindow *w; - WCHAR *wtitle; - BOOL hasMenubarBOOL; - - if (!resizable) maximized = 0; - - uiWindowsNewControl(uiWindow, w); - - hasMenubarBOOL = FALSE; - if (hasMenubar) - hasMenubarBOOL = TRUE; - w->hasMenubar = hasMenubarBOOL; - - int style = WS_OVERLAPPEDWINDOW; - int exstyle = 0; - - if (!resizable) - style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); - - wtitle = toUTF16(title); - w->hwnd = CreateWindowExW(exstyle, - windowClass, wtitle, - style, - CW_USEDEFAULT, CW_USEDEFAULT, - // use the raw width and height for now - // this will get CW_USEDEFAULT (hopefully) predicting well - // even if it doesn't, we're adjusting it later - width, height, - NULL, NULL, hInstance, w); - if (w->hwnd == NULL) - logLastError(L"error creating window"); - uiFree(wtitle); - - if (hasMenubar) { - w->menubar = makeMenubar(); - if (SetMenu(w->hwnd, w->menubar) == 0) - logLastError(L"error giving menu to window"); - } - - // and use the proper size - setClientSize(w, width, height, hasMenubarBOOL, style, exstyle); - - w->maximized = maximized; - - uiWindowOnClosing(w, defaultOnClosing, NULL); - uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL); - - uiWindowOnDropFile(w, NULL, NULL); - uiWindowOnGetFocus(w, NULL, NULL); - uiWindowOnLoseFocus(w, NULL, NULL); - - windows[w] = true; - return w; -} - -// this cannot queue a resize because it's called by the resize handler -void ensureMinimumWindowSize(uiWindow *w) -{ - int width, height; - RECT r; - - uiWindowsControlMinimumSize(uiWindowsControl(w), &width, &height); - uiWindowsEnsureGetClientRect(w->hwnd, &r); - if (width < (r.right - r.left)) // preserve width if larger - width = r.right - r.left; - if (height < (r.bottom - r.top)) // preserve height if larger - height = r.bottom - r.top; - clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar); - if (SetWindowPos(w->hwnd, NULL, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) - logLastError(L"error resizing window"); -} - -void disableAllWindowsExcept(uiWindow *which) -{ - for (auto &w : windows) { - if (w.first == which) - continue; - EnableWindow(w.first->hwnd, FALSE); - } -} - -void enableAllWindowsExcept(uiWindow *which) -{ - for (auto &w : windows) { - if (w.first == which) - continue; - if (!uiControlEnabled(uiControl(w.first))) - continue; - EnableWindow(w.first->hwnd, TRUE); - } -} diff --git a/src/libui_sdl/libui/windows/winpublic.cpp b/src/libui_sdl/libui/windows/winpublic.cpp deleted file mode 100644 index 397a3b54..00000000 --- a/src/libui_sdl/libui/windows/winpublic.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// 6 april 2015 -#include "uipriv_windows.hpp" - -void uiWindowsEnsureDestroyWindow(HWND hwnd) -{ - if (DestroyWindow(hwnd) == 0) - logLastError(L"error destroying window"); -} - -void uiWindowsEnsureSetParentHWND(HWND hwnd, HWND parent) -{ - if (parent == NULL) - parent = utilWindow; - if (SetParent(hwnd, parent) == 0) - logLastError(L"error setting window parent"); -} - -void uiWindowsEnsureAssignControlIDZOrder(HWND hwnd, LONG_PTR *controlID, HWND *insertAfter) -{ - SetWindowLongPtrW(hwnd, GWLP_ID, *controlID); - (*controlID)++; - setWindowInsertAfter(hwnd, *insertAfter); - *insertAfter = hwnd; -} - -void uiWindowsEnsureMoveWindowDuringResize(HWND hwnd, int x, int y, int width, int height) -{ - RECT r; - - r.left = x; - r.top = y; - r.right = x + width; - r.bottom = y + height; - if (SetWindowPos(hwnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0) - logLastError(L"error moving window"); -} - -// do these function even error out in any case other than invalid parameters?! I thought all windows had rects -void uiWindowsEnsureGetClientRect(HWND hwnd, RECT *r) -{ - if (GetClientRect(hwnd, r) == 0) { - logLastError(L"error getting window client rect"); - // zero out the rect on error just to be safe - r->left = 0; - r->top = 0; - r->right = 0; - r->bottom = 0; - } -} - -void uiWindowsEnsureGetWindowRect(HWND hwnd, RECT *r) -{ - if (GetWindowRect(hwnd, r) == 0) { - logLastError(L"error getting window rect"); - // zero out the rect on error just to be safe - r->left = 0; - r->top = 0; - r->right = 0; - r->bottom = 0; - } -} diff --git a/src/libui_sdl/libui/windows/winutil.cpp b/src/libui_sdl/libui/windows/winutil.cpp deleted file mode 100644 index 25528934..00000000 --- a/src/libui_sdl/libui/windows/winutil.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// 6 april 2015 -#include "uipriv_windows.hpp" - -// this is a helper function that takes the logic of determining window classes and puts it all in one place -// there are a number of places where we need to know what window class an arbitrary handle has -// theoretically we could use the class atom to avoid a _wcsicmp() -// however, raymond chen advises against this - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx (and we're not in control of the Tab class, before you say anything) -// usage: windowClassOf(hwnd, L"class 1", L"class 2", ..., NULL) -int windowClassOf(HWND hwnd, ...) -{ -// MSDN says 256 is the maximum length of a class name; add a few characters just to be safe (because it doesn't say whether this includes the terminating null character) -#define maxClassName 260 - WCHAR classname[maxClassName + 1]; - va_list ap; - WCHAR *curname; - int i; - - if (GetClassNameW(hwnd, classname, maxClassName) == 0) { - logLastError(L"error getting name of window class"); - // assume no match on error, just to be safe - return -1; - } - va_start(ap, hwnd); - i = 0; - for (;;) { - curname = va_arg(ap, WCHAR *); - if (curname == NULL) - break; - if (_wcsicmp(classname, curname) == 0) { - va_end(ap); - return i; - } - i++; - } - // no match - va_end(ap); - return -1; -} - -// wrapper around MapWindowRect() that handles the complex error handling -void mapWindowRect(HWND from, HWND to, RECT *r) -{ - RECT prevr; - DWORD le; - - prevr = *r; - SetLastError(0); - if (MapWindowRect(from, to, r) == 0) { - le = GetLastError(); - SetLastError(le); // just to be safe - if (le != 0) { - logLastError(L"error calling MapWindowRect()"); - // restore original rect on error, just in case - *r = prevr; - } - } -} - -DWORD getStyle(HWND hwnd) -{ - return (DWORD) GetWindowLongPtrW(hwnd, GWL_STYLE); -} - -void setStyle(HWND hwnd, DWORD style) -{ - SetWindowLongPtrW(hwnd, GWL_STYLE, (LONG_PTR) style); -} - -DWORD getExStyle(HWND hwnd) -{ - return (DWORD) GetWindowLongPtrW(hwnd, GWL_EXSTYLE); -} - -void setExStyle(HWND hwnd, DWORD exstyle) -{ - SetWindowLongPtrW(hwnd, GWL_EXSTYLE, (LONG_PTR) exstyle); -} - -// see http://blogs.msdn.com/b/oldnewthing/archive/2003/09/11/54885.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2003/09/13/54917.aspx -void clientSizeToWindowSize(HWND hwnd, int *width, int *height, BOOL hasMenubar) -{ - RECT window; - - window.left = 0; - window.top = 0; - window.right = *width; - window.bottom = *height; - if (AdjustWindowRectEx(&window, getStyle(hwnd), hasMenubar, getExStyle(hwnd)) == 0) { - logLastError(L"error getting adjusted window rect"); - // on error, don't give up; the window will be smaller but whatever - window.left = 0; - window.top = 0; - window.right = *width; - window.bottom = *height; - } - if (hasMenubar) { - RECT temp; - - temp = window; - temp.bottom = 0x7FFF; // infinite height - SendMessageW(hwnd, WM_NCCALCSIZE, (WPARAM) FALSE, (LPARAM) (&temp)); - window.bottom += temp.top; - } - *width = window.right - window.left; - *height = window.bottom - window.top; -} - -HWND parentOf(HWND child) -{ - return GetAncestor(child, GA_PARENT); -} - -HWND parentToplevel(HWND child) -{ - return GetAncestor(child, GA_ROOT); -} - -void setWindowInsertAfter(HWND hwnd, HWND insertAfter) -{ - if (SetWindowPos(hwnd, insertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE) == 0) - logLastError(L"error reordering window"); -} - -HWND getDlgItem(HWND hwnd, int id) -{ - HWND out; - - out = GetDlgItem(hwnd, id); - if (out == NULL) - logLastError(L"error getting dialog item handle"); - return out; -} - -void invalidateRect(HWND hwnd, RECT *r, BOOL erase) -{ - if (InvalidateRect(hwnd, r, erase) == 0) - logLastError(L"error invalidating window rect"); -} - -D2D1_SIZE_F realGetSize(ID2D1RenderTarget *rt) -{ - return rt->GetSize(); -} diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp deleted file mode 100644 index 64bc5329..00000000 --- a/src/libui_sdl/main.cpp +++ /dev/null @@ -1,3029 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#include -#include -#include -#include - -#ifndef __WIN32__ -#include -#endif - -#include -#include "libui/ui.h" - -#include "../OpenGLSupport.h" -#include "main_shaders.h" - -#include "../types.h" -#include "../version.h" -#include "PlatformConfig.h" - -#include "DlgEmuSettings.h" -#include "DlgInputConfig.h" -#include "DlgVideoSettings.h" -#include "DlgAudioSettings.h" -#include "DlgWifiSettings.h" - -#include "../NDS.h" -#include "../GBACart.h" -#include "../GPU.h" -#include "../SPU.h" -#include "../Wifi.h" -#include "../Platform.h" -#include "../Config.h" - -#include "../Savestate.h" - -#include "OSD.h" - -#ifdef MELONCAP -#include "MelonCap.h" -#endif // MELONCAP - - -// savestate slot mapping -// 1-8: regular slots (quick access) -// '9': load/save arbitrary file -const int kSavestateNum[9] = {1, 2, 3, 4, 5, 6, 7, 8, 0}; - -const int kScreenSize[4] = {1, 2, 3, 4}; -const int kScreenRot[4] = {0, 1, 2, 3}; -const int kScreenGap[6] = {0, 1, 8, 64, 90, 128}; -const int kScreenLayout[3] = {0, 1, 2}; -const int kScreenSizing[4] = {0, 1, 2, 3}; - - -char* EmuDirectory; - - -uiWindow* MainWindow; -uiArea* MainDrawArea; -uiAreaHandler MainDrawAreaHandler; - -const u32 kGLVersions[] = {uiGLVersion(3,2), uiGLVersion(3,1), 0}; -uiGLContext* GLContext; - -int WindowWidth, WindowHeight; - -uiMenuItem* MenuItem_SaveState; -uiMenuItem* MenuItem_LoadState; -uiMenuItem* MenuItem_UndoStateLoad; - -uiMenuItem* MenuItem_SaveStateSlot[9]; -uiMenuItem* MenuItem_LoadStateSlot[9]; - -uiMenuItem* MenuItem_Pause; -uiMenuItem* MenuItem_Reset; -uiMenuItem* MenuItem_Stop; - -uiMenuItem* MenuItem_SavestateSRAMReloc; - -uiMenuItem* MenuItem_ScreenRot[4]; -uiMenuItem* MenuItem_ScreenGap[6]; -uiMenuItem* MenuItem_ScreenLayout[3]; -uiMenuItem* MenuItem_ScreenSizing[4]; - -uiMenuItem* MenuItem_ScreenFilter; -uiMenuItem* MenuItem_LimitFPS; -uiMenuItem* MenuItem_AudioSync; -uiMenuItem* MenuItem_ShowOSD; - -SDL_Thread* EmuThread; -int EmuRunning; -volatile int EmuStatus; - -bool RunningSomething; -char ROMPath[2][1024]; -char SRAMPath[2][1024]; -char PrevSRAMPath[2][1024]; // for savestate 'undo load' - -bool SavestateLoaded; - -bool Screen_UseGL; - -bool ScreenDrawInited = false; -uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL}; - -GLuint GL_ScreenShader[3]; -GLuint GL_ScreenShaderAccel[3]; -GLuint GL_ScreenShaderOSD[3]; -struct -{ - float uScreenSize[2]; - u32 u3DScale; - u32 uFilterMode; - -} GL_ShaderConfig; -GLuint GL_ShaderConfigUBO; -GLuint GL_ScreenVertexArrayID, GL_ScreenVertexBufferID; -float GL_ScreenVertices[2 * 3*2 * 4]; // position/texcoord -GLuint GL_ScreenTexture; -bool GL_ScreenSizeDirty; - -int GL_3DScale; - -bool GL_VSyncStatus; - -int ScreenGap = 0; -int ScreenLayout = 0; -int ScreenSizing = 0; -int ScreenRotation = 0; - -int MainScreenPos[3]; -int AutoScreenSizing; - -uiRect TopScreenRect; -uiRect BottomScreenRect; -uiDrawMatrix TopScreenTrans; -uiDrawMatrix BottomScreenTrans; - -bool Touching = false; - -u32 KeyInputMask, JoyInputMask; -u32 KeyHotkeyMask, JoyHotkeyMask; -u32 HotkeyMask, LastHotkeyMask; -u32 HotkeyPress, HotkeyRelease; - -#define HotkeyDown(hk) (HotkeyMask & (1<<(hk))) -#define HotkeyPressed(hk) (HotkeyPress & (1<<(hk))) -#define HotkeyReleased(hk) (HotkeyRelease & (1<<(hk))) - -bool LidStatus; - -int JoystickID; -SDL_Joystick* Joystick; - -int AudioFreq; -float AudioSampleFrac; -SDL_AudioDeviceID AudioDevice, MicDevice; - -SDL_cond* AudioSync; -SDL_mutex* AudioSyncLock; - -u32 MicBufferLength = 2048; -s16 MicBuffer[2048]; -u32 MicBufferReadPos, MicBufferWritePos; - -u32 MicWavLength; -s16* MicWavBuffer; - -void SetupScreenRects(int width, int height); - -void TogglePause(void* blarg); -void Reset(void* blarg); - -void SetupSRAMPath(int slot); - -void SaveState(int slot); -void LoadState(int slot); -void UndoStateLoad(); -void GetSavestateName(int slot, char* filename, int len); - -void CreateMainWindow(bool opengl); -void DestroyMainWindow(); -void RecreateMainWindow(bool opengl); - - - -bool GLScreen_InitShader(GLuint* shader, const char* fs) -{ - if (!OpenGL_BuildShaderProgram(kScreenVS, fs, shader, "ScreenShader")) - return false; - - glBindAttribLocation(shader[2], 0, "vPosition"); - glBindAttribLocation(shader[2], 1, "vTexcoord"); - glBindFragDataLocation(shader[2], 0, "oColor"); - - if (!OpenGL_LinkShaderProgram(shader)) - return false; - - GLuint uni_id; - - uni_id = glGetUniformBlockIndex(shader[2], "uConfig"); - glUniformBlockBinding(shader[2], uni_id, 16); - - glUseProgram(shader[2]); - uni_id = glGetUniformLocation(shader[2], "ScreenTex"); - glUniform1i(uni_id, 0); - uni_id = glGetUniformLocation(shader[2], "_3DTex"); - glUniform1i(uni_id, 1); - - return true; -} - -bool GLScreen_InitOSDShader(GLuint* shader) -{ - if (!OpenGL_BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, shader, "ScreenShaderOSD")) - return false; - - glBindAttribLocation(shader[2], 0, "vPosition"); - glBindFragDataLocation(shader[2], 0, "oColor"); - - if (!OpenGL_LinkShaderProgram(shader)) - return false; - - GLuint uni_id; - - uni_id = glGetUniformBlockIndex(shader[2], "uConfig"); - glUniformBlockBinding(shader[2], uni_id, 16); - - glUseProgram(shader[2]); - uni_id = glGetUniformLocation(shader[2], "OSDTex"); - glUniform1i(uni_id, 0); - - return true; -} - -bool GLScreen_Init() -{ - GL_VSyncStatus = Config::ScreenVSync; - - // TODO: consider using epoxy? - if (!OpenGL_Init()) - return false; - - const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string - const GLubyte* version = glGetString(GL_VERSION); // version as a string - printf("OpenGL: renderer: %s\n", renderer); - printf("OpenGL: version: %s\n", version); - - if (!GLScreen_InitShader(GL_ScreenShader, kScreenFS)) - return false; - if (!GLScreen_InitShader(GL_ScreenShaderAccel, kScreenFS_Accel)) - return false; - if (!GLScreen_InitOSDShader(GL_ScreenShaderOSD)) - return false; - - memset(&GL_ShaderConfig, 0, sizeof(GL_ShaderConfig)); - - glGenBuffers(1, &GL_ShaderConfigUBO); - glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(GL_ShaderConfig), &GL_ShaderConfig, GL_STATIC_DRAW); - glBindBufferBase(GL_UNIFORM_BUFFER, 16, GL_ShaderConfigUBO); - - glGenBuffers(1, &GL_ScreenVertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(GL_ScreenVertices), NULL, GL_STATIC_DRAW); - - glGenVertexArrays(1, &GL_ScreenVertexArrayID); - glBindVertexArray(GL_ScreenVertexArrayID); - glEnableVertexAttribArray(0); // position - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0)); - glEnableVertexAttribArray(1); // texcoord - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4)); - - glGenTextures(1, &GL_ScreenTexture); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 256*3 + 1, 192*2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL); - - GL_ScreenSizeDirty = true; - - return true; -} - -void GLScreen_DeInit() -{ - glDeleteTextures(1, &GL_ScreenTexture); - - glDeleteVertexArrays(1, &GL_ScreenVertexArrayID); - glDeleteBuffers(1, &GL_ScreenVertexBufferID); - - OpenGL_DeleteShaderProgram(GL_ScreenShader); - OpenGL_DeleteShaderProgram(GL_ScreenShaderAccel); - OpenGL_DeleteShaderProgram(GL_ScreenShaderOSD); -} - -void GLScreen_DrawScreen() -{ - bool vsync = Config::ScreenVSync && !HotkeyDown(HK_FastForward); - if (vsync != GL_VSyncStatus) - { - GL_VSyncStatus = vsync; - uiGLSetVSync(vsync); - } - - float scale = uiGLGetFramebufferScale(GLContext); - - glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext)); - - if (GL_ScreenSizeDirty) - { - GL_ScreenSizeDirty = false; - - GL_ShaderConfig.uScreenSize[0] = WindowWidth; - GL_ShaderConfig.uScreenSize[1] = WindowHeight; - GL_ShaderConfig.u3DScale = GL_3DScale; - - glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO); - void* unibuf = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); - if (unibuf) memcpy(unibuf, &GL_ShaderConfig, sizeof(GL_ShaderConfig)); - glUnmapBuffer(GL_UNIFORM_BUFFER); - - float scwidth, scheight; - - float x0, y0, x1, y1; - float s0, s1, s2, s3; - float t0, t1, t2, t3; - -#define SETVERTEX(i, x, y, s, t) \ - GL_ScreenVertices[4*(i) + 0] = x; \ - GL_ScreenVertices[4*(i) + 1] = y; \ - GL_ScreenVertices[4*(i) + 2] = s; \ - GL_ScreenVertices[4*(i) + 3] = t; - - x0 = TopScreenRect.X; - y0 = TopScreenRect.Y; - x1 = TopScreenRect.X + TopScreenRect.Width; - y1 = TopScreenRect.Y + TopScreenRect.Height; - - scwidth = 256; - scheight = 192; - - switch (ScreenRotation) - { - case 0: - s0 = 0; t0 = 0; - s1 = scwidth; t1 = 0; - s2 = 0; t2 = scheight; - s3 = scwidth; t3 = scheight; - break; - - case 1: - s0 = 0; t0 = scheight; - s1 = 0; t1 = 0; - s2 = scwidth; t2 = scheight; - s3 = scwidth; t3 = 0; - break; - - case 2: - s0 = scwidth; t0 = scheight; - s1 = 0; t1 = scheight; - s2 = scwidth; t2 = 0; - s3 = 0; t3 = 0; - break; - - case 3: - s0 = scwidth; t0 = 0; - s1 = scwidth; t1 = scheight; - s2 = 0; t2 = 0; - s3 = 0; t3 = scheight; - break; - } - - SETVERTEX(0, x0, y0, s0, t0); - SETVERTEX(1, x1, y1, s3, t3); - SETVERTEX(2, x1, y0, s1, t1); - SETVERTEX(3, x0, y0, s0, t0); - SETVERTEX(4, x0, y1, s2, t2); - SETVERTEX(5, x1, y1, s3, t3); - - x0 = BottomScreenRect.X; - y0 = BottomScreenRect.Y; - x1 = BottomScreenRect.X + BottomScreenRect.Width; - y1 = BottomScreenRect.Y + BottomScreenRect.Height; - - scwidth = 256; - scheight = 192; - - switch (ScreenRotation) - { - case 0: - s0 = 0; t0 = 192; - s1 = scwidth; t1 = 192; - s2 = 0; t2 = 192+scheight; - s3 = scwidth; t3 = 192+scheight; - break; - - case 1: - s0 = 0; t0 = 192+scheight; - s1 = 0; t1 = 192; - s2 = scwidth; t2 = 192+scheight; - s3 = scwidth; t3 = 192; - break; - - case 2: - s0 = scwidth; t0 = 192+scheight; - s1 = 0; t1 = 192+scheight; - s2 = scwidth; t2 = 192; - s3 = 0; t3 = 192; - break; - - case 3: - s0 = scwidth; t0 = 192; - s1 = scwidth; t1 = 192+scheight; - s2 = 0; t2 = 192; - s3 = 0; t3 = 192+scheight; - break; - } - - SETVERTEX(6, x0, y0, s0, t0); - SETVERTEX(7, x1, y1, s3, t3); - SETVERTEX(8, x1, y0, s1, t1); - SETVERTEX(9, x0, y0, s0, t0); - SETVERTEX(10, x0, y1, s2, t2); - SETVERTEX(11, x1, y1, s3, t3); - -#undef SETVERTEX - - glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GL_ScreenVertices), GL_ScreenVertices); - } - - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_BLEND); - glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - glViewport(0, 0, WindowWidth*scale, WindowHeight*scale); - - if (GPU3D::Renderer == 0) - OpenGL_UseShaderProgram(GL_ScreenShader); - else - OpenGL_UseShaderProgram(GL_ScreenShaderAccel); - - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - - if (RunningSomething) - { - int frontbuf = GPU::FrontBuffer; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture); - - if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) - { - if (GPU3D::Renderer == 0) - { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); - } - else - { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); - } - } - - glActiveTexture(GL_TEXTURE1); - if (GPU3D::Renderer != 0) - GPU3D::GLRenderer::SetupAccelFrame(); - - glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID); - glBindVertexArray(GL_ScreenVertexArrayID); - glDrawArrays(GL_TRIANGLES, 0, 4*3); - } - - OpenGL_UseShaderProgram(GL_ScreenShaderOSD); - OSD::Update(true, NULL); - - glFlush(); - uiGLSwapBuffers(GLContext); -} - -void MicLoadWav(char* name) -{ - SDL_AudioSpec format; - memset(&format, 0, sizeof(SDL_AudioSpec)); - - if (MicWavBuffer) delete[] MicWavBuffer; - MicWavBuffer = NULL; - MicWavLength = 0; - - u8* buf; - u32 len; - if (!SDL_LoadWAV(name, &format, &buf, &len)) - return; - - const u64 dstfreq = 44100; - - if (format.format == AUDIO_S16 || format.format == AUDIO_U16) - { - int srcinc = format.channels; - len /= (2 * srcinc); - - MicWavLength = (len * dstfreq) / format.freq; - if (MicWavLength < 735) MicWavLength = 735; - MicWavBuffer = new s16[MicWavLength]; - - float res_incr = len / (float)MicWavLength; - float res_timer = 0; - int res_pos = 0; - - for (int i = 0; i < MicWavLength; i++) - { - u16 val = ((u16*)buf)[res_pos]; - if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000; - - MicWavBuffer[i] = val; - - res_timer += res_incr; - while (res_timer >= 1.0) - { - res_timer -= 1.0; - res_pos += srcinc; - } - } - } - else if (format.format == AUDIO_S8 || format.format == AUDIO_U8) - { - int srcinc = format.channels; - len /= srcinc; - - MicWavLength = (len * dstfreq) / format.freq; - if (MicWavLength < 735) MicWavLength = 735; - MicWavBuffer = new s16[MicWavLength]; - - float res_incr = len / (float)MicWavLength; - float res_timer = 0; - int res_pos = 0; - - for (int i = 0; i < MicWavLength; i++) - { - u16 val = buf[res_pos] << 8; - if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000; - - MicWavBuffer[i] = val; - - res_timer += res_incr; - while (res_timer >= 1.0) - { - res_timer -= 1.0; - res_pos += srcinc; - } - } - } - else - printf("bad WAV format %08X\n", format.format); - - SDL_FreeWAV(buf); -} - -void AudioCallback(void* data, Uint8* stream, int len) -{ - len /= (sizeof(s16) * 2); - - // resample incoming audio to match the output sample rate - - float f_len_in = (len * 32823.6328125) / (float)AudioFreq; - f_len_in += AudioSampleFrac; - int len_in = (int)floor(f_len_in); - AudioSampleFrac = f_len_in - len_in; - - s16 buf_in[1024*2]; - s16* buf_out = (s16*)stream; - - int num_in; - int num_out = len; - - SDL_LockMutex(AudioSyncLock); - num_in = SPU::ReadOutput(buf_in, len_in); - SDL_CondSignal(AudioSync); - SDL_UnlockMutex(AudioSyncLock); - - if (num_in < 1) - { - memset(stream, 0, len*sizeof(s16)*2); - return; - } - - int margin = 6; - if (num_in < len_in-margin) - { - int last = num_in-1; - if (last < 0) last = 0; - - for (int i = num_in; i < len_in-margin; i++) - ((u32*)buf_in)[i] = ((u32*)buf_in)[last]; - - num_in = len_in-margin; - } - - float res_incr = num_in / (float)num_out; - float res_timer = 0; - int res_pos = 0; - - int volume = Config::AudioVolume; - - for (int i = 0; i < len; i++) - { - buf_out[i*2 ] = (buf_in[res_pos*2 ] * volume) >> 8; - buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8; - - /*s16 s_l = buf_in[res_pos*2 ]; - s16 s_r = buf_in[res_pos*2+1]; - - float a = res_timer; - float b = 1.0 - a; - s_l = (s_l * a) + (buf_in[(res_pos-1)*2 ] * b); - s_r = (s_r * a) + (buf_in[(res_pos-1)*2+1] * b); - - buf_out[i*2 ] = (s_l * volume) >> 8; - buf_out[i*2+1] = (s_r * volume) >> 8;*/ - - res_timer += res_incr; - while (res_timer >= 1.0) - { - res_timer -= 1.0; - res_pos++; - } - } -} - -void MicCallback(void* data, Uint8* stream, int len) -{ - if (Config::MicInputType != 1) return; - - s16* input = (s16*)stream; - len /= sizeof(s16); - - if ((MicBufferWritePos + len) > MicBufferLength) - { - u32 len1 = MicBufferLength - MicBufferWritePos; - memcpy(&MicBuffer[MicBufferWritePos], &input[0], len1*sizeof(s16)); - memcpy(&MicBuffer[0], &input[len1], (len - len1)*sizeof(s16)); - MicBufferWritePos = len - len1; - } - else - { - memcpy(&MicBuffer[MicBufferWritePos], input, len*sizeof(s16)); - MicBufferWritePos += len; - } -} - -void FeedMicInput() -{ - int type = Config::MicInputType; - bool cmd = HotkeyDown(HK_Mic); - - if ((type != 1 && !cmd) || - (type == 1 && MicBufferLength == 0) || - (type == 3 && MicWavBuffer == NULL)) - { - type = 0; - MicBufferReadPos = 0; - } - - switch (type) - { - case 0: // no mic - NDS::MicInputFrame(NULL, 0); - break; - - case 1: // host mic - if ((MicBufferReadPos + 735) > MicBufferLength) - { - s16 tmp[735]; - u32 len1 = MicBufferLength - MicBufferReadPos; - memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16)); - memcpy(&tmp[len1], &MicBuffer[0], (735 - len1)*sizeof(s16)); - - NDS::MicInputFrame(tmp, 735); - MicBufferReadPos = 735 - len1; - } - else - { - NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735); - MicBufferReadPos += 735; - } - break; - - case 2: // white noise - { - s16 tmp[735]; - for (int i = 0; i < 735; i++) tmp[i] = rand() & 0xFFFF; - NDS::MicInputFrame(tmp, 735); - } - break; - - case 3: // WAV - if ((MicBufferReadPos + 735) > MicWavLength) - { - s16 tmp[735]; - u32 len1 = MicWavLength - MicBufferReadPos; - memcpy(&tmp[0], &MicWavBuffer[MicBufferReadPos], len1*sizeof(s16)); - memcpy(&tmp[len1], &MicWavBuffer[0], (735 - len1)*sizeof(s16)); - - NDS::MicInputFrame(tmp, 735); - MicBufferReadPos = 735 - len1; - } - else - { - NDS::MicInputFrame(&MicWavBuffer[MicBufferReadPos], 735); - MicBufferReadPos += 735; - } - break; - } -} - -void OpenJoystick() -{ - if (Joystick) SDL_JoystickClose(Joystick); - - int num = SDL_NumJoysticks(); - if (num < 1) - { - Joystick = NULL; - return; - } - - if (JoystickID >= num) - JoystickID = 0; - - Joystick = SDL_JoystickOpen(JoystickID); -} - -bool JoystickButtonDown(int val) -{ - if (val == -1) return false; - - bool hasbtn = ((val & 0xFFFF) != 0xFFFF); - - if (hasbtn) - { - if (val & 0x100) - { - int hatnum = (val >> 4) & 0xF; - int hatdir = val & 0xF; - Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum); - - bool pressed = false; - if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP); - else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN); - else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT); - else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT); - - if (pressed) return true; - } - else - { - int btnnum = val & 0xFFFF; - Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum); - - if (btnval) return true; - } - } - - if (val & 0x10000) - { - int axisnum = (val >> 24) & 0xF; - int axisdir = (val >> 20) & 0xF; - Sint16 axisval = SDL_JoystickGetAxis(Joystick, axisnum); - - switch (axisdir) - { - case 0: // positive - if (axisval > 16384) return true; - break; - - case 1: // negative - if (axisval < -16384) return true; - break; - - case 2: // trigger - if (axisval > 0) return true; - break; - } - } - - return false; -} - -void ProcessInput() -{ - SDL_JoystickUpdate(); - - if (Joystick) - { - if (!SDL_JoystickGetAttached(Joystick)) - { - SDL_JoystickClose(Joystick); - Joystick = NULL; - } - } - if (!Joystick && (SDL_NumJoysticks() > 0)) - { - JoystickID = Config::JoystickID; - OpenJoystick(); - } - - JoyInputMask = 0xFFF; - for (int i = 0; i < 12; i++) - if (JoystickButtonDown(Config::JoyMapping[i])) - JoyInputMask &= ~(1<> 4); - - bool pressed = false; - if (btnid == 0x101) // up - pressed = (hat & SDL_HAT_UP); - else if (btnid == 0x104) // down - pressed = (hat & SDL_HAT_DOWN); - else if (btnid == 0x102) // right - pressed = (hat & SDL_HAT_RIGHT); - else if (btnid == 0x108) // left - pressed = (hat & SDL_HAT_LEFT); - else if (btnid < njoybuttons) - pressed = (joybuttons[btnid] & ~(joybuttons[btnid] >> 1)) & 0x01; - - return pressed; -} - -bool JoyButtonHeld(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat) -{ - if (btnid < 0) return false; - - bool pressed = false; - if (btnid == 0x101) // up - pressed = (hat & SDL_HAT_UP); - else if (btnid == 0x104) // down - pressed = (hat & SDL_HAT_DOWN); - else if (btnid == 0x102) // right - pressed = (hat & SDL_HAT_RIGHT); - else if (btnid == 0x108) // left - pressed = (hat & SDL_HAT_LEFT); - else if (btnid < njoybuttons) - pressed = joybuttons[btnid] & 0x01; - - return pressed; -} - -void UpdateWindowTitle(void* data) -{ - if (EmuStatus == 0) return; - void** dataarray = (void**)data; - SDL_LockMutex((SDL_mutex*)dataarray[1]); - uiWindowSetTitle(MainWindow, (const char*)dataarray[0]); - SDL_UnlockMutex((SDL_mutex*)dataarray[1]); -} - -void UpdateFPSLimit(void* data) -{ - uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); -} - -int EmuThreadFunc(void* burp) -{ - NDS::Init(); - - MainScreenPos[0] = 0; - MainScreenPos[1] = 0; - MainScreenPos[2] = 0; - AutoScreenSizing = 0; - - if (Screen_UseGL) - { - uiGLMakeContextCurrent(GLContext); - GPU3D::InitRenderer(true); - uiGLMakeContextCurrent(NULL); - } - else - { - GPU3D::InitRenderer(false); - } - - Touching = false; - KeyInputMask = 0xFFF; - JoyInputMask = 0xFFF; - KeyHotkeyMask = 0; - JoyHotkeyMask = 0; - HotkeyMask = 0; - LastHotkeyMask = 0; - LidStatus = false; - - u32 nframes = 0; - u32 starttick = SDL_GetTicks(); - u32 lasttick = starttick; - u32 lastmeasuretick = lasttick; - u32 fpslimitcount = 0; - u64 perfcount = SDL_GetPerformanceCounter(); - u64 perffreq = SDL_GetPerformanceFrequency(); - float samplesleft = 0; - u32 nsamples = 0; - - char melontitle[100]; - SDL_mutex* titlemutex = SDL_CreateMutex(); - void* titledata[2] = {melontitle, titlemutex}; - - while (EmuRunning != 0) - { - ProcessInput(); - - if (HotkeyPressed(HK_FastForwardToggle)) - { - Config::LimitFPS = !Config::LimitFPS; - uiQueueMain(UpdateFPSLimit, NULL); - } - // TODO: similar hotkeys for video/audio sync? - - if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); - if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); - - if (GBACart::CartInserted && GBACart::HasSolarSensor) - { - if (HotkeyPressed(HK_SolarSensorDecrease)) - { - if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; - char msg[64]; - sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - OSD::AddMessage(0, msg); - } - if (HotkeyPressed(HK_SolarSensorIncrease)) - { - if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; - char msg[64]; - sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - OSD::AddMessage(0, msg); - } - } - - if (EmuRunning == 1) - { - EmuStatus = 1; - - // process input and hotkeys - NDS::SetKeyMask(KeyInputMask & JoyInputMask); - - if (HotkeyPressed(HK_Lid)) - { - LidStatus = !LidStatus; - NDS::SetLidClosed(LidStatus); - OSD::AddMessage(0, LidStatus ? "Lid closed" : "Lid opened"); - } - - // microphone input - FeedMicInput(); - - if (Screen_UseGL) - { - uiGLBegin(GLContext); - uiGLMakeContextCurrent(GLContext); - } - - // auto screen layout - { - MainScreenPos[2] = MainScreenPos[1]; - MainScreenPos[1] = MainScreenPos[0]; - MainScreenPos[0] = NDS::PowerControl9 >> 15; - - int guess; - if (MainScreenPos[0] == MainScreenPos[2] && - MainScreenPos[0] != MainScreenPos[1]) - { - // constant flickering, likely displaying 3D on both screens - // TODO: when both screens are used for 2D only...??? - guess = 0; - } - else - { - if (MainScreenPos[0] == 1) - guess = 1; - else - guess = 2; - } - - if (guess != AutoScreenSizing) - { - AutoScreenSizing = guess; - SetupScreenRects(WindowWidth, WindowHeight); - } - } - - // emulate - u32 nlines = NDS::RunFrame(); - -#ifdef MELONCAP - MelonCap::Update(); -#endif // MELONCAP - - if (EmuRunning == 0) break; - - if (Screen_UseGL) - { - GLScreen_DrawScreen(); - uiGLEnd(GLContext); - } - uiAreaQueueRedrawAll(MainDrawArea); - - bool fastforward = HotkeyDown(HK_FastForward); - - if (Config::AudioSync && !fastforward) - { - SDL_LockMutex(AudioSyncLock); - while (SPU::GetOutputSize() > 1024) - { - int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500); - if (ret == SDL_MUTEX_TIMEDOUT) break; - } - SDL_UnlockMutex(AudioSyncLock); - } - else - { - // ensure the audio FIFO doesn't overflow - //SPU::TrimOutput(); - } - - float framerate = (1000.0f * nlines) / (60.0f * 263.0f); - - { - u32 curtick = SDL_GetTicks(); - u32 delay = curtick - lasttick; - - bool limitfps = Config::LimitFPS && !fastforward; - if (limitfps) - { - float wantedtickF = starttick + (framerate * (fpslimitcount+1)); - u32 wantedtick = (u32)ceil(wantedtickF); - if (curtick < wantedtick) SDL_Delay(wantedtick - curtick); - - lasttick = SDL_GetTicks(); - fpslimitcount++; - if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60)) - { - fpslimitcount = 0; - nsamples = 0; - starttick = lasttick; - } - } - else - { - if (delay < 1) SDL_Delay(1); - lasttick = SDL_GetTicks(); - } - } - - nframes++; - if (nframes >= 30) - { - u32 tick = SDL_GetTicks(); - u32 diff = tick - lastmeasuretick; - lastmeasuretick = tick; - - u32 fps; - if (diff < 1) fps = 77777; - else fps = (nframes * 1000) / diff; - nframes = 0; - - float fpstarget; - if (framerate < 1) fpstarget = 999; - else fpstarget = 1000.0f/framerate; - - SDL_LockMutex(titlemutex); - sprintf(melontitle, "[%d/%.0f] melonDS " MELONDS_VERSION, fps, fpstarget); - SDL_UnlockMutex(titlemutex); - uiQueueMain(UpdateWindowTitle, titledata); - } - } - else - { - // paused - nframes = 0; - lasttick = SDL_GetTicks(); - starttick = lasttick; - lastmeasuretick = lasttick; - fpslimitcount = 0; - - if (EmuRunning == 2) - { - if (Screen_UseGL) - { - uiGLBegin(GLContext); - uiGLMakeContextCurrent(GLContext); - GLScreen_DrawScreen(); - uiGLEnd(GLContext); - } - uiAreaQueueRedrawAll(MainDrawArea); - } - - if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - - EmuStatus = EmuRunning; - - SDL_Delay(100); - } - } - - EmuStatus = 0; - - SDL_DestroyMutex(titlemutex); - - if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); - - NDS::DeInit(); - Platform::LAN_DeInit(); - - if (Screen_UseGL) - { - OSD::DeInit(true); - GLScreen_DeInit(); - } - else - OSD::DeInit(false); - - if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - - return 44203; -} - -void StopEmuThread() -{ - EmuRunning = 0; - SDL_WaitThread(EmuThread, NULL); -} - - -void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params) -{ - if (!ScreenDrawInited) - { - if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); - if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); - - ScreenDrawInited = true; - ScreenBitmap[0] = uiDrawNewBitmap(params->Context, 256, 192, 0); - ScreenBitmap[1] = uiDrawNewBitmap(params->Context, 256, 192, 0); - } - - int frontbuf = GPU::FrontBuffer; - if (!ScreenBitmap[0] || !ScreenBitmap[1]) return; - if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return; - - uiRect top = {0, 0, 256, 192}; - uiRect bot = {0, 0, 256, 192}; - - uiDrawBitmapUpdate(ScreenBitmap[0], GPU::Framebuffer[frontbuf][0]); - uiDrawBitmapUpdate(ScreenBitmap[1], GPU::Framebuffer[frontbuf][1]); - - uiDrawSave(params->Context); - uiDrawTransform(params->Context, &TopScreenTrans); - uiDrawBitmapDraw(params->Context, ScreenBitmap[0], &top, &TopScreenRect, Config::ScreenFilter==1); - uiDrawRestore(params->Context); - - uiDrawSave(params->Context); - uiDrawTransform(params->Context, &BottomScreenTrans); - uiDrawBitmapDraw(params->Context, ScreenBitmap[1], &bot, &BottomScreenRect, Config::ScreenFilter==1); - uiDrawRestore(params->Context); - - OSD::Update(false, params); -} - -void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt) -{ - int x = (int)evt->X; - int y = (int)evt->Y; - - if (Touching && (evt->Up == 1)) - { - Touching = false; - NDS::ReleaseKey(16+6); - NDS::ReleaseScreen(); - } - else if (!Touching && (evt->Down == 1) && - (x >= BottomScreenRect.X) && (y >= BottomScreenRect.Y) && - (x < (BottomScreenRect.X+BottomScreenRect.Width)) && (y < (BottomScreenRect.Y+BottomScreenRect.Height))) - { - Touching = true; - NDS::PressKey(16+6); - } - - if (Touching) - { - x -= BottomScreenRect.X; - y -= BottomScreenRect.Y; - - if (ScreenRotation == 0 || ScreenRotation == 2) - { - if (BottomScreenRect.Width != 256) - x = (x * 256) / BottomScreenRect.Width; - if (BottomScreenRect.Height != 192) - y = (y * 192) / BottomScreenRect.Height; - - if (ScreenRotation == 2) - { - x = 255 - x; - y = 191 - y; - } - } - else - { - if (BottomScreenRect.Width != 192) - x = (x * 192) / BottomScreenRect.Width; - if (BottomScreenRect.Height != 256) - y = (y * 256) / BottomScreenRect.Height; - - if (ScreenRotation == 1) - { - int tmp = x; - x = y; - y = 191 - tmp; - } - else - { - int tmp = x; - x = 255 - y; - y = tmp; - } - } - - // clamp - if (x < 0) x = 0; - else if (x > 255) x = 255; - if (y < 0) y = 0; - else if (y > 191) y = 191; - - // TODO: take advantage of possible extra precision when possible? (scaled window for example) - NDS::TouchScreen(x, y); - } -} - -void OnAreaMouseCrossed(uiAreaHandler* handler, uiArea* area, int left) -{ -} - -void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area) -{ -} - -bool EventMatchesKey(uiAreaKeyEvent* evt, int val, bool checkmod) -{ - if (val == -1) return false; - - int key = val & 0xFFFF; - int mod = val >> 16; - return evt->Scancode == key && (!checkmod || evt->Modifiers == mod); -} - -int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt) -{ - // TODO: release all keys if the window loses focus? or somehow global key input? - if (evt->Scancode == 0x38) // ALT - return 0; - if (evt->Modifiers == 0x2) // ALT+key - return 0; - - if (evt->Up) - { - for (int i = 0; i < 12; i++) - if (EventMatchesKey(evt, Config::KeyMapping[i], false)) - KeyInputMask |= (1<Repeat) - { - // TODO, eventually: make savestate keys configurable? - // F keys: 3B-44, 57-58 | SHIFT: mod. 0x4 - if (evt->Scancode >= 0x3B && evt->Scancode <= 0x42) // F1-F8, quick savestate - { - if (evt->Modifiers == 0x4) SaveState(1 + (evt->Scancode - 0x3B)); - else if (evt->Modifiers == 0x0) LoadState(1 + (evt->Scancode - 0x3B)); - } - else if (evt->Scancode == 0x43) // F9, savestate from/to file - { - if (evt->Modifiers == 0x4) SaveState(0); - else if (evt->Modifiers == 0x0) LoadState(0); - } - else if (evt->Scancode == 0x58) // F12, undo savestate - { - if (evt->Modifiers == 0x0) UndoStateLoad(); - } - - for (int i = 0; i < 12; i++) - if (EventMatchesKey(evt, Config::KeyMapping[i], false)) - KeyInputMask &= ~(1<Scancode == 0x57) // F11 - // NDS::debug(0); - } - - return 1; -} - -void SetupScreenRects(int width, int height) -{ - bool horizontal = false; - bool sideways = false; - - if (ScreenRotation == 1 || ScreenRotation == 3) - sideways = true; - - if (ScreenLayout == 2) horizontal = true; - else if (ScreenLayout == 0) - { - if (sideways) - horizontal = true; - } - - int sizemode; - if (ScreenSizing == 3) - sizemode = AutoScreenSizing; - else - sizemode = ScreenSizing; - - int screenW, screenH, gap; - if (sideways) - { - screenW = 192; - screenH = 256; - } - else - { - screenW = 256; - screenH = 192; - } - - gap = ScreenGap; - - uiRect *topscreen, *bottomscreen; - if (ScreenRotation == 1 || ScreenRotation == 2) - { - topscreen = &BottomScreenRect; - bottomscreen = &TopScreenRect; - } - else - { - topscreen = &TopScreenRect; - bottomscreen = &BottomScreenRect; - } - - if (horizontal) - { - // side-by-side - - int heightreq; - int startX = 0; - - width -= gap; - - if (sizemode == 0) // even - { - heightreq = (width * screenH) / (screenW*2); - if (heightreq > height) - { - int newwidth = (height * width) / heightreq; - startX = (width - newwidth) / 2; - heightreq = height; - width = newwidth; - } - } - else // emph. top/bottom - { - heightreq = ((width - screenW) * screenH) / screenW; - if (heightreq > height) - { - int newwidth = ((height * (width - screenW)) / heightreq) + screenW; - startX = (width - newwidth) / 2; - heightreq = height; - width = newwidth; - } - } - - if (sizemode == 2) - { - topscreen->Width = screenW; - topscreen->Height = screenH; - } - else - { - topscreen->Width = (sizemode==0) ? (width / 2) : (width - screenW); - topscreen->Height = heightreq; - } - topscreen->X = startX; - topscreen->Y = ((height - heightreq) / 2) + (heightreq - topscreen->Height); - - bottomscreen->X = topscreen->X + topscreen->Width + gap; - - if (sizemode == 1) - { - bottomscreen->Width = screenW; - bottomscreen->Height = screenH; - } - else - { - bottomscreen->Width = width - topscreen->Width; - bottomscreen->Height = heightreq; - } - bottomscreen->Y = ((height - heightreq) / 2) + (heightreq - bottomscreen->Height); - } - else - { - // top then bottom - - int widthreq; - int startY = 0; - - height -= gap; - - if (sizemode == 0) // even - { - widthreq = (height * screenW) / (screenH*2); - if (widthreq > width) - { - int newheight = (width * height) / widthreq; - startY = (height - newheight) / 2; - widthreq = width; - height = newheight; - } - } - else // emph. top/bottom - { - widthreq = ((height - screenH) * screenW) / screenH; - if (widthreq > width) - { - int newheight = ((width * (height - screenH)) / widthreq) + screenH; - startY = (height - newheight) / 2; - widthreq = width; - height = newheight; - } - } - - if (sizemode == 2) - { - topscreen->Width = screenW; - topscreen->Height = screenH; - } - else - { - topscreen->Width = widthreq; - topscreen->Height = (sizemode==0) ? (height / 2) : (height - screenH); - } - topscreen->Y = startY; - topscreen->X = (width - topscreen->Width) / 2; - - bottomscreen->Y = topscreen->Y + topscreen->Height + gap; - - if (sizemode == 1) - { - bottomscreen->Width = screenW; - bottomscreen->Height = screenH; - } - else - { - bottomscreen->Width = widthreq; - bottomscreen->Height = height - topscreen->Height; - } - bottomscreen->X = (width - bottomscreen->Width) / 2; - } - - // setup matrices for potential rotation - - uiDrawMatrixSetIdentity(&TopScreenTrans); - uiDrawMatrixSetIdentity(&BottomScreenTrans); - - switch (ScreenRotation) - { - case 1: // 90° - { - uiDrawMatrixTranslate(&TopScreenTrans, -TopScreenRect.X, -TopScreenRect.Y); - uiDrawMatrixRotate(&TopScreenTrans, 0, 0, M_PI/2.0f); - uiDrawMatrixScale(&TopScreenTrans, 0, 0, - TopScreenRect.Width/(double)TopScreenRect.Height, - TopScreenRect.Height/(double)TopScreenRect.Width); - uiDrawMatrixTranslate(&TopScreenTrans, TopScreenRect.X+TopScreenRect.Width, TopScreenRect.Y); - - uiDrawMatrixTranslate(&BottomScreenTrans, -BottomScreenRect.X, -BottomScreenRect.Y); - uiDrawMatrixRotate(&BottomScreenTrans, 0, 0, M_PI/2.0f); - uiDrawMatrixScale(&BottomScreenTrans, 0, 0, - BottomScreenRect.Width/(double)BottomScreenRect.Height, - BottomScreenRect.Height/(double)BottomScreenRect.Width); - uiDrawMatrixTranslate(&BottomScreenTrans, BottomScreenRect.X+BottomScreenRect.Width, BottomScreenRect.Y); - } - break; - - case 2: // 180° - { - uiDrawMatrixTranslate(&TopScreenTrans, -TopScreenRect.X, -TopScreenRect.Y); - uiDrawMatrixRotate(&TopScreenTrans, 0, 0, M_PI); - uiDrawMatrixTranslate(&TopScreenTrans, TopScreenRect.X+TopScreenRect.Width, TopScreenRect.Y+TopScreenRect.Height); - - uiDrawMatrixTranslate(&BottomScreenTrans, -BottomScreenRect.X, -BottomScreenRect.Y); - uiDrawMatrixRotate(&BottomScreenTrans, 0, 0, M_PI); - uiDrawMatrixTranslate(&BottomScreenTrans, BottomScreenRect.X+BottomScreenRect.Width, BottomScreenRect.Y+BottomScreenRect.Height); - } - break; - - case 3: // 270° - { - uiDrawMatrixTranslate(&TopScreenTrans, -TopScreenRect.X, -TopScreenRect.Y); - uiDrawMatrixRotate(&TopScreenTrans, 0, 0, -M_PI/2.0f); - uiDrawMatrixScale(&TopScreenTrans, 0, 0, - TopScreenRect.Width/(double)TopScreenRect.Height, - TopScreenRect.Height/(double)TopScreenRect.Width); - uiDrawMatrixTranslate(&TopScreenTrans, TopScreenRect.X, TopScreenRect.Y+TopScreenRect.Height); - - uiDrawMatrixTranslate(&BottomScreenTrans, -BottomScreenRect.X, -BottomScreenRect.Y); - uiDrawMatrixRotate(&BottomScreenTrans, 0, 0, -M_PI/2.0f); - uiDrawMatrixScale(&BottomScreenTrans, 0, 0, - BottomScreenRect.Width/(double)BottomScreenRect.Height, - BottomScreenRect.Height/(double)BottomScreenRect.Width); - uiDrawMatrixTranslate(&BottomScreenTrans, BottomScreenRect.X, BottomScreenRect.Y+BottomScreenRect.Height); - } - break; - } - - GL_ScreenSizeDirty = true; -} - -void SetMinSize(int w, int h) -{ - int cw, ch; - uiWindowContentSize(MainWindow, &cw, &ch); - - uiControlSetMinSize(uiControl(MainDrawArea), w, h); - if ((cw < w) || (ch < h)) - { - if (cw < w) cw = w; - if (ch < h) ch = h; - uiWindowSetContentSize(MainWindow, cw, ch); - } -} - -void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height) -{ - SetupScreenRects(width, height); - - // TODO: - // should those be the size of the uiArea, or the size of the window client area? - // for now the uiArea fills the whole window anyway - // but... we never know, I guess - WindowWidth = width; - WindowHeight = height; - - int ismax = uiWindowMaximized(MainWindow); - int ismin = uiWindowMinimized(MainWindow); - - Config::WindowMaximized = ismax; - if (!ismax && !ismin) - { - Config::WindowWidth = width; - Config::WindowHeight = height; - } - - OSD::WindowResized(Screen_UseGL); -} - - -void Run() -{ - EmuRunning = 1; - RunningSomething = true; - - SPU::InitOutput(); - AudioSampleFrac = 0; - SDL_PauseAudioDevice(AudioDevice, 0); - SDL_PauseAudioDevice(MicDevice, 0); - - uiMenuItemEnable(MenuItem_SaveState); - uiMenuItemEnable(MenuItem_LoadState); - - if (SavestateLoaded) - uiMenuItemEnable(MenuItem_UndoStateLoad); - else - uiMenuItemDisable(MenuItem_UndoStateLoad); - - for (int i = 0; i < 8; i++) - { - char ssfile[1024]; - GetSavestateName(i+1, ssfile, 1024); - if (Platform::FileExists(ssfile)) uiMenuItemEnable(MenuItem_LoadStateSlot[i]); - else uiMenuItemDisable(MenuItem_LoadStateSlot[i]); - } - - for (int i = 0; i < 9; i++) uiMenuItemEnable(MenuItem_SaveStateSlot[i]); - uiMenuItemEnable(MenuItem_LoadStateSlot[8]); - - uiMenuItemEnable(MenuItem_Pause); - uiMenuItemEnable(MenuItem_Reset); - uiMenuItemEnable(MenuItem_Stop); - uiMenuItemSetChecked(MenuItem_Pause, 0); -} - -void TogglePause(void* blarg) -{ - if (!RunningSomething) return; - - if (EmuRunning == 1) - { - // enable pause - EmuRunning = 2; - uiMenuItemSetChecked(MenuItem_Pause, 1); - - SPU::DrainOutput(); - SDL_PauseAudioDevice(AudioDevice, 1); - SDL_PauseAudioDevice(MicDevice, 1); - - OSD::AddMessage(0, "Paused"); - } - else - { - // disable pause - EmuRunning = 1; - uiMenuItemSetChecked(MenuItem_Pause, 0); - - SPU::InitOutput(); - AudioSampleFrac = 0; - SDL_PauseAudioDevice(AudioDevice, 0); - SDL_PauseAudioDevice(MicDevice, 0); - - OSD::AddMessage(0, "Resumed"); - } -} - -void Reset(void* blarg) -{ - if (!RunningSomething) return; - - EmuRunning = 2; - while (EmuStatus != 2); - - SavestateLoaded = false; - uiMenuItemDisable(MenuItem_UndoStateLoad); - - if (ROMPath[0][0] == '\0') - NDS::LoadBIOS(); - else - { - SetupSRAMPath(0); - NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot); - } - - if (ROMPath[1][0] != '\0') - { - SetupSRAMPath(1); - NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); - } - - Run(); - - OSD::AddMessage(0, "Reset"); -} - -void Stop(bool internal) -{ - EmuRunning = 2; - if (!internal) // if shutting down from the UI thread, wait till the emu thread has stopped - while (EmuStatus != 2); - RunningSomething = false; - - // eject any inserted GBA cartridge - GBACart::Eject(); - ROMPath[1][0] = '\0'; - - uiWindowSetTitle(MainWindow, "melonDS " MELONDS_VERSION); - - for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); - for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]); - uiMenuItemDisable(MenuItem_UndoStateLoad); - - uiMenuItemDisable(MenuItem_Pause); - uiMenuItemDisable(MenuItem_Reset); - uiMenuItemDisable(MenuItem_Stop); - uiMenuItemSetChecked(MenuItem_Pause, 0); - - uiAreaQueueRedrawAll(MainDrawArea); - - SPU::DrainOutput(); - SDL_PauseAudioDevice(AudioDevice, 1); - SDL_PauseAudioDevice(MicDevice, 1); - - OSD::AddMessage(0xFFC040, "Shutdown"); -} - -void SetupSRAMPath(int slot) -{ - strncpy(SRAMPath[slot], ROMPath[slot], 1023); - SRAMPath[slot][1023] = '\0'; - strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); -} - -void TryLoadROM(char* file, int slot, int prevstatus) -{ - char oldpath[1024]; - char oldsram[1024]; - strncpy(oldpath, ROMPath[slot], 1024); - strncpy(oldsram, SRAMPath[slot], 1024); - - strncpy(ROMPath[slot], file, 1023); - ROMPath[slot][1023] = '\0'; - - SetupSRAMPath(0); - SetupSRAMPath(1); - - if (slot == 0 && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot)) - { - SavestateLoaded = false; - uiMenuItemDisable(MenuItem_UndoStateLoad); - - // Reload the inserted GBA cartridge (if any) - if (ROMPath[1][0] != '\0') NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); - - strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety - Run(); - } - else if (slot == 1 && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) - { - SavestateLoaded = false; - uiMenuItemDisable(MenuItem_UndoStateLoad); - - strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety - if (RunningSomething) Run(); // do not start just from a GBA cart - } - else - { - uiMsgBoxError(MainWindow, - "Failed to load the ROM", - "Make sure the file can be accessed and isn't opened in another application."); - - strncpy(ROMPath[slot], oldpath, 1024); - strncpy(SRAMPath[slot], oldsram, 1024); - EmuRunning = prevstatus; - } -} - - -// SAVESTATE TODO -// * configurable paths. not everyone wants their ROM directory to be polluted, I guess. - -void GetSavestateName(int slot, char* filename, int len) -{ - int pos; - - if (ROMPath[0][0] == '\0') // running firmware, no ROM - { - strcpy(filename, "firmware"); - pos = 8; - } - else - { - int l = strlen(ROMPath[0]); - pos = l; - while (ROMPath[0][pos] != '.' && pos > 0) pos--; - if (pos == 0) pos = l; - - // avoid buffer overflow. shoddy - if (pos > len-5) pos = len-5; - - strncpy(&filename[0], ROMPath[0], pos); - } - strcpy(&filename[pos], ".ml"); - filename[pos+3] = '0'+slot; - filename[pos+4] = '\0'; -} - -void LoadState(int slot) -{ - int prevstatus = EmuRunning; - EmuRunning = 2; - while (EmuStatus != 2); - - char filename[1024]; - - if (slot > 0) - { - GetSavestateName(slot, filename, 1024); - } - else - { - char* file = uiOpenFile(MainWindow, "melonDS savestate (any)|*.ml1;*.ml2;*.ml3;*.ml4;*.ml5;*.ml6;*.ml7;*.ml8;*.mln", Config::LastROMFolder); - if (!file) - { - EmuRunning = prevstatus; - return; - } - - strncpy(filename, file, 1023); - filename[1023] = '\0'; - uiFreeText(file); - } - - if (!Platform::FileExists(filename)) - { - char msg[64]; - if (slot > 0) sprintf(msg, "State slot %d is empty", slot); - else sprintf(msg, "State file does not exist"); - OSD::AddMessage(0xFFA0A0, msg); - - EmuRunning = prevstatus; - return; - } - - u32 oldGBACartCRC = GBACart::CartCRC; - - // backup - Savestate* backup = new Savestate("timewarp.mln", true); - NDS::DoSavestate(backup); - delete backup; - - bool failed = false; - - Savestate* state = new Savestate(filename, false); - if (state->Error) - { - delete state; - - uiMsgBoxError(MainWindow, "Error", "Could not load savestate file."); - - // current state might be crapoed, so restore from sane backup - state = new Savestate("timewarp.mln", false); - failed = true; - } - - NDS::DoSavestate(state); - delete state; - - if (!failed) - { - if (Config::SavestateRelocSRAM && ROMPath[0][0]!='\0') - { - strncpy(PrevSRAMPath[0], SRAMPath[0], 1024); - - strncpy(SRAMPath[0], filename, 1019); - int len = strlen(SRAMPath[0]); - strcpy(&SRAMPath[0][len], ".sav"); - SRAMPath[0][len+4] = '\0'; - - NDS::RelocateSave(SRAMPath[0], false); - } - - bool loadedPartialGBAROM = false; - - // in case we have a GBA cart inserted, and the GBA ROM changes - // due to having loaded a save state, we do not want to reload - // the previous cartridge on reset, or commit writes to any - // loaded save file. therefore, their paths are "nulled". - if (GBACart::CartInserted && GBACart::CartCRC != oldGBACartCRC) - { - ROMPath[1][0] = '\0'; - SRAMPath[1][0] = '\0'; - loadedPartialGBAROM = true; - } - - char msg[64]; - if (slot > 0) sprintf(msg, "State loaded from slot %d%s", - slot, loadedPartialGBAROM ? " (GBA ROM header only)" : ""); - else sprintf(msg, "State loaded from file%s", - loadedPartialGBAROM ? " (GBA ROM header only)" : ""); - OSD::AddMessage(0, msg); - - SavestateLoaded = true; - uiMenuItemEnable(MenuItem_UndoStateLoad); - } - - EmuRunning = prevstatus; -} - -void SaveState(int slot) -{ - int prevstatus = EmuRunning; - EmuRunning = 2; - while (EmuStatus != 2); - - char filename[1024]; - - if (slot > 0) - { - GetSavestateName(slot, filename, 1024); - } - else - { - char* file = uiSaveFile(MainWindow, "melonDS savestate (*.mln)|*.mln", Config::LastROMFolder); - if (!file) - { - EmuRunning = prevstatus; - return; - } - - strncpy(filename, file, 1023); - filename[1023] = '\0'; - uiFreeText(file); - } - - Savestate* state = new Savestate(filename, true); - if (state->Error) - { - delete state; - - uiMsgBoxError(MainWindow, "Error", "Could not save state."); - } - else - { - NDS::DoSavestate(state); - delete state; - - if (slot > 0) - uiMenuItemEnable(MenuItem_LoadStateSlot[slot-1]); - - if (Config::SavestateRelocSRAM && ROMPath[0][0]!='\0') - { - strncpy(SRAMPath[0], filename, 1019); - int len = strlen(SRAMPath[0]); - strcpy(&SRAMPath[0][len], ".sav"); - SRAMPath[0][len+4] = '\0'; - - NDS::RelocateSave(SRAMPath[0], true); - } - } - - char msg[64]; - if (slot > 0) sprintf(msg, "State saved to slot %d", slot); - else sprintf(msg, "State saved to file"); - OSD::AddMessage(0, msg); - - EmuRunning = prevstatus; -} - -void UndoStateLoad() -{ - if (!SavestateLoaded) return; - - int prevstatus = EmuRunning; - EmuRunning = 2; - while (EmuStatus != 2); - - // pray that this works - // what do we do if it doesn't??? - // but it should work. - Savestate* backup = new Savestate("timewarp.mln", false); - NDS::DoSavestate(backup); - delete backup; - - if (ROMPath[0][0]!='\0') - { - strncpy(SRAMPath[0], PrevSRAMPath[0], 1024); - NDS::RelocateSave(SRAMPath[0], false); - } - - OSD::AddMessage(0, "State load undone"); - - EmuRunning = prevstatus; -} - - -void CloseAllDialogs() -{ - DlgAudioSettings::Close(); - DlgEmuSettings::Close(); - DlgInputConfig::Close(0); - DlgInputConfig::Close(1); - DlgVideoSettings::Close(); - DlgWifiSettings::Close(); -} - - -int OnCloseWindow(uiWindow* window, void* blarg) -{ - EmuRunning = 3; - while (EmuStatus != 3); - - CloseAllDialogs(); - StopEmuThread(); - uiQuit(); - return 1; -} - -void OnDropFile(uiWindow* window, char* file, void* blarg) -{ - char* ext = &file[strlen(file)-3]; - int prevstatus = EmuRunning; - - if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl")) - { - if (RunningSomething) - { - EmuRunning = 2; - while (EmuStatus != 2); - } - - TryLoadROM(file, 0, prevstatus); - } - else if (!strcasecmp(ext, "gba")) - { - TryLoadROM(file, 1, prevstatus); - } -} - -void OnGetFocus(uiWindow* window, void* blarg) -{ - uiControlSetFocus(uiControl(MainDrawArea)); -} - -void OnLoseFocus(uiWindow* window, void* blarg) -{ - // TODO: shit here? -} - -void OnCloseByMenu(uiMenuItem* item, uiWindow* window, void* blarg) -{ - EmuRunning = 3; - while (EmuStatus != 3); - - CloseAllDialogs(); - StopEmuThread(); - DestroyMainWindow(); - uiQuit(); -} - -void OnOpenFile(uiMenuItem* item, uiWindow* window, void* blarg) -{ - int prevstatus = EmuRunning; - EmuRunning = 2; - while (EmuStatus != 2); - - char* file = uiOpenFile(window, "DS ROM (*.nds)|*.nds;*.srl|GBA ROM (*.gba)|*.gba|Any file|*.*", Config::LastROMFolder); - if (!file) - { - EmuRunning = prevstatus; - return; - } - - int pos = strlen(file)-1; - while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--; - strncpy(Config::LastROMFolder, file, pos); - Config::LastROMFolder[pos] = '\0'; - char* ext = &file[strlen(file)-3]; - - if (!strcasecmp(ext, "gba")) - { - TryLoadROM(file, 1, prevstatus); - } - else - { - TryLoadROM(file, 0, prevstatus); - } - - uiFreeText(file); -} - -void OnSaveState(uiMenuItem* item, uiWindow* window, void* param) -{ - int slot = *(int*)param; - SaveState(slot); -} - -void OnLoadState(uiMenuItem* item, uiWindow* window, void* param) -{ - int slot = *(int*)param; - LoadState(slot); -} - -void OnUndoStateLoad(uiMenuItem* item, uiWindow* window, void* param) -{ - UndoStateLoad(); -} - -void OnRun(uiMenuItem* item, uiWindow* window, void* blarg) -{ - if (!RunningSomething) - { - ROMPath[0][0] = '\0'; - NDS::LoadBIOS(); - - if (ROMPath[1][0] != '\0') - { - SetupSRAMPath(1); - NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); - } - } - - Run(); -} - -void OnPause(uiMenuItem* item, uiWindow* window, void* blarg) -{ - TogglePause(NULL); -} - -void OnReset(uiMenuItem* item, uiWindow* window, void* blarg) -{ - Reset(NULL); -} - -void OnStop(uiMenuItem* item, uiWindow* window, void* blarg) -{ - if (!RunningSomething) return; - - Stop(false); -} - -void OnOpenEmuSettings(uiMenuItem* item, uiWindow* window, void* blarg) -{ - DlgEmuSettings::Open(); -} - -void OnOpenInputConfig(uiMenuItem* item, uiWindow* window, void* blarg) -{ - DlgInputConfig::Open(0); -} - -void OnOpenHotkeyConfig(uiMenuItem* item, uiWindow* window, void* blarg) -{ - DlgInputConfig::Open(1); -} - -void OnOpenVideoSettings(uiMenuItem* item, uiWindow* window, void* blarg) -{ - DlgVideoSettings::Open(); -} - -void OnOpenAudioSettings(uiMenuItem* item, uiWindow* window, void* blarg) -{ - DlgAudioSettings::Open(); -} - -void OnOpenWifiSettings(uiMenuItem* item, uiWindow* window, void* blarg) -{ - DlgWifiSettings::Open(); -} - - -void OnSetSavestateSRAMReloc(uiMenuItem* item, uiWindow* window, void* param) -{ - Config::SavestateRelocSRAM = uiMenuItemChecked(item) ? 1:0; -} - - -void EnsureProperMinSize() -{ - bool isHori = (ScreenRotation == 1 || ScreenRotation == 3); - - int w0 = 256; - int h0 = 192; - int w1 = 256; - int h1 = 192; - - if (ScreenLayout == 0) // natural - { - if (isHori) - SetMinSize(h0+ScreenGap+h1, std::max(w0,w1)); - else - SetMinSize(std::max(w0,w1), h0+ScreenGap+h1); - } - else if (ScreenLayout == 1) // vertical - { - if (isHori) - SetMinSize(std::max(h0,h1), w0+ScreenGap+w1); - else - SetMinSize(std::max(w0,w1), h0+ScreenGap+h1); - } - else // horizontal - { - if (isHori) - SetMinSize(h0+ScreenGap+h1, std::max(w0,w1)); - else - SetMinSize(w0+ScreenGap+w1, std::max(h0,h1)); - } -} - -void OnSetScreenSize(uiMenuItem* item, uiWindow* window, void* param) -{ - int factor = *(int*)param; - bool isHori = (ScreenRotation == 1 || ScreenRotation == 3); - - int w = 256*factor; - int h = 192*factor; - - // FIXME - - if (ScreenLayout == 0) // natural - { - if (isHori) - uiWindowSetContentSize(window, (h*2)+ScreenGap, w); - else - uiWindowSetContentSize(window, w, (h*2)+ScreenGap); - } - else if (ScreenLayout == 1) // vertical - { - if (isHori) - uiWindowSetContentSize(window, h, (w*2)+ScreenGap); - else - uiWindowSetContentSize(window, w, (h*2)+ScreenGap); - } - else // horizontal - { - if (isHori) - uiWindowSetContentSize(window, (h*2)+ScreenGap, w); - else - uiWindowSetContentSize(window, (w*2)+ScreenGap, h); - } -} - -void OnSetScreenRotation(uiMenuItem* item, uiWindow* window, void* param) -{ - int rot = *(int*)param; - - int oldrot = ScreenRotation; - ScreenRotation = rot; - - int w, h; - uiWindowContentSize(window, &w, &h); - - bool isHori = (rot == 1 || rot == 3); - bool wasHori = (oldrot == 1 || oldrot == 3); - - EnsureProperMinSize(); - - if (ScreenLayout == 0) // natural - { - if (isHori ^ wasHori) - { - int blarg = h; - h = w; - w = blarg; - - uiWindowSetContentSize(window, w, h); - } - } - - SetupScreenRects(w, h); - - for (int i = 0; i < 4; i++) - uiMenuItemSetChecked(MenuItem_ScreenRot[i], i==ScreenRotation); -} - -void OnSetScreenGap(uiMenuItem* item, uiWindow* window, void* param) -{ - int gap = *(int*)param; - - //int oldgap = ScreenGap; - ScreenGap = gap; - - EnsureProperMinSize(); - SetupScreenRects(WindowWidth, WindowHeight); - - for (int i = 0; i < 6; i++) - uiMenuItemSetChecked(MenuItem_ScreenGap[i], kScreenGap[i]==ScreenGap); -} - -void OnSetScreenLayout(uiMenuItem* item, uiWindow* window, void* param) -{ - int layout = *(int*)param; - ScreenLayout = layout; - - EnsureProperMinSize(); - SetupScreenRects(WindowWidth, WindowHeight); - - for (int i = 0; i < 3; i++) - uiMenuItemSetChecked(MenuItem_ScreenLayout[i], i==ScreenLayout); -} - -void OnSetScreenSizing(uiMenuItem* item, uiWindow* window, void* param) -{ - int sizing = *(int*)param; - ScreenSizing = sizing; - - SetupScreenRects(WindowWidth, WindowHeight); - - for (int i = 0; i < 4; i++) - uiMenuItemSetChecked(MenuItem_ScreenSizing[i], i==ScreenSizing); -} - -void OnSetScreenFiltering(uiMenuItem* item, uiWindow* window, void* blarg) -{ - int chk = uiMenuItemChecked(item); - if (chk != 0) Config::ScreenFilter = 1; - else Config::ScreenFilter = 0; -} - -void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg) -{ - int chk = uiMenuItemChecked(item); - if (chk != 0) Config::LimitFPS = true; - else Config::LimitFPS = false; -} - -void OnSetAudioSync(uiMenuItem* item, uiWindow* window, void* blarg) -{ - int chk = uiMenuItemChecked(item); - if (chk != 0) Config::AudioSync = true; - else Config::AudioSync = false; -} - -void OnSetShowOSD(uiMenuItem* item, uiWindow* window, void* blarg) -{ - int chk = uiMenuItemChecked(item); - if (chk != 0) Config::ShowOSD = true; - else Config::ShowOSD = false; -} - -void ApplyNewSettings(int type) -{ - if (!RunningSomething) - { - if (type == 1) return; - } - - int prevstatus = EmuRunning; - EmuRunning = 3; - while (EmuStatus != 3); - - if (type == 0) // 3D renderer settings - { - if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); - GPU3D::UpdateRendererConfig(); - if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - - GL_3DScale = Config::GL_ScaleFactor; // dorp - GL_ScreenSizeDirty = true; - } - else if (type == 1) // wifi settings - { - if (Wifi::MPInited) - { - Platform::MP_DeInit(); - Platform::MP_Init(); - } - - Platform::LAN_DeInit(); - Platform::LAN_Init(); - } - else if (type == 2) // video output method - { - bool usegl = Config::ScreenUseGL || (Config::_3DRenderer != 0); - if (usegl != Screen_UseGL) - { - if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); - GPU3D::DeInitRenderer(); - OSD::DeInit(Screen_UseGL); - if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - - Screen_UseGL = usegl; - RecreateMainWindow(usegl); - - if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); - GPU3D::InitRenderer(Screen_UseGL); - if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - } - } - else if (type == 3) // 3D renderer - { - if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); - GPU3D::DeInitRenderer(); - GPU3D::InitRenderer(Screen_UseGL); - if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - } - /*else if (type == 4) // vsync - { - if (Screen_UseGL) - { - uiGLMakeContextCurrent(GLContext); - uiGLSetVSync(Config::ScreenVSync); - uiGLMakeContextCurrent(NULL); - } - else - { - // TODO eventually: VSync for non-GL screen? - } - }*/ - - EmuRunning = prevstatus; -} - - -void CreateMainWindowMenu() -{ - uiMenu* menu; - uiMenuItem* menuitem; - - menu = uiNewMenu("File"); - menuitem = uiMenuAppendItem(menu, "Open ROM..."); - uiMenuItemOnClicked(menuitem, OnOpenFile, NULL); - uiMenuAppendSeparator(menu); - { - uiMenu* submenu = uiNewMenu("Save state"); - - for (int i = 0; i < 9; i++) - { - char name[32]; - if (i < 8) - sprintf(name, "%d\tShift+F%d", kSavestateNum[i], kSavestateNum[i]); - else - strcpy(name, "File...\tShift+F9"); - - uiMenuItem* ssitem = uiMenuAppendItem(submenu, name); - uiMenuItemOnClicked(ssitem, OnSaveState, (void*)&kSavestateNum[i]); - - MenuItem_SaveStateSlot[i] = ssitem; - } - - MenuItem_SaveState = uiMenuAppendSubmenu(menu, submenu); - } - { - uiMenu* submenu = uiNewMenu("Load state"); - - for (int i = 0; i < 9; i++) - { - char name[32]; - if (i < 8) - sprintf(name, "%d\tF%d", kSavestateNum[i], kSavestateNum[i]); - else - strcpy(name, "File...\tF9"); - - uiMenuItem* ssitem = uiMenuAppendItem(submenu, name); - uiMenuItemOnClicked(ssitem, OnLoadState, (void*)&kSavestateNum[i]); - - MenuItem_LoadStateSlot[i] = ssitem; - } - - MenuItem_LoadState = uiMenuAppendSubmenu(menu, submenu); - } - menuitem = uiMenuAppendItem(menu, "Undo state load\tF12"); - uiMenuItemOnClicked(menuitem, OnUndoStateLoad, NULL); - MenuItem_UndoStateLoad = menuitem; - uiMenuAppendSeparator(menu); - menuitem = uiMenuAppendItem(menu, "Quit"); - uiMenuItemOnClicked(menuitem, OnCloseByMenu, NULL); - - menu = uiNewMenu("System"); - menuitem = uiMenuAppendItem(menu, "Run"); - uiMenuItemOnClicked(menuitem, OnRun, NULL); - menuitem = uiMenuAppendCheckItem(menu, "Pause"); - uiMenuItemOnClicked(menuitem, OnPause, NULL); - MenuItem_Pause = menuitem; - uiMenuAppendSeparator(menu); - menuitem = uiMenuAppendItem(menu, "Reset"); - uiMenuItemOnClicked(menuitem, OnReset, NULL); - MenuItem_Reset = menuitem; - menuitem = uiMenuAppendItem(menu, "Stop"); - uiMenuItemOnClicked(menuitem, OnStop, NULL); - MenuItem_Stop = menuitem; - - menu = uiNewMenu("Config"); - { - menuitem = uiMenuAppendItem(menu, "Emu settings"); - uiMenuItemOnClicked(menuitem, OnOpenEmuSettings, NULL); - menuitem = uiMenuAppendItem(menu, "Input config"); - uiMenuItemOnClicked(menuitem, OnOpenInputConfig, NULL); - menuitem = uiMenuAppendItem(menu, "Hotkey config"); - uiMenuItemOnClicked(menuitem, OnOpenHotkeyConfig, NULL); - menuitem = uiMenuAppendItem(menu, "Video settings"); - uiMenuItemOnClicked(menuitem, OnOpenVideoSettings, NULL); - menuitem = uiMenuAppendItem(menu, "Audio settings"); - uiMenuItemOnClicked(menuitem, OnOpenAudioSettings, NULL); - menuitem = uiMenuAppendItem(menu, "Wifi settings"); - uiMenuItemOnClicked(menuitem, OnOpenWifiSettings, NULL); - } - uiMenuAppendSeparator(menu); - { - uiMenu* submenu = uiNewMenu("Savestate settings"); - - MenuItem_SavestateSRAMReloc = uiMenuAppendCheckItem(submenu, "Separate savefiles"); - uiMenuItemOnClicked(MenuItem_SavestateSRAMReloc, OnSetSavestateSRAMReloc, NULL); - - uiMenuAppendSubmenu(menu, submenu); - } - uiMenuAppendSeparator(menu); - { - uiMenu* submenu = uiNewMenu("Screen size"); - - for (int i = 0; i < 4; i++) - { - char name[32]; - sprintf(name, "%dx", kScreenSize[i]); - uiMenuItem* item = uiMenuAppendItem(submenu, name); - uiMenuItemOnClicked(item, OnSetScreenSize, (void*)&kScreenSize[i]); - } - - uiMenuAppendSubmenu(menu, submenu); - } - { - uiMenu* submenu = uiNewMenu("Screen rotation"); - - for (int i = 0; i < 4; i++) - { - char name[32]; - sprintf(name, "%d", kScreenRot[i]*90); - MenuItem_ScreenRot[i] = uiMenuAppendCheckItem(submenu, name); - uiMenuItemOnClicked(MenuItem_ScreenRot[i], OnSetScreenRotation, (void*)&kScreenRot[i]); - } - - uiMenuAppendSubmenu(menu, submenu); - } - { - uiMenu* submenu = uiNewMenu("Mid-screen gap"); - - //for (int i = 0; kScreenGap[i] != -1; i++) - for (int i = 0; i < 6; i++) - { - char name[32]; - sprintf(name, "%d pixels", kScreenGap[i]); - MenuItem_ScreenGap[i] = uiMenuAppendCheckItem(submenu, name); - uiMenuItemOnClicked(MenuItem_ScreenGap[i], OnSetScreenGap, (void*)&kScreenGap[i]); - } - - uiMenuAppendSubmenu(menu, submenu); - } - { - uiMenu* submenu = uiNewMenu("Screen layout"); - - MenuItem_ScreenLayout[0] = uiMenuAppendCheckItem(submenu, "Natural"); - uiMenuItemOnClicked(MenuItem_ScreenLayout[0], OnSetScreenLayout, (void*)&kScreenLayout[0]); - MenuItem_ScreenLayout[1] = uiMenuAppendCheckItem(submenu, "Vertical"); - uiMenuItemOnClicked(MenuItem_ScreenLayout[1], OnSetScreenLayout, (void*)&kScreenLayout[1]); - MenuItem_ScreenLayout[2] = uiMenuAppendCheckItem(submenu, "Horizontal"); - uiMenuItemOnClicked(MenuItem_ScreenLayout[2], OnSetScreenLayout, (void*)&kScreenLayout[2]); - - uiMenuAppendSubmenu(menu, submenu); - } - { - uiMenu* submenu = uiNewMenu("Screen sizing"); - - MenuItem_ScreenSizing[0] = uiMenuAppendCheckItem(submenu, "Even"); - uiMenuItemOnClicked(MenuItem_ScreenSizing[0], OnSetScreenSizing, (void*)&kScreenSizing[0]); - MenuItem_ScreenSizing[1] = uiMenuAppendCheckItem(submenu, "Emphasize top"); - uiMenuItemOnClicked(MenuItem_ScreenSizing[1], OnSetScreenSizing, (void*)&kScreenSizing[1]); - MenuItem_ScreenSizing[2] = uiMenuAppendCheckItem(submenu, "Emphasize bottom"); - uiMenuItemOnClicked(MenuItem_ScreenSizing[2], OnSetScreenSizing, (void*)&kScreenSizing[2]); - MenuItem_ScreenSizing[3] = uiMenuAppendCheckItem(submenu, "Auto"); - uiMenuItemOnClicked(MenuItem_ScreenSizing[3], OnSetScreenSizing, (void*)&kScreenSizing[3]); - - uiMenuAppendSubmenu(menu, submenu); - } - - MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering"); - uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL); - - MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD"); - uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL); - - uiMenuAppendSeparator(menu); - - MenuItem_LimitFPS = uiMenuAppendCheckItem(menu, "Limit framerate"); - uiMenuItemOnClicked(MenuItem_LimitFPS, OnSetLimitFPS, NULL); - - MenuItem_AudioSync = uiMenuAppendCheckItem(menu, "Audio sync"); - uiMenuItemOnClicked(MenuItem_AudioSync, OnSetAudioSync, NULL); -} - -void CreateMainWindow(bool opengl) -{ - MainWindow = uiNewWindow("melonDS " MELONDS_VERSION, - WindowWidth, WindowHeight, - Config::WindowMaximized, 1, 1); - uiWindowOnClosing(MainWindow, OnCloseWindow, NULL); - - uiWindowSetDropTarget(MainWindow, 1); - uiWindowOnDropFile(MainWindow, OnDropFile, NULL); - - uiWindowOnGetFocus(MainWindow, OnGetFocus, NULL); - uiWindowOnLoseFocus(MainWindow, OnLoseFocus, NULL); - - ScreenDrawInited = false; - bool opengl_good = opengl; - - if (!opengl) MainDrawArea = uiNewArea(&MainDrawAreaHandler); - else MainDrawArea = uiNewGLArea(&MainDrawAreaHandler, kGLVersions); - - uiWindowSetChild(MainWindow, uiControl(MainDrawArea)); - uiControlSetMinSize(uiControl(MainDrawArea), 256, 384); - uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0); - - uiControlShow(uiControl(MainWindow)); - uiControlSetFocus(uiControl(MainDrawArea)); - - if (opengl_good) - { - GLContext = uiAreaGetGLContext(MainDrawArea); - if (!GLContext) opengl_good = false; - } - if (opengl_good) - { - uiGLMakeContextCurrent(GLContext); - uiGLSetVSync(Config::ScreenVSync); - if (!GLScreen_Init()) opengl_good = false; - if (opengl_good) - { - OpenGL_UseShaderProgram(GL_ScreenShaderOSD); - OSD::Init(true); - } - uiGLMakeContextCurrent(NULL); - } - - if (opengl && !opengl_good) - { - printf("OpenGL: initialization failed\n"); - RecreateMainWindow(false); - Screen_UseGL = false; - } - - if (!opengl) OSD::Init(false); -} - -void DestroyMainWindow() -{ - uiControlDestroy(uiControl(MainWindow)); - - if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); - if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); - - ScreenBitmap[0] = NULL; - ScreenBitmap[1] = NULL; -} - -void RecreateMainWindow(bool opengl) -{ - int winX, winY, maxi; - uiWindowPosition(MainWindow, &winX, &winY); - maxi = uiWindowMaximized(MainWindow); - DestroyMainWindow(); - CreateMainWindow(opengl); - uiWindowSetPosition(MainWindow, winX, winY); - uiWindowSetMaximized(MainWindow, maxi); -} - - -int ___main(int argc, char** argv) -{ - srand(time(NULL)); - - printf("melonDS " MELONDS_VERSION "\n"); - printf(MELONDS_URL "\n"); - -#if defined(__WIN32__) || defined(UNIX_PORTABLE) - if (argc > 0 && strlen(argv[0]) > 0) - { - int len = strlen(argv[0]); - while (len > 0) - { - if (argv[0][len] == '/') break; - if (argv[0][len] == '\\') break; - len--; - } - if (len > 0) - { - EmuDirectory = new char[len+1]; - strncpy(EmuDirectory, argv[0], len); - EmuDirectory[len] = '\0'; - } - else - { - EmuDirectory = new char[2]; - strcpy(EmuDirectory, "."); - } - } - else - { - EmuDirectory = new char[2]; - strcpy(EmuDirectory, "."); - } -#else - const char* confdir = g_get_user_config_dir(); - const char* confname = "/melonDS"; - EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1]; - strcat(EmuDirectory, confdir); - strcat(EmuDirectory, confname); -#endif - - // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl - SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - - if (SDL_Init(SDL_INIT_HAPTIC) < 0) - { - printf("SDL couldn't init rumble\n"); - } - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) - { - printf("SDL shat itself :(\n"); - return 1; - } - - SDL_JoystickEventState(SDL_ENABLE); - - uiInitOptions ui_opt; - memset(&ui_opt, 0, sizeof(uiInitOptions)); - const char* ui_err = uiInit(&ui_opt); - if (ui_err != NULL) - { - printf("libui shat itself :( %s\n", ui_err); - uiFreeInitError(ui_err); - return 1; - } - - Config::Load(); - - if (Config::AudioVolume < 0) Config::AudioVolume = 0; - else if (Config::AudioVolume > 256) Config::AudioVolume = 256; - - if (!Platform::LocalFileExists("bios7.bin") || - !Platform::LocalFileExists("bios9.bin") || - !Platform::LocalFileExists("firmware.bin")) - { -#if defined(__WIN32__) || defined(UNIX_PORTABLE) - const char* locationName = "the directory you run melonDS from"; -#else - char* locationName = EmuDirectory; -#endif - char msgboxtext[512]; - sprintf(msgboxtext, - "One or more of the following required files don't exist or couldn't be accessed:\n\n" - "bios7.bin -- ARM7 BIOS\n" - "bios9.bin -- ARM9 BIOS\n" - "firmware.bin -- firmware image\n\n" - "Dump the files from your DS and place them in %s.\n" - "Make sure that the files can be accessed.", - locationName - ); - - uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext); - - uiUninit(); - SDL_Quit(); - return 0; - } - if (!Platform::LocalFileExists("firmware.bin.bak")) - { - // verify the firmware - // - // there are dumps of an old hacked firmware floating around on the internet - // and those are problematic - // the hack predates WFC, and, due to this, any game that alters the WFC - // access point data will brick that firmware due to it having critical - // data in the same area. it has the same problem on hardware. - // - // but this should help stop users from reporting that issue over and over - // again, when the issue is not from melonDS but from their firmware dump. - // - // I don't know about all the firmware hacks in existence, but the one I - // looked at has 0x180 bytes from the header repeated at 0x3FC80, but - // bytes 0x0C-0x14 are different. - - FILE* f = Platform::OpenLocalFile("firmware.bin", "rb"); - u8 chk1[0x180], chk2[0x180]; - - fseek(f, 0, SEEK_SET); - fread(chk1, 1, 0x180, f); - fseek(f, -0x380, SEEK_END); - fread(chk2, 1, 0x180, f); - - memset(&chk1[0x0C], 0, 8); - memset(&chk2[0x0C], 0, 8); - - fclose(f); - - if (!memcmp(chk1, chk2, 0x180)) - { - uiMsgBoxError(NULL, - "Problematic firmware dump", - "You are using an old hacked firmware dump.\n" - "Firmware boot will stop working if you run any game that alters WFC settings.\n\n" - "Note that the issue is not from melonDS, it would also happen on an actual DS."); - } - } - { - const char* romlist_missing = "Save memory type detection will not work correctly.\n\n" - "You should use the latest version of romlist.bin (provided in melonDS release packages)."; -#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) - std::string missingstr = std::string(romlist_missing) + - "\n\nThe ROM list should be placed in " + g_get_user_data_dir() + "/melonds/, otherwise " - "melonDS will search for it in the current working directory."; - const char* romlist_missing_text = missingstr.c_str(); -#else - const char* romlist_missing_text = romlist_missing; -#endif - - FILE* f = Platform::OpenDataFile("romlist.bin"); - if (f) - { - u32 data; - fread(&data, 4, 1, f); - fclose(f); - - if ((data >> 24) == 0) // old CRC-based list - { - uiMsgBoxError(NULL, "Your version of romlist.bin is outdated.", romlist_missing_text); - } - } - else - { - uiMsgBoxError(NULL, "romlist.bin not found.", romlist_missing_text); - } - } - - CreateMainWindowMenu(); - - MainDrawAreaHandler.Draw = OnAreaDraw; - MainDrawAreaHandler.MouseEvent = OnAreaMouseEvent; - MainDrawAreaHandler.MouseCrossed = OnAreaMouseCrossed; - MainDrawAreaHandler.DragBroken = OnAreaDragBroken; - MainDrawAreaHandler.KeyEvent = OnAreaKeyEvent; - MainDrawAreaHandler.Resize = OnAreaResize; - - WindowWidth = Config::WindowWidth; - WindowHeight = Config::WindowHeight; - - Screen_UseGL = Config::ScreenUseGL || (Config::_3DRenderer != 0); - - GL_3DScale = Config::GL_ScaleFactor; - if (GL_3DScale < 1) GL_3DScale = 1; - else if (GL_3DScale > 8) GL_3DScale = 8; - - CreateMainWindow(Screen_UseGL); - - ScreenRotation = Config::ScreenRotation; - ScreenGap = Config::ScreenGap; - ScreenLayout = Config::ScreenLayout; - ScreenSizing = Config::ScreenSizing; - -#define SANITIZE(var, min, max) if ((var < min) || (var > max)) var = 0; - SANITIZE(ScreenRotation, 0, 3); - SANITIZE(ScreenLayout, 0, 2); - SANITIZE(ScreenSizing, 0, 3); -#undef SANITIZE - - for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]); - for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]); - uiMenuItemDisable(MenuItem_UndoStateLoad); - - uiMenuItemDisable(MenuItem_Pause); - uiMenuItemDisable(MenuItem_Reset); - uiMenuItemDisable(MenuItem_Stop); - - uiMenuItemSetChecked(MenuItem_SavestateSRAMReloc, Config::SavestateRelocSRAM?1:0); - - uiMenuItemSetChecked(MenuItem_ScreenRot[ScreenRotation], 1); - uiMenuItemSetChecked(MenuItem_ScreenLayout[ScreenLayout], 1); - uiMenuItemSetChecked(MenuItem_ScreenSizing[ScreenSizing], 1); - - for (int i = 0; i < 6; i++) - { - if (ScreenGap == kScreenGap[i]) - uiMenuItemSetChecked(MenuItem_ScreenGap[i], 1); - } - - OnSetScreenRotation(MenuItem_ScreenRot[ScreenRotation], MainWindow, (void*)&kScreenRot[ScreenRotation]); - - uiMenuItemSetChecked(MenuItem_ScreenFilter, Config::ScreenFilter==1); - uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1); - uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1); - uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1); - -#ifdef MELONCAP - MelonCap::Init(); -#endif // MELONCAP - - AudioSync = SDL_CreateCond(); - AudioSyncLock = SDL_CreateMutex(); - - AudioFreq = 48000; // TODO: make configurable? - SDL_AudioSpec whatIwant, whatIget; - memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); - whatIwant.freq = AudioFreq; - whatIwant.format = AUDIO_S16LSB; - whatIwant.channels = 2; - whatIwant.samples = 1024; - whatIwant.callback = AudioCallback; - AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); - if (!AudioDevice) - { - printf("Audio init failed: %s\n", SDL_GetError()); - } - else - { - AudioFreq = whatIget.freq; - printf("Audio output frequency: %d Hz\n", AudioFreq); - SDL_PauseAudioDevice(AudioDevice, 1); - } - - memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); - whatIwant.freq = 44100; - whatIwant.format = AUDIO_S16LSB; - whatIwant.channels = 1; - whatIwant.samples = 1024; - whatIwant.callback = MicCallback; - MicDevice = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0); - if (!MicDevice) - { - printf("Mic init failed: %s\n", SDL_GetError()); - MicBufferLength = 0; - } - else - { - SDL_PauseAudioDevice(MicDevice, 1); - } - - memset(MicBuffer, 0, sizeof(MicBuffer)); - MicBufferReadPos = 0; - MicBufferWritePos = 0; - - MicWavBuffer = NULL; - if (Config::MicInputType == 3) MicLoadWav(Config::MicWavPath); - - JoystickID = Config::JoystickID; - Joystick = NULL; - OpenJoystick(); - - EmuRunning = 2; - RunningSomething = false; - EmuThread = SDL_CreateThread(EmuThreadFunc, "melonDS magic", NULL); - - if (argc > 1) - { - char* file = argv[1]; - char* ext = &file[strlen(file)-3]; - - if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl")) - { - strncpy(ROMPath[0], file, 1023); - ROMPath[0][1023] = '\0'; - - SetupSRAMPath(0); - - if (NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot)) - Run(); - } - - if (argc > 2) - { - file = argv[2]; - ext = &file[strlen(file)-3]; - - if (!strcasecmp(ext, "gba")) - { - strncpy(ROMPath[1], file, 1023); - ROMPath[1][1023] = '\0'; - - SetupSRAMPath(1); - - NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); - } - } - } - - uiMain(); - - if (Joystick) SDL_JoystickClose(Joystick); - if (AudioDevice) SDL_CloseAudioDevice(AudioDevice); - if (MicDevice) SDL_CloseAudioDevice(MicDevice); - - SDL_DestroyCond(AudioSync); - SDL_DestroyMutex(AudioSyncLock); - - if (MicWavBuffer) delete[] MicWavBuffer; - -#ifdef MELONCAP - MelonCap::DeInit(); -#endif // MELONCAP - - if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]); - if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]); - - Config::ScreenRotation = ScreenRotation; - Config::ScreenGap = ScreenGap; - Config::ScreenLayout = ScreenLayout; - Config::ScreenSizing = ScreenSizing; - - Config::Save(); - - uiUninit(); - SDL_Quit(); - delete[] EmuDirectory; - return 0; -} - - diff --git a/src/libui_sdl/main_shaders.h b/src/libui_sdl/main_shaders.h deleted file mode 100644 index 22d4dd9d..00000000 --- a/src/libui_sdl/main_shaders.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - Copyright 2016-2020 Arisotura - - This file is part of melonDS. - - melonDS is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - melonDS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with melonDS. If not, see http://www.gnu.org/licenses/. -*/ - -#ifndef MAIN_SHADERS_H -#define MAIN_SHADERS_H - -const char* kScreenVS = R"(#version 140 - -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; - -in vec2 vPosition; -in vec2 vTexcoord; - -smooth out vec2 fTexcoord; - -void main() -{ - vec4 fpos; - fpos.xy = ((vPosition * 2.0) / uScreenSize) - 1.0; - fpos.y *= -1; - fpos.z = 0.0; - fpos.w = 1.0; - - gl_Position = fpos; - fTexcoord = vTexcoord; -} -)"; - -const char* kScreenFS = R"(#version 140 - -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; - -uniform usampler2D ScreenTex; - -smooth in vec2 fTexcoord; - -out vec4 oColor; - -void main() -{ - ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); - - // TODO: filters - - oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0); -} -)"; - -const char* kScreenFS_Accel = R"(#version 140 - -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; - -uniform usampler2D ScreenTex; -uniform sampler2D _3DTex; - -smooth in vec2 fTexcoord; - -out vec4 oColor; - -void main() -{ - ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); - - ivec4 mbright = ivec4(texelFetch(ScreenTex, ivec2(256*3, int(fTexcoord.y)), 0)); - int dispmode = mbright.b & 0x3; - - if (dispmode == 1) - { - ivec4 val1 = pixel; - ivec4 val2 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(256,0), 0)); - ivec4 val3 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(512,0), 0)); - - int compmode = val3.a & 0xF; - int eva, evb, evy; - - if (compmode == 4) - { - // 3D on top, blending - - float xpos = val3.r + fract(fTexcoord.x); - float ypos = mod(fTexcoord.y, 192); - ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra - * vec4(63,63,63,31)); - - if (_3dpix.a > 0) - { - eva = (_3dpix.a & 0x1F) + 1; - evb = 32 - eva; - - val1 = ((_3dpix * eva) + (val1 * evb)) >> 5; - if (eva <= 16) val1 += ivec4(1,1,1,0); - val1 = min(val1, 0x3F); - } - else - val1 = val2; - } - else if (compmode == 1) - { - // 3D on bottom, blending - - float xpos = val3.r + fract(fTexcoord.x); - float ypos = mod(fTexcoord.y, 192); - ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra - * vec4(63,63,63,31)); - - if (_3dpix.a > 0) - { - eva = val3.g; - evb = val3.b; - - val1 = ((val1 * eva) + (_3dpix * evb)) >> 4; - val1 = min(val1, 0x3F); - } - else - val1 = val2; - } - else if (compmode <= 3) - { - // 3D on top, normal/fade - - float xpos = val3.r + fract(fTexcoord.x); - float ypos = mod(fTexcoord.y, 192); - ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra - * vec4(63,63,63,31)); - - if (_3dpix.a > 0) - { - evy = val3.g; - - val1 = _3dpix; - if (compmode == 2) val1 += ((ivec4(0x3F,0x3F,0x3F,0) - val1) * evy) >> 4; - else if (compmode == 3) val1 -= (val1 * evy) >> 4; - } - else - val1 = val2; - } - - pixel = val1; - } - - if (dispmode != 0) - { - int brightmode = mbright.g >> 6; - if (brightmode == 1) - { - // up - int evy = mbright.r & 0x1F; - if (evy > 16) evy = 16; - - pixel += ((ivec4(0x3F,0x3F,0x3F,0) - pixel) * evy) >> 4; - } - else if (brightmode == 2) - { - // down - int evy = mbright.r & 0x1F; - if (evy > 16) evy = 16; - - pixel -= (pixel * evy) >> 4; - } - } - - pixel.rgb <<= 2; - pixel.rgb |= (pixel.rgb >> 6); - - // TODO: filters - - oColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); -} -)"; - - -const char* kScreenVS_OSD = R"(#version 140 - -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; - -uniform ivec2 uOSDPos; -uniform ivec2 uOSDSize; - -in vec2 vPosition; - -smooth out vec2 fTexcoord; - -void main() -{ - vec4 fpos; - - vec2 osdpos = (vPosition * vec2(uOSDSize)); - fTexcoord = osdpos; - osdpos += uOSDPos; - - fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0; - fpos.y *= -1; - fpos.z = 0.0; - fpos.w = 1.0; - - gl_Position = fpos; -} -)"; - -const char* kScreenFS_OSD = R"(#version 140 - -uniform sampler2D OSDTex; - -smooth in vec2 fTexcoord; - -out vec4 oColor; - -void main() -{ - vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0); - oColor = pixel.bgra; -} -)"; - -#endif // MAIN_SHADERS_H From d58c9d4b53162c0e41fb084d7d8218f6672cc8ab Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 25 Apr 2020 18:56:39 +0200 Subject: [PATCH 008/105] blarg --- CMakeLists.txt | 6 --- src/frontend/qt_sdl/CMakeLists.txt | 73 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 src/frontend/qt_sdl/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 048dd44a..98c653a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,14 +32,8 @@ endif() add_compile_options(-fno-pic) add_link_options(-no-pie) -option(BUILD_LIBUI "Build libui frontend" ON) - add_subdirectory(src) -if (BUILD_LIBUI) - add_subdirectory(src/libui_sdl) -endif() - configure_file( ${CMAKE_SOURCE_DIR}/romlist.bin ${CMAKE_BINARY_DIR}/romlist.bin COPYONLY) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt new file mode 100644 index 00000000..e95d24b5 --- /dev/null +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -0,0 +1,73 @@ +project(qt_sdl) + +SET(SOURCES_LIBUI + main.cpp + Platform.cpp + PlatformConfig.cpp + LAN_Socket.cpp + LAN_PCap.cpp + DlgAudioSettings.cpp + DlgEmuSettings.cpp + DlgInputConfig.cpp + DlgVideoSettings.cpp + DlgWifiSettings.cpp + OSD.cpp +) + +if (WIN32) + set(CMAKE_RC_COMPILE_OBJECT " -i -o ") +endif() + +option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON) +set(BUILD_SHARED_LIBS OFF) +add_subdirectory(libui) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(SDL2 REQUIRED sdl2) + +add_executable(melonDS ${SOURCES_LIBUI}) +target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) +target_link_libraries(melonDS core libui ${SDL2_LIBRARIES}) + +if (UNIX) + option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) + if (UNIX_PORTABLE) + add_definitions(-DUNIX_PORTABLE) + endif() + + find_package(PkgConfig REQUIRED) + pkg_check_modules(GTK3 REQUIRED gtk+-3.0) + + target_include_directories(melonDS PRIVATE ${GTK3_INCLUDE_DIRS}) + target_link_libraries(melonDS ${GTK3_LIBRARIES}) + + ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) + + add_custom_command(OUTPUT melon_grc.c + COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} + --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c + --generate-source "${CMAKE_SOURCE_DIR}/melon_grc.xml" + COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} + --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h + --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") + + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + target_link_libraries(melonDS dl) + endif () + + target_sources(melonDS PUBLIC melon_grc.c) +elseif (WIN32) + target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") + target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) +endif () + +install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) +install(FILES ../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_32x32.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/32x32/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) +install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) From 0bdafb62951234eab93ea46ba82ea9e2a0fc1277 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 25 Apr 2020 19:31:19 +0200 Subject: [PATCH 009/105] finally get this going, I guess --- CMakeLists.txt | 6 ++++++ src/frontend/qt_sdl/CMakeLists.txt | 27 ++++++++------------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98c653a2..488da81d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,8 +32,14 @@ endif() add_compile_options(-fno-pic) add_link_options(-no-pie) +option(BUILD_QT_SDL "Build Qt/SDL frontend" ON) + add_subdirectory(src) +if (BUILD_QT_SDL) + add_subdirectory(src/frontend/qt_sdl) +endif() + configure_file( ${CMAKE_SOURCE_DIR}/romlist.bin ${CMAKE_BINARY_DIR}/romlist.bin COPYONLY) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index e95d24b5..ff2ed095 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -1,33 +1,22 @@ project(qt_sdl) -SET(SOURCES_LIBUI +SET(SOURCES_QT_SDL main.cpp - Platform.cpp - PlatformConfig.cpp - LAN_Socket.cpp - LAN_PCap.cpp - DlgAudioSettings.cpp - DlgEmuSettings.cpp - DlgInputConfig.cpp - DlgVideoSettings.cpp - DlgWifiSettings.cpp - OSD.cpp ) if (WIN32) set(CMAKE_RC_COMPILE_OBJECT " -i -o ") endif() -option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON) -set(BUILD_SHARED_LIBS OFF) -add_subdirectory(libui) +find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(Qt5 COMPONENTS Widgets REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) -add_executable(melonDS ${SOURCES_LIBUI}) +add_executable(melonDS ${SOURCES_QT_SDL}) target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) -target_link_libraries(melonDS core libui ${SDL2_LIBRARIES}) +target_link_libraries(melonDS core ${SDL2_LIBRARIES}) if (UNIX) option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) @@ -52,14 +41,14 @@ if (UNIX) --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(melonDS dl) + target_link_libraries(melonDS dl Qt5::Core Qt5::Widgets) endif () target_sources(melonDS PUBLIC melon_grc.c) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) + target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 Qt5::Core Qt5::Widgets) endif () install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) From 439ca1b2b557040f6d5a2fe1e70dd0f5e4d74484 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 25 Apr 2020 20:43:09 +0200 Subject: [PATCH 010/105] get a Qt window showing up. 'tis a start, I guess. --- src/frontend/qt_sdl/CMakeLists.txt | 7 +++++-- src/frontend/qt_sdl/main.cpp | 27 ++++++++++++++++++++------- src/frontend/qt_sdl/main.h | 14 +++++++++++++- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index ff2ed095..1ee76298 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -9,8 +9,11 @@ if (WIN32) endif() find_package(Qt5 COMPONENTS Core REQUIRED) +find_package(Qt5 COMPONENTS Gui REQUIRED) find_package(Qt5 COMPONENTS Widgets REQUIRED) +set(CMAKE_AUTOMOC ON) + find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) @@ -41,14 +44,14 @@ if (UNIX) --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(melonDS dl Qt5::Core Qt5::Widgets) + target_link_libraries(melonDS dl Qt5::Core Qt5::Gui Qt5::Widgets) endif () target_sources(melonDS PUBLIC melon_grc.c) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 Qt5::Core Qt5::Widgets) + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 Qt5::Core Qt5::Gui Qt5::Widgets) endif () install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 0b9d15e3..0eb84a5a 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -21,15 +21,26 @@ #include #include -// Qt includes and shit here, I guess -#include +#include +#include #include "main.h" #include "../../version.h" -// +MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) +{ + setWindowTitle("melonDS - assfucking Qt version"); + + // burp + QWidget *centralWidget = new QWidget(this); + setCentralWidget(centralWidget); +} + +MainWindow::~MainWindow() +{ +} int main(int argc, char** argv) @@ -39,10 +50,12 @@ int main(int argc, char** argv) printf("melonDS " MELONDS_VERSION "\n"); printf(MELONDS_URL "\n"); - printf("Arisotura hereby admits defeat\n"); - printf("NI DIEU NI MAITRE\n"); + QApplication melon(argc, argv); - return 0; + MainWindow win; + win.show(); + + return melon.exec(); } #ifdef __WIN32__ @@ -59,7 +72,7 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho for (int i = 0; i < argc; i++) { int len = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, NULL, 0, NULL, NULL); - if (len < 1) return NULL; + if (len < 1) { argv[i] = nullarg; continue; } argv[i] = new char[len]; int res = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, argv[i], len, NULL, NULL); if (res != len) { delete[] argv[i]; argv[i] = nullarg; } diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 65d6518c..ad795efb 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -19,6 +19,18 @@ #ifndef MAIN_H #define MAIN_H -// put the class shit here +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget* parent = nullptr); + ~MainWindow(); + +private: + // private shit goes here +}; #endif // MAIN_H From d3f14b7a8bcba9a71b7008a5b78abdfd4b70cb34 Mon Sep 17 00:00:00 2001 From: RSDuck Date: Mon, 27 Apr 2020 00:56:36 +0200 Subject: [PATCH 011/105] fix #584 --- src/libui_sdl/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 8e8bf9ec..9dea9f17 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -904,8 +904,6 @@ void UpdateFPSLimit(void* data) int EmuThreadFunc(void* burp) { - NDS::Init(); - MainScreenPos[0] = 0; MainScreenPos[1] = 0; MainScreenPos[2] = 0; @@ -2958,6 +2956,8 @@ int main(int argc, char** argv) Joystick = NULL; OpenJoystick(); + NDS::Init(); + EmuRunning = 2; RunningSomething = false; EmuThread = SDL_CreateThread(EmuThreadFunc, "melonDS magic", NULL); From 690f9f38744ddda7fd65c299288227767e4b03f0 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 12:06:44 +0200 Subject: [PATCH 012/105] get some of the shit going, I guess atleast the emuthread is going and we have its control system down and other fun shit, too --- src/CMakeLists.txt | 1 + src/frontend/qt_sdl/CMakeLists.txt | 2 + src/frontend/qt_sdl/Platform.cpp | 558 ++++++++++++++++++++++++ src/frontend/qt_sdl/PlatformConfig.cpp | 151 +++++++ src/frontend/qt_sdl/PlatformConfig.h | 82 ++++ src/frontend/qt_sdl/main.cpp | 570 ++++++++++++++++++++++++- src/frontend/qt_sdl/main.h | 42 +- 7 files changed, 1397 insertions(+), 9 deletions(-) create mode 100644 src/frontend/qt_sdl/Platform.cpp create mode 100644 src/frontend/qt_sdl/PlatformConfig.cpp create mode 100644 src/frontend/qt_sdl/PlatformConfig.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5537e6d0..64d922c2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(core STATIC NDS.cpp NDSCart.cpp OpenGLSupport.cpp + Platform.h RTC.cpp Savestate.cpp SPI.cpp diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 1ee76298..f24464d4 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -2,6 +2,8 @@ project(qt_sdl) SET(SOURCES_QT_SDL main.cpp + Platform.cpp + PlatformConfig.cpp ) if (WIN32) diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp new file mode 100644 index 00000000..31b5277d --- /dev/null +++ b/src/frontend/qt_sdl/Platform.cpp @@ -0,0 +1,558 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include +#include +#include "Platform.h" +#include "PlatformConfig.h" +//#include "LAN_Socket.h" +//#include "LAN_PCap.h" +#include + +#ifdef __WIN32__ + #define NTDDI_VERSION 0x06000000 // GROSS FUCKING HACK + #include + //#include // FUCK THAT SHIT + extern "C" const GUID DECLSPEC_SELECTANY FOLDERID_RoamingAppData = {0x3eb685db, 0x65f9, 0x4cf6, {0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d}}; + #include + #include + #include + #define socket_t SOCKET + #define sockaddr_t SOCKADDR +#else + #include + #include + #include + #include + #include + #include + #define socket_t int + #define sockaddr_t struct sockaddr + #define closesocket close +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (socket_t)-1 +#endif + + +extern char* EmuDirectory; + +void Stop(bool internal); + + +namespace Platform +{ + + +typedef struct +{ + SDL_Thread* ID; + void (*Func)(); + +} ThreadData; + +int ThreadEntry(void* data) +{ + ThreadData* thread = (ThreadData*)data; + thread->Func(); + return 0; +} + + +socket_t MPSocket; +sockaddr_t MPSendAddr; +u8 PacketBuffer[2048]; + +#define NIFI_VER 1 + + +void StopEmu() +{ + //Stop(true); +} + + +FILE* OpenFile(const char* path, const char* mode, bool mustexist) +{ + FILE* ret; + +#ifdef __WIN32__ + + int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); + if (len < 1) return NULL; + WCHAR* fatpath = new WCHAR[len]; + int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, fatpath, len); + if (res != len) { delete[] fatpath; return NULL; } // checkme? + + // this will be more than enough + WCHAR fatmode[4]; + fatmode[0] = mode[0]; + fatmode[1] = mode[1]; + fatmode[2] = mode[2]; + fatmode[3] = 0; + + if (mustexist) + { + ret = _wfopen(fatpath, L"rb"); + if (ret) ret = _wfreopen(fatpath, fatmode, ret); + } + else + ret = _wfopen(fatpath, fatmode); + + delete[] fatpath; + +#else + + if (mustexist) + { + ret = fopen(path, "rb"); + if (ret) ret = freopen(path, mode, ret); + } + else + ret = fopen(path, mode); + +#endif + + return ret; +} + +#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) + +FILE* OpenLocalFile(const char* path, const char* mode) +{ + std::string fullpath; + if (path[0] == '/') + { + // If it's an absolute path, just open that. + fullpath = std::string(path); + } + else + { + // Check user configuration directory + std::string confpath = std::string(g_get_user_config_dir()) + "/melonDS/"; + g_mkdir_with_parents(confpath.c_str(), 0755); + fullpath = confpath + path; + } + + return OpenFile(fullpath.c_str(), mode, mode[0] != 'w'); +} + +FILE* OpenDataFile(const char* path) +{ + const char* melondir = "melonDS"; + const char* const* sys_dirs = g_get_system_data_dirs(); + const char* user_dir = g_get_user_data_dir(); + + // First check the user's data directory + char* fullpath = g_build_path("/", user_dir, melondir, path, NULL); + if (access(fullpath, R_OK) == 0) + { + FILE* f = fopen(fullpath, "r"); + g_free(fullpath); + return f; + } + free(fullpath); + + // Then check the system data directories + for (size_t i = 0; sys_dirs[i] != NULL; i++) + { + const char* dir = sys_dirs[i]; + char* fullpath = g_build_path("/", dir, melondir, path, NULL); + + if (access(fullpath, R_OK) == 0) + { + FILE* f = fopen(fullpath, "r"); + g_free(fullpath); + return f; + } + free(fullpath); + } + + FILE* f = fopen(path, "rb"); + if (f) return f; + + return NULL; +} + +#else + +FILE* OpenLocalFile(const char* path, const char* mode) +{ + bool relpath = false; + int pathlen = strlen(path); + +#ifdef __WIN32__ + if (pathlen > 3) + { + if (path[1] == ':' && path[2] == '\\') + return OpenFile(path, mode); + } +#else + if (pathlen > 1) + { + if (path[0] == '/') + return OpenFile(path, mode); + } +#endif + + if (pathlen >= 3) + { + if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path[2] == '\\')) + relpath = true; + } + + int emudirlen = strlen(EmuDirectory); + char* emudirpath; + if (emudirlen) + { + int len = emudirlen + 1 + pathlen + 1; + emudirpath = new char[len]; + strncpy(&emudirpath[0], EmuDirectory, emudirlen); + emudirpath[emudirlen] = '/'; + strncpy(&emudirpath[emudirlen+1], path, pathlen); + emudirpath[emudirlen+1+pathlen] = '\0'; + } + else + { + emudirpath = new char[pathlen+1]; + strncpy(&emudirpath[0], path, pathlen); + emudirpath[pathlen] = '\0'; + } + + // Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonDS on Linux + + FILE* f; + + // First check current working directory + f = OpenFile(path, mode, true); + if (f) { delete[] emudirpath; return f; } + + // then emu directory + f = OpenFile(emudirpath, mode, true); + if (f) { delete[] emudirpath; return f; } + +#ifdef __WIN32__ + + // a path relative to AppData wouldn't make much sense + if (!relpath) + { + // Now check AppData + PWSTR appDataPath = NULL; + SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath); + if (!appDataPath) + { + delete[] emudirpath; + return NULL; + } + + // this will be more than enough + WCHAR fatperm[4]; + fatperm[0] = mode[0]; + fatperm[1] = mode[1]; + fatperm[2] = mode[2]; + fatperm[3] = 0; + + int fnlen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); + if (fnlen < 1) { delete[] emudirpath; return NULL; } + WCHAR* wfileName = new WCHAR[fnlen]; + int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, wfileName, fnlen); + if (res != fnlen) { delete[] wfileName; delete[] emudirpath; return NULL; } // checkme? + + const WCHAR* appdir = L"\\melonDS\\"; + + int pos = wcslen(appDataPath); + void* ptr = CoTaskMemRealloc(appDataPath, (pos+wcslen(appdir)+fnlen+1)*sizeof(WCHAR)); + if (!ptr) { delete[] wfileName; delete[] emudirpath; return NULL; } // oh well + appDataPath = (PWSTR)ptr; + + wcscpy(&appDataPath[pos], appdir); pos += wcslen(appdir); + wcscpy(&appDataPath[pos], wfileName); + + f = _wfopen(appDataPath, L"rb"); + if (f) f = _wfreopen(appDataPath, fatperm, f); + CoTaskMemFree(appDataPath); + delete[] wfileName; + if (f) { delete[] emudirpath; return f; } + } + +#else + + if (!relpath) + { + // Now check XDG_CONFIG_HOME + // TODO: check for memory leak there + std::string fullpath = std::string(g_get_user_config_dir()) + "/melonDS/" + path; + f = OpenFile(fullpath.c_str(), mode, true); + if (f) { delete[] emudirpath; return f; } + } + +#endif + + if (mode[0] != 'r') + { + f = OpenFile(emudirpath, mode); + if (f) { delete[] emudirpath; return f; } + } + + delete[] emudirpath; + return NULL; +} + +FILE* OpenDataFile(const char* path) +{ + return OpenLocalFile(path, "rb"); +} + +#endif + + +void* Thread_Create(void (*func)()) +{ + ThreadData* data = new ThreadData; + data->Func = func; + data->ID = SDL_CreateThread(ThreadEntry, "melonDS core thread", data); + return data; +} + +void Thread_Free(void* thread) +{ + delete (ThreadData*)thread; +} + +void Thread_Wait(void* thread) +{ + SDL_WaitThread((SDL_Thread*)((ThreadData*)thread)->ID, NULL); +} + + +void* Semaphore_Create() +{ + return SDL_CreateSemaphore(0); +} + +void Semaphore_Free(void* sema) +{ + SDL_DestroySemaphore((SDL_sem*)sema); +} + +void Semaphore_Reset(void* sema) +{ + while (SDL_SemTryWait((SDL_sem*)sema) == 0); +} + +void Semaphore_Wait(void* sema) +{ + SDL_SemWait((SDL_sem*)sema); +} + +void Semaphore_Post(void* sema) +{ + SDL_SemPost((SDL_sem*)sema); +} + + +void* GL_GetProcAddress(const char* proc) +{ + return NULL;//uiGLGetProcAddress(proc); +} + + +bool MP_Init() +{ + int opt_true = 1; + int res; + +#ifdef __WIN32__ + WSADATA wsadata; + if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) + { + return false; + } +#endif // __WIN32__ + + MPSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (MPSocket < 0) + { + return false; + } + + res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); + if (res < 0) + { + closesocket(MPSocket); + MPSocket = INVALID_SOCKET; + return false; + } + + sockaddr_t saddr; + saddr.sa_family = AF_INET; + *(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK); + *(u16*)&saddr.sa_data[0] = htons(7064); + res = bind(MPSocket, &saddr, sizeof(sockaddr_t)); + if (res < 0) + { + closesocket(MPSocket); + MPSocket = INVALID_SOCKET; + return false; + } + + res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); + if (res < 0) + { + closesocket(MPSocket); + MPSocket = INVALID_SOCKET; + return false; + } + + MPSendAddr.sa_family = AF_INET; + *(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST); + *(u16*)&MPSendAddr.sa_data[0] = htons(7064); + + return true; +} + +void MP_DeInit() +{ + if (MPSocket >= 0) + closesocket(MPSocket); + +#ifdef __WIN32__ + WSACleanup(); +#endif // __WIN32__ +} + +int MP_SendPacket(u8* data, int len) +{ + if (MPSocket < 0) + return 0; + + if (len > 2048-8) + { + printf("MP_SendPacket: error: packet too long (%d)\n", len); + return 0; + } + + *(u32*)&PacketBuffer[0] = htonl(0x4946494E); // NIFI + PacketBuffer[4] = NIFI_VER; + PacketBuffer[5] = 0; + *(u16*)&PacketBuffer[6] = htons(len); + memcpy(&PacketBuffer[8], data, len); + + int slen = sendto(MPSocket, (const char*)PacketBuffer, len+8, 0, &MPSendAddr, sizeof(sockaddr_t)); + if (slen < 8) return 0; + return slen - 8; +} + +int MP_RecvPacket(u8* data, bool block) +{ + if (MPSocket < 0) + return 0; + + fd_set fd; + struct timeval tv; + + FD_ZERO(&fd); + FD_SET(MPSocket, &fd); + tv.tv_sec = 0; + tv.tv_usec = block ? 5000 : 0; + + if (!select(MPSocket+1, &fd, 0, 0, &tv)) + { + return 0; + } + + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + int rlen = recvfrom(MPSocket, (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen); + if (rlen < 8+24) + { + return 0; + } + rlen -= 8; + + if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E) + { + return 0; + } + + if (PacketBuffer[4] != NIFI_VER) + { + return 0; + } + + if (ntohs(*(u16*)&PacketBuffer[6]) != rlen) + { + return 0; + } + + memcpy(data, &PacketBuffer[8], rlen); + return rlen; +} + + + +bool LAN_Init() +{ + /*if (Config::DirectLAN) + { + if (!LAN_PCap::Init(true)) + return false; + } + else + { + if (!LAN_Socket::Init()) + return false; + }*/ + + return true; +} + +void LAN_DeInit() +{ + // checkme. blarg + //if (Config::DirectLAN) + // LAN_PCap::DeInit(); + //else + // LAN_Socket::DeInit(); + /*LAN_PCap::DeInit(); + LAN_Socket::DeInit();*/ +} + +int LAN_SendPacket(u8* data, int len) +{ + /*if (Config::DirectLAN) + return LAN_PCap::SendPacket(data, len); + else + return LAN_Socket::SendPacket(data, len);*/ + return 0; +} + +int LAN_RecvPacket(u8* data) +{ + /*if (Config::DirectLAN) + return LAN_PCap::RecvPacket(data); + else + return LAN_Socket::RecvPacket(data);*/ + return 0; +} + + +} diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp new file mode 100644 index 00000000..f78b1957 --- /dev/null +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -0,0 +1,151 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include +#include "PlatformConfig.h" + +namespace Config +{ + +int KeyMapping[12]; +int JoyMapping[12]; + +int HKKeyMapping[HK_MAX]; +int HKJoyMapping[HK_MAX]; + +int JoystickID; + +int WindowWidth; +int WindowHeight; +int WindowMaximized; + +int ScreenRotation; +int ScreenGap; +int ScreenLayout; +int ScreenSizing; +int ScreenFilter; + +int ScreenUseGL; +int ScreenVSync; +int ScreenRatio; + +int LimitFPS; +int AudioSync; +int ShowOSD; + +int DirectBoot; + +int SocketBindAnyAddr; +char LANDevice[128]; +int DirectLAN; + +int SavestateRelocSRAM; + +int AudioVolume; +int MicInputType; +char MicWavPath[512]; + +char LastROMFolder[512]; + + +ConfigEntry PlatformConfigFile[] = +{ + {"Key_A", 0, &KeyMapping[0], 32, NULL, 0}, + {"Key_B", 0, &KeyMapping[1], 31, NULL, 0}, + {"Key_Select", 0, &KeyMapping[2], 57, NULL, 0}, + {"Key_Start", 0, &KeyMapping[3], 28, NULL, 0}, + {"Key_Right", 0, &KeyMapping[4], 333, NULL, 0}, + {"Key_Left", 0, &KeyMapping[5], 331, NULL, 0}, + {"Key_Up", 0, &KeyMapping[6], 328, NULL, 0}, + {"Key_Down", 0, &KeyMapping[7], 336, NULL, 0}, + {"Key_R", 0, &KeyMapping[8], 54, NULL, 0}, + {"Key_L", 0, &KeyMapping[9], 86, NULL, 0}, + {"Key_X", 0, &KeyMapping[10], 17, NULL, 0}, + {"Key_Y", 0, &KeyMapping[11], 30, NULL, 0}, + + {"Joy_A", 0, &JoyMapping[0], -1, NULL, 0}, + {"Joy_B", 0, &JoyMapping[1], -1, NULL, 0}, + {"Joy_Select", 0, &JoyMapping[2], -1, NULL, 0}, + {"Joy_Start", 0, &JoyMapping[3], -1, NULL, 0}, + {"Joy_Right", 0, &JoyMapping[4], -1, NULL, 0}, + {"Joy_Left", 0, &JoyMapping[5], -1, NULL, 0}, + {"Joy_Up", 0, &JoyMapping[6], -1, NULL, 0}, + {"Joy_Down", 0, &JoyMapping[7], -1, NULL, 0}, + {"Joy_R", 0, &JoyMapping[8], -1, NULL, 0}, + {"Joy_L", 0, &JoyMapping[9], -1, NULL, 0}, + {"Joy_X", 0, &JoyMapping[10], -1, NULL, 0}, + {"Joy_Y", 0, &JoyMapping[11], -1, NULL, 0}, + + {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0}, + {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0}, + {"HKKey_Pause", 0, &HKKeyMapping[HK_Pause], -1, NULL, 0}, + {"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0}, + {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0}, + {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], 0x4B, NULL, 0}, + {"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], 0x4D, NULL, 0}, + + {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0}, + {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0}, + {"HKJoy_Pause", 0, &HKJoyMapping[HK_Pause], -1, NULL, 0}, + {"HKJoy_Reset", 0, &HKJoyMapping[HK_Reset], -1, NULL, 0}, + {"HKJoy_FastForward", 0, &HKJoyMapping[HK_FastForward], -1, NULL, 0}, + {"HKJoy_FastForwardToggle", 0, &HKJoyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKJoy_SolarSensorDecrease", 0, &HKJoyMapping[HK_SolarSensorDecrease], -1, NULL, 0}, + {"HKJoy_SolarSensorIncrease", 0, &HKJoyMapping[HK_SolarSensorIncrease], -1, NULL, 0}, + + {"JoystickID", 0, &JoystickID, 0, NULL, 0}, + + {"WindowWidth", 0, &WindowWidth, 256, NULL, 0}, + {"WindowHeight", 0, &WindowHeight, 384, NULL, 0}, + {"WindowMax", 0, &WindowMaximized, 0, NULL, 0}, + + {"ScreenRotation", 0, &ScreenRotation, 0, NULL, 0}, + {"ScreenGap", 0, &ScreenGap, 0, NULL, 0}, + {"ScreenLayout", 0, &ScreenLayout, 0, NULL, 0}, + {"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0}, + {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0}, + + {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, + {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, + {"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0}, + + {"LimitFPS", 0, &LimitFPS, 0, NULL, 0}, + {"AudioSync", 0, &AudioSync, 1, NULL, 0}, + {"ShowOSD", 0, &ShowOSD, 1, NULL, 0}, + + {"DirectBoot", 0, &DirectBoot, 1, NULL, 0}, + + {"SockBindAnyAddr", 0, &SocketBindAnyAddr, 0, NULL, 0}, + {"LANDevice", 1, LANDevice, 0, "", 127}, + {"DirectLAN", 0, &DirectLAN, 0, NULL, 0}, + + {"SavStaRelocSRAM", 0, &SavestateRelocSRAM, 0, NULL, 0}, + + {"AudioVolume", 0, &AudioVolume, 256, NULL, 0}, + {"MicInputType", 0, &MicInputType, 1, NULL, 0}, + {"MicWavPath", 1, MicWavPath, 0, "", 511}, + + {"LastROMFolder", 1, LastROMFolder, 0, "", 511}, + + {"", -1, NULL, 0, NULL, 0} +}; + +} diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h new file mode 100644 index 00000000..d0f765b2 --- /dev/null +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -0,0 +1,82 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef PLATFORMCONFIG_H +#define PLATFORMCONFIG_H + +#include "Config.h" + +enum +{ + HK_Lid = 0, + HK_Mic, + HK_Pause, + HK_Reset, + HK_FastForward, + HK_FastForwardToggle, + HK_SolarSensorDecrease, + HK_SolarSensorIncrease, + HK_MAX +}; + +namespace Config +{ + +extern int KeyMapping[12]; +extern int JoyMapping[12]; + +extern int HKKeyMapping[HK_MAX]; +extern int HKJoyMapping[HK_MAX]; + +extern int JoystickID; + +extern int WindowWidth; +extern int WindowHeight; +extern int WindowMaximized; + +extern int ScreenRotation; +extern int ScreenGap; +extern int ScreenLayout; +extern int ScreenSizing; +extern int ScreenFilter; + +extern int ScreenUseGL; +extern int ScreenVSync; +extern int ScreenRatio; + +extern int LimitFPS; +extern int AudioSync; +extern int ShowOSD; + +extern int DirectBoot; + +extern int SocketBindAnyAddr; +extern char LANDevice[128]; +extern int DirectLAN; + +extern int SavestateRelocSRAM; + +extern int AudioVolume; +extern int MicInputType; +extern char MicWavPath[512]; + +extern char LastROMFolder[512]; + +} + +#endif // PLATFORMCONFIG_H diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 0eb84a5a..91926851 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -22,20 +22,364 @@ #include #include -#include +#include +#include +#include +#include +#include + +#include #include "main.h" -#include "../../version.h" +#include "types.h" +#include "version.h" + +#include "NDS.h" +#include "GBACart.h" +#include "GPU.h" +#include "SPU.h" +#include "Wifi.h" +#include "Platform.h" +#include "Config.h" + +#include "Savestate.h" + + +char* EmuDirectory; + +bool RunningSomething; +char ROMPath[2][1024]; +char SRAMPath[2][1024]; +char PrevSRAMPath[2][1024]; // for savestate 'undo load' + +bool SavestateLoaded; + +MainWindow* mainWindow; +EmuThread* emuThread; + + +EmuThread::EmuThread(QObject* parent) : QThread(parent) +{ + EmuStatus = 0; + EmuRunning = 2; +} + +void EmuThread::run() +{ + NDS::Init(); + + /*MainScreenPos[0] = 0; + MainScreenPos[1] = 0; + MainScreenPos[2] = 0; + AutoScreenSizing = 0;*/ + + /*if (Screen_UseGL) + { + uiGLMakeContextCurrent(GLContext); + GPU3D::InitRenderer(true); + uiGLMakeContextCurrent(NULL); + } + else*/ + { + GPU3D::InitRenderer(false); + } + + /*Touching = false; + KeyInputMask = 0xFFF; + JoyInputMask = 0xFFF; + KeyHotkeyMask = 0; + JoyHotkeyMask = 0; + HotkeyMask = 0; + LastHotkeyMask = 0; + LidStatus = false;*/ + + u32 nframes = 0; + u32 starttick = SDL_GetTicks(); + u32 lasttick = starttick; + u32 lastmeasuretick = lasttick; + u32 fpslimitcount = 0; + u64 perfcount = SDL_GetPerformanceCounter(); + u64 perffreq = SDL_GetPerformanceFrequency(); + float samplesleft = 0; + u32 nsamples = 0; + + char melontitle[100]; + SDL_mutex* titlemutex = SDL_CreateMutex(); + void* titledata[2] = {melontitle, titlemutex}; +printf("emu thread start: %d\n", EmuRunning); + while (EmuRunning != 0) + { + /*ProcessInput(); + + if (HotkeyPressed(HK_FastForwardToggle)) + { + Config::LimitFPS = !Config::LimitFPS; + uiQueueMain(UpdateFPSLimit, NULL); + } + // TODO: similar hotkeys for video/audio sync? + + if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); + if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); + + if (GBACart::CartInserted && GBACart::HasSolarSensor) + { + if (HotkeyPressed(HK_SolarSensorDecrease)) + { + if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); + } + if (HotkeyPressed(HK_SolarSensorIncrease)) + { + if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); + } + }*/ + + if (EmuRunning == 1) + { + EmuStatus = 1; + + // process input and hotkeys + NDS::SetKeyMask(0xFFF); + /*NDS::SetKeyMask(KeyInputMask & JoyInputMask); + + if (HotkeyPressed(HK_Lid)) + { + LidStatus = !LidStatus; + NDS::SetLidClosed(LidStatus); + OSD::AddMessage(0, LidStatus ? "Lid closed" : "Lid opened"); + }*/ + + // microphone input + /*FeedMicInput(); + + if (Screen_UseGL) + { + uiGLBegin(GLContext); + uiGLMakeContextCurrent(GLContext); + }*/ + + // auto screen layout + /*{ + MainScreenPos[2] = MainScreenPos[1]; + MainScreenPos[1] = MainScreenPos[0]; + MainScreenPos[0] = NDS::PowerControl9 >> 15; + + int guess; + if (MainScreenPos[0] == MainScreenPos[2] && + MainScreenPos[0] != MainScreenPos[1]) + { + // constant flickering, likely displaying 3D on both screens + // TODO: when both screens are used for 2D only...??? + guess = 0; + } + else + { + if (MainScreenPos[0] == 1) + guess = 1; + else + guess = 2; + } + + if (guess != AutoScreenSizing) + { + AutoScreenSizing = guess; + SetupScreenRects(WindowWidth, WindowHeight); + } + }*/ + + // emulate + u32 nlines = NDS::RunFrame(); + +#ifdef MELONCAP + MelonCap::Update(); +#endif // MELONCAP + + if (EmuRunning == 0) break; + + /*if (Screen_UseGL) + { + GLScreen_DrawScreen(); + uiGLEnd(GLContext); + } + uiAreaQueueRedrawAll(MainDrawArea);*/ + + /*bool fastforward = HotkeyDown(HK_FastForward); + + if (Config::AudioSync && !fastforward) + { + SDL_LockMutex(AudioSyncLock); + while (SPU::GetOutputSize() > 1024) + { + int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500); + if (ret == SDL_MUTEX_TIMEDOUT) break; + } + SDL_UnlockMutex(AudioSyncLock); + } + + float framerate = (1000.0f * nlines) / (60.0f * 263.0f); + + { + u32 curtick = SDL_GetTicks(); + u32 delay = curtick - lasttick; + + bool limitfps = Config::LimitFPS && !fastforward; + if (limitfps) + { + float wantedtickF = starttick + (framerate * (fpslimitcount+1)); + u32 wantedtick = (u32)ceil(wantedtickF); + if (curtick < wantedtick) SDL_Delay(wantedtick - curtick); + + lasttick = SDL_GetTicks(); + fpslimitcount++; + if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60)) + { + fpslimitcount = 0; + nsamples = 0; + starttick = lasttick; + } + } + else + { + if (delay < 1) SDL_Delay(1); + lasttick = SDL_GetTicks(); + } + } + + nframes++; + if (nframes >= 30) + { + u32 tick = SDL_GetTicks(); + u32 diff = tick - lastmeasuretick; + lastmeasuretick = tick; + + u32 fps; + if (diff < 1) fps = 77777; + else fps = (nframes * 1000) / diff; + nframes = 0; + + float fpstarget; + if (framerate < 1) fpstarget = 999; + else fpstarget = 1000.0f/framerate; + + SDL_LockMutex(titlemutex); + sprintf(melontitle, "[%d/%.0f] melonDS " MELONDS_VERSION, fps, fpstarget); + SDL_UnlockMutex(titlemutex); + uiQueueMain(UpdateWindowTitle, titledata); + }*/ + } + else + { + // paused + nframes = 0; + lasttick = SDL_GetTicks(); + starttick = lasttick; + lastmeasuretick = lasttick; + fpslimitcount = 0; + + if (EmuRunning == 2) + { + /*if (Screen_UseGL) + { + uiGLBegin(GLContext); + uiGLMakeContextCurrent(GLContext); + GLScreen_DrawScreen(); + uiGLEnd(GLContext); + } + uiAreaQueueRedrawAll(MainDrawArea);*/ + } + + //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + + EmuStatus = EmuRunning; + + SDL_Delay(100); + } + printf("ran iteration: status=%d run=%d\n", EmuStatus, EmuRunning); + } + + EmuStatus = 0; + + SDL_DestroyMutex(titlemutex); + + //if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); + + NDS::DeInit(); + //Platform::LAN_DeInit(); + + /*if (Screen_UseGL) + { + OSD::DeInit(true); + GLScreen_DeInit(); + } + else + OSD::DeInit(false);*/ + + //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); +} + +void EmuThread::emuRun() +{ + EmuRunning = 1; +} + +void EmuThread::emuPause(bool refresh) +{ + int status = refresh ? 2:3; + PrevEmuStatus = EmuRunning; + EmuRunning = status;printf("emuPause %d -> %d %d\n", PrevEmuStatus, EmuRunning, EmuStatus); + while (EmuStatus != status);printf("wait done\n"); +} + +void EmuThread::emuUnpause() +{ + EmuRunning = PrevEmuStatus; +} + +void EmuThread::emuStop() +{ + EmuRunning = 0; +} + + +MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) +{ +} + +MainWindowPanel::~MainWindowPanel() +{ +} + +void MainWindowPanel::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + + //painter. +} MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("melonDS - assfucking Qt version"); - // burp - QWidget *centralWidget = new QWidget(this); - setCentralWidget(centralWidget); + QMenuBar* menubar = new QMenuBar(); + { + QMenu* menu = menubar->addMenu("File"); + QAction* act; + + act = menu->addAction("Open file..."); + connect(act, &QAction::triggered, this, &MainWindow::onOpenFile); + } + setMenuBar(menubar); + + panel = new MainWindowPanel(this); + setCentralWidget(panel); + panel->setMinimumSize(256, 384); } MainWindow::~MainWindow() @@ -43,6 +387,13 @@ MainWindow::~MainWindow() } +void MainWindow::onOpenFile() +{ + QString filename = QFileDialog::getOpenFileName(this, "Open ROM", "", "DS ROMs (*.nds *.srl);;Any file (*.*)"); + printf("fark: %p %d %s\n", filename, filename.isEmpty(), filename.toStdString().c_str()); +} + + int main(int argc, char** argv) { srand(time(NULL)); @@ -50,12 +401,212 @@ int main(int argc, char** argv) printf("melonDS " MELONDS_VERSION "\n"); printf(MELONDS_URL "\n"); +#if defined(__WIN32__) || defined(UNIX_PORTABLE) + if (argc > 0 && strlen(argv[0]) > 0) + { + int len = strlen(argv[0]); + while (len > 0) + { + if (argv[0][len] == '/') break; + if (argv[0][len] == '\\') break; + len--; + } + if (len > 0) + { + EmuDirectory = new char[len+1]; + strncpy(EmuDirectory, argv[0], len); + EmuDirectory[len] = '\0'; + } + else + { + EmuDirectory = new char[2]; + strcpy(EmuDirectory, "."); + } + } + else + { + EmuDirectory = new char[2]; + strcpy(EmuDirectory, "."); + } +#else + const char* confdir = g_get_user_config_dir(); + const char* confname = "/melonDS"; + EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1]; + strcat(EmuDirectory, confdir); + strcat(EmuDirectory, confname); +#endif + QApplication melon(argc, argv); - MainWindow win; - win.show(); + // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - return melon.exec(); + if (SDL_Init(SDL_INIT_HAPTIC) < 0) + { + printf("SDL couldn't init rumble\n"); + } + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) + { + QMessageBox::critical(NULL, "melonDS", "SDL shat itself :("); + return 1; + } + + SDL_JoystickEventState(SDL_ENABLE); + + Config::Load(); + + //if (Config::AudioVolume < 0) Config::AudioVolume = 0; + //else if (Config::AudioVolume > 256) Config::AudioVolume = 256; + + // TODO: those should be checked before running anything + // (as to let the user specify their own BIOS/firmware path etc) +#if 0 + if (!Platform::LocalFileExists("bios7.bin") || + !Platform::LocalFileExists("bios9.bin") || + !Platform::LocalFileExists("firmware.bin")) + { +#if defined(__WIN32__) || defined(UNIX_PORTABLE) + const char* locationName = "the directory you run melonDS from"; +#else + char* locationName = EmuDirectory; +#endif + char msgboxtext[512]; + sprintf(msgboxtext, + "One or more of the following required files don't exist or couldn't be accessed:\n\n" + "bios7.bin -- ARM7 BIOS\n" + "bios9.bin -- ARM9 BIOS\n" + "firmware.bin -- firmware image\n\n" + "Dump the files from your DS and place them in %s.\n" + "Make sure that the files can be accessed.", + locationName + ); + + uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext); + + uiUninit(); + SDL_Quit(); + return 0; + } + if (!Platform::LocalFileExists("firmware.bin.bak")) + { + // verify the firmware + // + // there are dumps of an old hacked firmware floating around on the internet + // and those are problematic + // the hack predates WFC, and, due to this, any game that alters the WFC + // access point data will brick that firmware due to it having critical + // data in the same area. it has the same problem on hardware. + // + // but this should help stop users from reporting that issue over and over + // again, when the issue is not from melonDS but from their firmware dump. + // + // I don't know about all the firmware hacks in existence, but the one I + // looked at has 0x180 bytes from the header repeated at 0x3FC80, but + // bytes 0x0C-0x14 are different. + + FILE* f = Platform::OpenLocalFile("firmware.bin", "rb"); + u8 chk1[0x180], chk2[0x180]; + + fseek(f, 0, SEEK_SET); + fread(chk1, 1, 0x180, f); + fseek(f, -0x380, SEEK_END); + fread(chk2, 1, 0x180, f); + + memset(&chk1[0x0C], 0, 8); + memset(&chk2[0x0C], 0, 8); + + fclose(f); + + if (!memcmp(chk1, chk2, 0x180)) + { + uiMsgBoxError(NULL, + "Problematic firmware dump", + "You are using an old hacked firmware dump.\n" + "Firmware boot will stop working if you run any game that alters WFC settings.\n\n" + "Note that the issue is not from melonDS, it would also happen on an actual DS."); + } + } + { + const char* romlist_missing = "Save memory type detection will not work correctly.\n\n" + "You should use the latest version of romlist.bin (provided in melonDS release packages)."; +#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) + std::string missingstr = std::string(romlist_missing) + + "\n\nThe ROM list should be placed in " + g_get_user_data_dir() + "/melonds/, otherwise " + "melonDS will search for it in the current working directory."; + const char* romlist_missing_text = missingstr.c_str(); +#else + const char* romlist_missing_text = romlist_missing; +#endif + + FILE* f = Platform::OpenDataFile("romlist.bin"); + if (f) + { + u32 data; + fread(&data, 4, 1, f); + fclose(f); + + if ((data >> 24) == 0) // old CRC-based list + { + uiMsgBoxError(NULL, "Your version of romlist.bin is outdated.", romlist_missing_text); + } + } + else + { + uiMsgBoxError(NULL, "romlist.bin not found.", romlist_missing_text); + } + } +#endif + + mainWindow = new MainWindow(); + mainWindow->show(); + + emuThread = new EmuThread(); + emuThread->start(); + emuThread->emuPause(true); + + if (argc > 1) + { + char* file = argv[1]; + char* ext = &file[strlen(file)-3]; + + if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl")) + { + strncpy(ROMPath[0], file, 1023); + ROMPath[0][1023] = '\0'; + + //SetupSRAMPath(0); + + //if (NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot)) + // Run(); + } + + if (argc > 2) + { + file = argv[2]; + ext = &file[strlen(file)-3]; + + if (!strcasecmp(ext, "gba")) + { + strncpy(ROMPath[1], file, 1023); + ROMPath[1][1023] = '\0'; + + //SetupSRAMPath(1); + + //NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); + } + } + } + + int ret = melon.exec(); +printf("melon over\n"); + emuThread->emuStop();printf("STOP\n"); + emuThread->wait();printf("farked\n"); + + Config::Save(); + + SDL_Quit(); + delete[] EmuDirectory; + return ret; } #ifdef __WIN32__ @@ -71,6 +622,7 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho char** argv = new char*[argc]; for (int i = 0; i < argc; i++) { + if (!argv_w) { argv[i] = nullarg; continue; } int len = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, NULL, 0, NULL, NULL); if (len < 1) { argv[i] = nullarg; continue; } argv[i] = new char[len]; @@ -78,6 +630,8 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho if (res != len) { delete[] argv[i]; argv[i] = nullarg; } } + if (argv_w) LocalFree(argv_w); + if (AttachConsole(ATTACH_PARENT_PROCESS)) { freopen("CONOUT$", "w", stdout); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index ad795efb..92b18465 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -19,8 +19,45 @@ #ifndef MAIN_H #define MAIN_H +#include +#include #include + +class EmuThread : public QThread +{ + Q_OBJECT + void run() override; + +public: + explicit EmuThread(QObject* parent = nullptr); + + // to be called from the UI thread + void emuRun(); + void emuPause(bool refresh); + void emuUnpause(); + void emuStop(); + +private: + volatile int EmuStatus; + int PrevEmuStatus; + int EmuRunning; +}; + + +class MainWindowPanel : public QWidget +{ + Q_OBJECT + +public: + explicit MainWindowPanel(QWidget* parent); + ~MainWindowPanel(); + +protected: + void paintEvent(QPaintEvent* event) override; +}; + + class MainWindow : public QMainWindow { Q_OBJECT @@ -29,8 +66,11 @@ public: explicit MainWindow(QWidget* parent = nullptr); ~MainWindow(); +private slots: + void onOpenFile(); + private: - // private shit goes here + MainWindowPanel* panel; }; #endif // MAIN_H From d9c55a4f1f269de2fd17fe214403f13a9cf6f341 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 15:59:52 +0200 Subject: [PATCH 013/105] fix dumb include path shit. --- src/frontend/qt_sdl/CMakeLists.txt | 2 +- src/frontend/qt_sdl/main.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index f24464d4..baa4be26 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -21,6 +21,7 @@ pkg_check_modules(SDL2 REQUIRED sdl2) add_executable(melonDS ${SOURCES_QT_SDL}) target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) +target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") target_link_libraries(melonDS core ${SDL2_LIBRARIES}) if (UNIX) @@ -52,7 +53,6 @@ if (UNIX) target_sources(melonDS PUBLIC melon_grc.c) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 Qt5::Core Qt5::Gui Qt5::Widgets) endif () diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 91926851..4999d945 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -208,6 +208,7 @@ printf("emu thread start: %d\n", EmuRunning); uiGLEnd(GLContext); } uiAreaQueueRedrawAll(MainDrawArea);*/ + mainWindow->update(); /*bool fastforward = HotkeyDown(HK_FastForward); @@ -292,6 +293,7 @@ printf("emu thread start: %d\n", EmuRunning); uiGLEnd(GLContext); } uiAreaQueueRedrawAll(MainDrawArea);*/ + mainWindow->update(); } //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); @@ -359,7 +361,10 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) { QPainter painter(this); - //painter. + // fill background + painter.fillRect(event->rect(), QColor::fromRgb(0, 0, 0)); + + painter.fillRect(0, 0, 256, 192, QColor::fromRgb(0, 255, 255)); } From d6efb03248e3c7751b0c7e5d3b6398ea671325b0 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 20:59:11 +0200 Subject: [PATCH 014/105] HARK HARK HARK --- src/frontend/FrontendUtil.h | 31 ++++++++++++++++++++++++++++++ src/frontend/Util_ROM.cpp | 17 ++++++++++++++++ src/frontend/qt_sdl/CMakeLists.txt | 4 ++++ 3 files changed, 52 insertions(+) create mode 100644 src/frontend/FrontendUtil.h create mode 100644 src/frontend/Util_ROM.cpp diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h new file mode 100644 index 00000000..6a199b7b --- /dev/null +++ b/src/frontend/FrontendUtil.h @@ -0,0 +1,31 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef FRONTENDUTIL_H +#define FRONTENDUTIL_H + +#include "types.h" + +namespace FrontendUtil +{ + +// + +} + +#endif // FRONTENDUTIL_H diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp new file mode 100644 index 00000000..b3077f76 --- /dev/null +++ b/src/frontend/Util_ROM.cpp @@ -0,0 +1,17 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index baa4be26..fb9f5475 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -4,6 +4,9 @@ SET(SOURCES_QT_SDL main.cpp Platform.cpp PlatformConfig.cpp + + ../Util_ROM.cpp + ../FrontendUtil.h ) if (WIN32) @@ -21,6 +24,7 @@ pkg_check_modules(SDL2 REQUIRED sdl2) add_executable(melonDS ${SOURCES_QT_SDL}) target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) +target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") target_link_libraries(melonDS core ${SDL2_LIBRARIES}) From 931da1c66fb50138109f8bf4cb157db8f1e79c64 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 22:02:45 +0200 Subject: [PATCH 015/105] add a bunch of code --- src/CMakeLists.txt | 2 + src/Config.h | 2 + src/frontend/FrontendUtil.h | 38 +++++- src/frontend/Util_ROM.cpp | 236 +++++++++++++++++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 19 ++- 5 files changed, 284 insertions(+), 13 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 64d922c2..dca0ca9f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,8 @@ add_library(core STATIC Savestate.cpp SPI.cpp SPU.cpp + types.h + version.h Wifi.cpp WifiAP.cpp ) diff --git a/src/Config.h b/src/Config.h index 84fd57bc..0aeab852 100644 --- a/src/Config.h +++ b/src/Config.h @@ -19,6 +19,8 @@ #ifndef CONFIG_H #define CONFIG_H +#include + #include "types.h" namespace Config diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 6a199b7b..7e171ce7 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -21,10 +21,44 @@ #include "types.h" -namespace FrontendUtil +namespace Frontend { -// +enum +{ + ROMSlot_NDS = 0, + ROMSlot_GBA, + + ROMSlot_MAX +}; + +extern char ROMPath [ROMSlot_MAX][1024]; +extern char SRAMPath[ROMSlot_MAX][1024]; +extern bool SavestateLoaded; + + +// initialize the ROM handling utility +void Init_ROM(); + +// load a ROM file to the specified cart slot +// note: loading a ROM to the NDS slot resets emulation +bool LoadROM(char* file, int slot); + +// get the filename associated with the given savestate slot +void GetSavestateName(int slot, char* filename, int len); + +// determine whether the given savestate slot does contain a savestate +bool SavestateExists(int slot); + +// load the given savestate file +// if successful, emulation will continue from the savestate's point +bool LoadState(const char* filename); + +// save the current emulator state to the given file +bool SaveState(const char* filename); + +// undo the latest savestate load +void UndoStateLoad(); } diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index b3077f76..574148b1 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -15,3 +15,239 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include +#include + +#include "FrontendUtil.h" +#include "Config.h" +#include "qt_sdl/PlatformConfig.h" // FIXME!!! +#include "Platform.h" + +#include "NDS.h" +#include "GBACart.h" + + +namespace Frontend +{ + +char ROMPath [ROMSlot_MAX][1024]; +char SRAMPath [ROMSlot_MAX][1024]; +char PrevSRAMPath[ROMSlot_MAX][1024]; // for savestate 'undo load' + +bool SavestateLoaded; + + +void Init_ROM() +{ + SavestateLoaded = false; + + memset(ROMPath[ROMSlot_NDS], 0, 1024); + memset(ROMPath[ROMSlot_GBA], 0, 1024); + memset(SRAMPath[ROMSlot_NDS], 0, 1024); + memset(SRAMPath[ROMSlot_GBA], 0, 1024); + memset(PrevSRAMPath[ROMSlot_NDS], 0, 1024); + memset(PrevSRAMPath[ROMSlot_GBA], 0, 1024); +} + +void SetupSRAMPath(int slot) +{ + strncpy(SRAMPath[slot], ROMPath[slot], 1023); + SRAMPath[slot][1023] = '\0'; + strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); +} + +bool LoadROM(char* file, int slot) +{ + char oldpath[1024]; + char oldsram[1024]; + strncpy(oldpath, ROMPath[slot], 1024); + strncpy(oldsram, SRAMPath[slot], 1024); + + strncpy(ROMPath[slot], file, 1023); + ROMPath[slot][1023] = '\0'; + + SetupSRAMPath(0); + SetupSRAMPath(1); + + if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot)) + { + SavestateLoaded = false; + + // Reload the inserted GBA cartridge (if any) + if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]); + + strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety + return true; + } + else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) + { + SavestateLoaded = false; + + strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety + return true; + } + else + { + strncpy(ROMPath[slot], oldpath, 1024); + strncpy(SRAMPath[slot], oldsram, 1024); + return false; + } +} + + +// SAVESTATE TODO +// * configurable paths. not everyone wants their ROM directory to be polluted, I guess. + +void GetSavestateName(int slot, char* filename, int len) +{ + int pos; + + if (ROMPath[ROMSlot_NDS][0] == '\0') // running firmware, no ROM + { + strcpy(filename, "firmware"); + pos = 8; + } + else + { + int l = strlen(ROMPath[ROMSlot_NDS]); + pos = l; + while (ROMPath[ROMSlot_NDS][pos] != '.' && pos > 0) pos--; + if (pos == 0) pos = l; + + // avoid buffer overflow. shoddy + if (pos > len-5) pos = len-5; + + strncpy(&filename[0], ROMPath[ROMSlot_NDS], pos); + } + strcpy(&filename[pos], ".ml"); + filename[pos+3] = '0'+slot; + filename[pos+4] = '\0'; +} + +bool SavestateExists(int slot) +{ + char ssfile[1024]; + GetSavestateName(slot, ssfile, 1024); + return Platform::FileExists(ssfile); +} + +bool LoadState(const char* filename) +{ + u32 oldGBACartCRC = GBACart::CartCRC; + + // backup + Savestate* backup = new Savestate("timewarp.mln", true); + NDS::DoSavestate(backup); + delete backup; + + bool failed = false; + + Savestate* state = new Savestate(filename, false); + if (state->Error) + { + delete state; + + //uiMsgBoxError(MainWindow, "Error", "Could not load savestate file."); + + // current state might be crapoed, so restore from sane backup + state = new Savestate("timewarp.mln", false); + failed = true; + } + + NDS::DoSavestate(state); + delete state; + + if (!failed) + { + if (Config::SavestateRelocSRAM && ROMPath[ROMSlot_NDS][0]!='\0') + { + strncpy(PrevSRAMPath[ROMSlot_NDS], SRAMPath[0], 1024); + + strncpy(SRAMPath[ROMSlot_NDS], filename, 1019); + int len = strlen(SRAMPath[ROMSlot_NDS]); + strcpy(&SRAMPath[ROMSlot_NDS][len], ".sav"); + SRAMPath[ROMSlot_NDS][len+4] = '\0'; + + NDS::RelocateSave(SRAMPath[ROMSlot_NDS], false); + } + + bool loadedPartialGBAROM = false; + + // in case we have a GBA cart inserted, and the GBA ROM changes + // due to having loaded a save state, we do not want to reload + // the previous cartridge on reset, or commit writes to any + // loaded save file. therefore, their paths are "nulled". + if (GBACart::CartInserted && GBACart::CartCRC != oldGBACartCRC) + { + ROMPath[ROMSlot_GBA][0] = '\0'; + SRAMPath[ROMSlot_GBA][0] = '\0'; + loadedPartialGBAROM = true; + } + + // TODO forward this to user in a meaningful way!! + /*char msg[64]; + if (slot > 0) sprintf(msg, "State loaded from slot %d%s", + slot, loadedPartialGBAROM ? " (GBA ROM header only)" : ""); + else sprintf(msg, "State loaded from file%s", + loadedPartialGBAROM ? " (GBA ROM header only)" : ""); + OSD::AddMessage(0, msg);*/ + + SavestateLoaded = true; + } + + return !failed; +} + +bool SaveState(const char* filename) +{ + Savestate* state = new Savestate(filename, true); + if (state->Error) + { + delete state; + return false; + } + else + { + NDS::DoSavestate(state); + delete state; + + if (Config::SavestateRelocSRAM && ROMPath[ROMSlot_NDS][0]!='\0') + { + strncpy(SRAMPath[ROMSlot_NDS], filename, 1019); + int len = strlen(SRAMPath[ROMSlot_NDS]); + strcpy(&SRAMPath[ROMSlot_NDS][len], ".sav"); + SRAMPath[ROMSlot_NDS][len+4] = '\0'; + + NDS::RelocateSave(SRAMPath[ROMSlot_NDS], true); + } + } + + /*char msg[64]; + if (slot > 0) sprintf(msg, "State saved to slot %d", slot); + else sprintf(msg, "State saved to file"); + OSD::AddMessage(0, msg);*/ + return true; +} + +void UndoStateLoad() +{ + if (!SavestateLoaded) return; + + // pray that this works + // what do we do if it doesn't??? + // but it should work. + Savestate* backup = new Savestate("timewarp.mln", false); + NDS::DoSavestate(backup); + delete backup; + + if (ROMPath[ROMSlot_NDS][0]!='\0') + { + strncpy(SRAMPath[ROMSlot_NDS], PrevSRAMPath[ROMSlot_NDS], 1024); + NDS::RelocateSave(SRAMPath[ROMSlot_NDS], false); + } + + //OSD::AddMessage(0, "State load undone"); +} + +} diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 4999d945..648cd998 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -49,11 +49,6 @@ char* EmuDirectory; bool RunningSomething; -char ROMPath[2][1024]; -char SRAMPath[2][1024]; -char PrevSRAMPath[2][1024]; // for savestate 'undo load' - -bool SavestateLoaded; MainWindow* mainWindow; EmuThread* emuThread; @@ -334,8 +329,8 @@ void EmuThread::emuPause(bool refresh) { int status = refresh ? 2:3; PrevEmuStatus = EmuRunning; - EmuRunning = status;printf("emuPause %d -> %d %d\n", PrevEmuStatus, EmuRunning, EmuStatus); - while (EmuStatus != status);printf("wait done\n"); + EmuRunning = status; + while (EmuStatus != status); } void EmuThread::emuUnpause() @@ -370,7 +365,7 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { - setWindowTitle("melonDS - assfucking Qt version"); + setWindowTitle("melonDS " MELONDS_VERSION); QMenuBar* menubar = new QMenuBar(); { @@ -569,6 +564,7 @@ int main(int argc, char** argv) emuThread->start(); emuThread->emuPause(true); + #if 0 if (argc > 1) { char* file = argv[1]; @@ -601,11 +597,12 @@ int main(int argc, char** argv) } } } + #endif int ret = melon.exec(); -printf("melon over\n"); - emuThread->emuStop();printf("STOP\n"); - emuThread->wait();printf("farked\n"); + + emuThread->emuStop(); + emuThread->wait(); Config::Save(); From 3c883a2152c699b432c951b3498a1adc3d4c21b1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 22:32:33 +0200 Subject: [PATCH 016/105] hey look, it runs shit now! --- src/frontend/FrontendUtil.h | 2 +- src/frontend/Util_ROM.cpp | 2 +- src/frontend/qt_sdl/main.cpp | 60 +++++++++++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 7e171ce7..91f3cddd 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -42,7 +42,7 @@ void Init_ROM(); // load a ROM file to the specified cart slot // note: loading a ROM to the NDS slot resets emulation -bool LoadROM(char* file, int slot); +bool LoadROM(const char* file, int slot); // get the filename associated with the given savestate slot void GetSavestateName(int slot, char* filename, int len); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 574148b1..ffee69ac 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -57,7 +57,7 @@ void SetupSRAMPath(int slot) strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); } -bool LoadROM(char* file, int slot) +bool LoadROM(const char* file, int slot) { char oldpath[1024]; char oldsram[1024]; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 648cd998..6b4c8736 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -35,13 +35,15 @@ #include "types.h" #include "version.h" +#include "FrontendUtil.h" + #include "NDS.h" -#include "GBACart.h" #include "GPU.h" #include "SPU.h" #include "Wifi.h" #include "Platform.h" #include "Config.h" +#include "PlatformConfig.h" #include "Savestate.h" @@ -102,7 +104,7 @@ void EmuThread::run() char melontitle[100]; SDL_mutex* titlemutex = SDL_CreateMutex(); void* titledata[2] = {melontitle, titlemutex}; -printf("emu thread start: %d\n", EmuRunning); + while (EmuRunning != 0) { /*ProcessInput(); @@ -389,8 +391,56 @@ MainWindow::~MainWindow() void MainWindow::onOpenFile() { - QString filename = QFileDialog::getOpenFileName(this, "Open ROM", "", "DS ROMs (*.nds *.srl);;Any file (*.*)"); - printf("fark: %p %d %s\n", filename, filename.isEmpty(), filename.toStdString().c_str()); + emuThread->emuPause(true); + + QString filename = QFileDialog::getOpenFileName(this, + "Open ROM", + Config::LastROMFolder, + "DS ROMs (*.nds *.srl);;GBA ROMs (*.gba);;Any file (*.*)"); + if (filename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + // this shit is stupid + char file[1024]; + strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0'; + + int pos = strlen(file)-1; + while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--; + strncpy(Config::LastROMFolder, file, pos); + Config::LastROMFolder[pos] = '\0'; + char* ext = &file[strlen(file)-3]; + + int slot; bool res; + if (!strcasecmp(ext, "gba")) + { + slot = 1; + res = Frontend::LoadROM(file, Frontend::ROMSlot_GBA); + } + else + { + slot = 0; + res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); + } + + if (!res) + { + QMessageBox::critical(this, + "melonDS", + "Failed to load the ROM.\n\nMake sure the file is accessible and isn't used by another application."); + emuThread->emuUnpause(); + } + else if (slot == 1) + { + // checkme + emuThread->emuUnpause(); + } + else + { + emuThread->emuRun(); + } } @@ -557,6 +607,8 @@ int main(int argc, char** argv) } #endif + RunningSomething = false; + mainWindow = new MainWindow(); mainWindow->show(); From a8aa834c16d5044c25f6d313f88a470cb79ffbfa Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 22:42:07 +0200 Subject: [PATCH 017/105] now with display! --- src/frontend/qt_sdl/main.cpp | 20 ++++++++++++++++++-- src/frontend/qt_sdl/main.h | 4 ++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 6b4c8736..33dad2b0 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -299,7 +299,6 @@ void EmuThread::run() SDL_Delay(100); } - printf("ran iteration: status=%d run=%d\n", EmuStatus, EmuRunning); } EmuStatus = 0; @@ -325,6 +324,7 @@ void EmuThread::run() void EmuThread::emuRun() { EmuRunning = 1; + RunningSomething = true; } void EmuThread::emuPause(bool refresh) @@ -348,10 +348,14 @@ void EmuThread::emuStop() MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) { + screen[0] = new QImage(256, 192, QImage::Format_RGB32); + screen[1] = new QImage(256, 192, QImage::Format_RGB32); } MainWindowPanel::~MainWindowPanel() { + delete screen[0]; + delete screen[1]; } void MainWindowPanel::paintEvent(QPaintEvent* event) @@ -361,7 +365,19 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) // fill background painter.fillRect(event->rect(), QColor::fromRgb(0, 0, 0)); - painter.fillRect(0, 0, 256, 192, QColor::fromRgb(0, 255, 255)); + int frontbuf = GPU::FrontBuffer; + if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return; + + memcpy(screen[0]->scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4); + memcpy(screen[1]->scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4); + + QRect src = QRect(0, 0, 256, 192); + + QRect dstTop = QRect(0, 0, 256, 192); // TODO + QRect dstBot = QRect(0, 192, 256, 192); // TODO + + painter.drawImage(dstTop, *screen[0]); + painter.drawImage(dstBot, *screen[1]); } diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 92b18465..fb35fa54 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -22,6 +22,7 @@ #include #include #include +#include class EmuThread : public QThread @@ -55,6 +56,9 @@ public: protected: void paintEvent(QPaintEvent* event) override; + +private: + QImage* screen[2]; }; From 0913576ef598bee4d2ea3c4268a6a6f163cd90ef Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 27 Apr 2020 23:58:29 +0200 Subject: [PATCH 018/105] FPS counter is back --- src/frontend/qt_sdl/main.cpp | 32 +++++++++++++++++++++----------- src/frontend/qt_sdl/main.h | 7 +++++++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 33dad2b0..e9b91227 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -60,6 +60,9 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) { EmuStatus = 0; EmuRunning = 2; + RunningSomething = false; + + connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); } void EmuThread::run() @@ -102,8 +105,6 @@ void EmuThread::run() u32 nsamples = 0; char melontitle[100]; - SDL_mutex* titlemutex = SDL_CreateMutex(); - void* titledata[2] = {melontitle, titlemutex}; while (EmuRunning != 0) { @@ -207,6 +208,7 @@ void EmuThread::run() uiAreaQueueRedrawAll(MainDrawArea);*/ mainWindow->update(); + bool fastforward = false; /*bool fastforward = HotkeyDown(HK_FastForward); if (Config::AudioSync && !fastforward) @@ -218,7 +220,7 @@ void EmuThread::run() if (ret == SDL_MUTEX_TIMEDOUT) break; } SDL_UnlockMutex(AudioSyncLock); - } + }*/ float framerate = (1000.0f * nlines) / (60.0f * 263.0f); @@ -265,11 +267,9 @@ void EmuThread::run() if (framerate < 1) fpstarget = 999; else fpstarget = 1000.0f/framerate; - SDL_LockMutex(titlemutex); sprintf(melontitle, "[%d/%.0f] melonDS " MELONDS_VERSION, fps, fpstarget); - SDL_UnlockMutex(titlemutex); - uiQueueMain(UpdateWindowTitle, titledata); - }*/ + changeWindowTitle(melontitle); + } } else { @@ -297,14 +297,15 @@ void EmuThread::run() EmuStatus = EmuRunning; + sprintf(melontitle, "melonDS " MELONDS_VERSION); + changeWindowTitle(melontitle); + SDL_Delay(100); } } EmuStatus = 0; - SDL_DestroyMutex(titlemutex); - //if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); NDS::DeInit(); @@ -321,6 +322,11 @@ void EmuThread::run() //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); } +void EmuThread::changeWindowTitle(char* title) +{ + emit windowTitleChange(QString(title)); +} + void EmuThread::emuRun() { EmuRunning = 1; @@ -460,6 +466,12 @@ void MainWindow::onOpenFile() } +void MainWindow::onTitleUpdate(QString title) +{ + setWindowTitle(title); +} + + int main(int argc, char** argv) { srand(time(NULL)); @@ -623,8 +635,6 @@ int main(int argc, char** argv) } #endif - RunningSomething = false; - mainWindow = new MainWindow(); mainWindow->show(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index fb35fa54..a1093fef 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -33,12 +33,17 @@ class EmuThread : public QThread public: explicit EmuThread(QObject* parent = nullptr); + void changeWindowTitle(char* title); + // to be called from the UI thread void emuRun(); void emuPause(bool refresh); void emuUnpause(); void emuStop(); +signals: + void windowTitleChange(QString title); + private: volatile int EmuStatus; int PrevEmuStatus; @@ -73,6 +78,8 @@ public: private slots: void onOpenFile(); + void onTitleUpdate(QString title); + private: MainWindowPanel* panel; }; From 63efc2e02aa51c44c9cb5abc621624aa1d7bf1e5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 28 Apr 2020 22:45:11 +0200 Subject: [PATCH 019/105] add menu items for running the firmware and for quitting. --- src/frontend/FrontendUtil.h | 3 +++ src/frontend/Util_ROM.cpp | 16 +++++++++++++ src/frontend/qt_sdl/main.cpp | 44 +++++++++++++++++++++++++++++++++--- src/frontend/qt_sdl/main.h | 9 ++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 91f3cddd..eb4cb387 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -40,6 +40,9 @@ extern bool SavestateLoaded; // initialize the ROM handling utility void Init_ROM(); +// load the BIOS/firmware and boot from it +bool LoadBIOS(); + // load a ROM file to the specified cart slot // note: loading a ROM to the NDS slot resets emulation bool LoadROM(const char* file, int slot); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index ffee69ac..cf40a78f 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -57,6 +57,22 @@ void SetupSRAMPath(int slot) strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); } +bool LoadBIOS() +{ + // TODO: + // original code in the libui frontend called NDS::LoadGBAROM() if needed + // should this be carried over here? + // is that behavior consistent with that of LoadROM() below? + + ROMPath[ROMSlot_NDS][0] = '\0'; + SRAMPath[ROMSlot_NDS][0] = '\0'; + + NDS::LoadBIOS(); + + // TODO: error reporting? + return true; +} + bool LoadROM(const char* file, int slot) { char oldpath[1024]; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index e9b91227..cadcec96 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -394,10 +394,17 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) QMenuBar* menubar = new QMenuBar(); { QMenu* menu = menubar->addMenu("File"); - QAction* act; - act = menu->addAction("Open file..."); - connect(act, &QAction::triggered, this, &MainWindow::onOpenFile); + actOpenROM = menu->addAction("Open file..."); + connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile); + + actBootFirmware = menu->addAction("Launch DS menu"); + connect(actBootFirmware, &QAction::triggered, this, &MainWindow::onBootFirmware); + + menu->addSeparator(); + + actQuit = menu->addAction("Quit"); + connect(actQuit, &QAction::triggered, this, &MainWindow::onQuit); } setMenuBar(menubar); @@ -411,6 +418,12 @@ MainWindow::~MainWindow() } +void MainWindow::keyPressEvent(QKeyEvent* event) +{ + printf("key press. %d %d %08X %08X\n", event->key(), event->nativeScanCode(), event->modifiers(), event->nativeModifiers()); +} + + void MainWindow::onOpenFile() { emuThread->emuPause(true); @@ -465,6 +478,31 @@ void MainWindow::onOpenFile() } } +void MainWindow::onBootFirmware() +{ + // TODO: ensure the firmware is actually bootable!! + // TODO: check the whole GBA cart shito + + emuThread->emuPause(true); + + bool res = Frontend::LoadBIOS(); + if (!res) + { + // TODO! + + emuThread->emuUnpause(); + } + else + { + emuThread->emuRun(); + } +} + +void MainWindow::onQuit() +{ + QApplication::quit(); +} + void MainWindow::onTitleUpdate(QString title) { diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index a1093fef..9ccbddda 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -75,13 +75,22 @@ public: explicit MainWindow(QWidget* parent = nullptr); ~MainWindow(); +protected: + void keyPressEvent(QKeyEvent* event) override; + private slots: void onOpenFile(); + void onBootFirmware(); + void onQuit(); void onTitleUpdate(QString title); private: MainWindowPanel* panel; + + QAction* actOpenROM; + QAction* actBootFirmware; + QAction* actQuit; }; #endif // MAIN_H From 47ff012f5ed743d30d994a10de48e07b650f706b Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 28 Apr 2020 22:46:31 +0200 Subject: [PATCH 020/105] blarg --- src/frontend/qt_sdl/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index cadcec96..af4fd4b1 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -398,7 +398,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actOpenROM = menu->addAction("Open file..."); connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile); - actBootFirmware = menu->addAction("Launch DS menu"); + //actBootFirmware = menu->addAction("Launch DS menu"); + actBootFirmware = menu->addAction("Boot firmware"); connect(actBootFirmware, &QAction::triggered, this, &MainWindow::onBootFirmware); menu->addSeparator(); From 5fbad464c27fd5290c837d78a72378215ee8e77f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 29 Apr 2020 00:50:23 +0200 Subject: [PATCH 021/105] hook up savestate shito --- src/frontend/FrontendUtil.h | 2 +- src/frontend/Util_ROM.cpp | 2 + src/frontend/qt_sdl/main.cpp | 141 ++++++++++++++++++++++++++++++++++- src/frontend/qt_sdl/main.h | 6 ++ 4 files changed, 149 insertions(+), 2 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index eb4cb387..d9f5c582 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -47,7 +47,7 @@ bool LoadBIOS(); // note: loading a ROM to the NDS slot resets emulation bool LoadROM(const char* file, int slot); -// get the filename associated with the given savestate slot +// get the filename associated with the given savestate slot (1-8) void GetSavestateName(int slot, char* filename, int len); // determine whether the given savestate slot does contain a savestate diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index cf40a78f..19c8eb91 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -69,6 +69,8 @@ bool LoadBIOS() NDS::LoadBIOS(); + SavestateLoaded = false; + // TODO: error reporting? return true; } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index af4fd4b1..a6a14233 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -395,7 +395,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { QMenu* menu = menubar->addMenu("File"); - actOpenROM = menu->addAction("Open file..."); + actOpenROM = menu->addAction("Open ROM..."); connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile); //actBootFirmware = menu->addAction("Launch DS menu"); @@ -404,6 +404,49 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) menu->addSeparator(); + { + QMenu* submenu = menu->addMenu("Save state"); + + for (int i = 1; i < 9; i++) + { + char title[16]; + sprintf(title, "%d", i); + actSaveState[i] = submenu->addAction(title); + actSaveState[i]->setShortcut(QKeySequence(Qt::ShiftModifier | (Qt::Key_F1+i-1))); + actSaveState[i]->setData(QVariant(i)); + connect(actSaveState[i], &QAction::triggered, this, &MainWindow::onSaveState); + } + + actSaveState[0] = submenu->addAction("File..."); + actSaveState[0]->setShortcut(QKeySequence(Qt::ShiftModifier | Qt::Key_F9)); + actSaveState[0]->setData(QVariant(0)); + connect(actSaveState[0], &QAction::triggered, this, &MainWindow::onSaveState); + } + { + QMenu* submenu = menu->addMenu("Load state"); + + for (int i = 1; i < 9; i++) + { + char title[16]; + sprintf(title, "%d", i); + actLoadState[i] = submenu->addAction(title); + actLoadState[i]->setShortcut(QKeySequence(Qt::Key_F1+i-1)); + actLoadState[i]->setData(QVariant(i)); + connect(actLoadState[i], &QAction::triggered, this, &MainWindow::onLoadState); + } + + actLoadState[0] = submenu->addAction("File..."); + actLoadState[0]->setShortcut(QKeySequence(Qt::Key_F9)); + actLoadState[0]->setData(QVariant(0)); + connect(actLoadState[0], &QAction::triggered, this, &MainWindow::onLoadState); + } + + actUndoStateLoad = menu->addAction("Undo state load"); + actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12)); + connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad); + + menu->addSeparator(); + actQuit = menu->addAction("Quit"); connect(actQuit, &QAction::triggered, this, &MainWindow::onQuit); } @@ -499,6 +542,102 @@ void MainWindow::onBootFirmware() } } +void MainWindow::onSaveState() +{ + int slot = ((QAction*)sender())->data().toInt(); + + emuThread->emuPause(true); + + char filename[1024]; + if (slot > 0) + { + Frontend::GetSavestateName(slot, filename, 1024); + } + else + { + // TODO: specific 'last directory' for savestate files? + QString qfilename = QFileDialog::getSaveFileName(this, + "Save state", + Config::LastROMFolder, + "melonDS savestates (*.mln);;Any file (*.*)"); + if (qfilename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + strncpy(filename, qfilename.toStdString().c_str(), 1023); filename[1023] = '\0'; + } + + if (Frontend::SaveState(filename)) + { + // TODO: OSD message + } + else + { + // TODO: OSD error message? + } + + emuThread->emuUnpause(); +} + +void MainWindow::onLoadState() +{ + int slot = ((QAction*)sender())->data().toInt(); + + emuThread->emuPause(true); + + char filename[1024]; + if (slot > 0) + { + Frontend::GetSavestateName(slot, filename, 1024); + } + else + { + // TODO: specific 'last directory' for savestate files? + QString qfilename = QFileDialog::getOpenFileName(this, + "Load state", + Config::LastROMFolder, + "melonDS savestates (*.ml*);;Any file (*.*)"); + if (qfilename.isEmpty()) + { + emuThread->emuUnpause(); + return; + } + + strncpy(filename, qfilename.toStdString().c_str(), 1023); filename[1023] = '\0'; + } + + if (!Platform::FileExists(filename)) + { + /*char msg[64]; + if (slot > 0) sprintf(msg, "State slot %d is empty", slot); + else sprintf(msg, "State file does not exist"); + OSD::AddMessage(0xFFA0A0, msg);*/ + + emuThread->emuUnpause(); + return; + } + + if (Frontend::LoadState(filename)) + { + // TODO: OSD message + } + else + { + // TODO: OSD error message? + } + + emuThread->emuUnpause(); +} + +void MainWindow::onUndoStateLoad() +{ + emuThread->emuPause(true); + Frontend::UndoStateLoad(); + emuThread->emuUnpause(); +} + void MainWindow::onQuit() { QApplication::quit(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 9ccbddda..86948388 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -81,6 +81,9 @@ protected: private slots: void onOpenFile(); void onBootFirmware(); + void onSaveState(); + void onLoadState(); + void onUndoStateLoad(); void onQuit(); void onTitleUpdate(QString title); @@ -90,6 +93,9 @@ private: QAction* actOpenROM; QAction* actBootFirmware; + QAction* actSaveState[9]; + QAction* actLoadState[9]; + QAction* actUndoStateLoad; QAction* actQuit; }; From 7f3e67c12a6b7687467c4b56d79e4770cc32ae43 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 30 Apr 2020 01:02:17 +0200 Subject: [PATCH 022/105] some more UI work --- src/frontend/qt_sdl/main.cpp | 93 ++++++++++++++++++++++++++++++++++++ src/frontend/qt_sdl/main.h | 19 ++++++++ 2 files changed, 112 insertions(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index a6a14233..5cc48262 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -63,6 +63,10 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) RunningSomething = false; connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); + connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); + connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); + + emit windowEmuStop(); } void EmuThread::run() @@ -331,6 +335,9 @@ void EmuThread::emuRun() { EmuRunning = 1; RunningSomething = true; + + // checkme + emit windowEmuStart(); } void EmuThread::emuPause(bool refresh) @@ -339,11 +346,15 @@ void EmuThread::emuPause(bool refresh) PrevEmuStatus = EmuRunning; EmuRunning = status; while (EmuStatus != status); + + //emit windowEmuPause(); } void EmuThread::emuUnpause() { EmuRunning = PrevEmuStatus; + + //emit windowEmuUnpause(); } void EmuThread::emuStop() @@ -351,6 +362,11 @@ void EmuThread::emuStop() EmuRunning = 0; } +bool EmuThread::emuIsRunning() +{ + return (EmuRunning == 1); +} + MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) { @@ -450,6 +466,19 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actQuit = menu->addAction("Quit"); connect(actQuit, &QAction::triggered, this, &MainWindow::onQuit); } + { + QMenu* menu = menubar->addMenu("System"); + + actPause = menu->addAction("Pause"); + actPause->setCheckable(true); + connect(actPause, &QAction::triggered, this, &MainWindow::onPause); + + actReset = menu->addAction("Reset"); + connect(actReset, &QAction::triggered, this, &MainWindow::onReset); + + actStop = menu->addAction("Stop"); + connect(actStop, &QAction::triggered, this, &MainWindow::onStop); + } setMenuBar(menubar); panel = new MainWindowPanel(this); @@ -644,11 +673,75 @@ void MainWindow::onQuit() } +void MainWindow::onPause(bool checked) +{ + if (emuThread->emuIsRunning()) + { + emuThread->emuPause(true); + } + else + { + emuThread->emuUnpause(); + } +} + +void MainWindow::onReset() +{ + // +} + +void MainWindow::onStop() +{ + // +} + + void MainWindow::onTitleUpdate(QString title) { setWindowTitle(title); } +void MainWindow::onEmuStart() +{ + for (int i = 1; i < 9; i++) + { + actSaveState[i]->setEnabled(true); + actLoadState[i]->setEnabled(Frontend::SavestateExists(i)); + } + actSaveState[0]->setEnabled(true); + actLoadState[0]->setEnabled(true); + actUndoStateLoad->setEnabled(true); + + actPause->setEnabled(true); + actPause->setChecked(false); + actReset->setEnabled(true); + actStop->setEnabled(true); +} + +void MainWindow::onEmuStop() +{ + for (int i = 0; i < 9; i++) + { + actSaveState[i]->setEnabled(false); + actLoadState[i]->setEnabled(false); + } + actUndoStateLoad->setEnabled(false); + + actPause->setEnabled(false); + actReset->setEnabled(false); + actStop->setEnabled(false); +} + +void MainWindow::onEmuPause() +{ + // +} + +void MainWindow::onEmuUnpause() +{ + // +} + int main(int argc, char** argv) { diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 86948388..30cef1f5 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -41,9 +41,15 @@ public: void emuUnpause(); void emuStop(); + bool emuIsRunning(); + signals: void windowTitleChange(QString title); + void windowEmuStart(); + void windowEmuStop(); + void windowPauseToggle(); + private: volatile int EmuStatus; int PrevEmuStatus; @@ -86,8 +92,17 @@ private slots: void onUndoStateLoad(); void onQuit(); + void onPause(bool checked); + void onReset(); + void onStop(); + void onTitleUpdate(QString title); + void onEmuStart(); + void onEmuStop(); + void onEmuPause(); + void onEmuUnpause(); + private: MainWindowPanel* panel; @@ -97,6 +112,10 @@ private: QAction* actLoadState[9]; QAction* actUndoStateLoad; QAction* actQuit; + + QAction* actPause; + QAction* actReset; + QAction* actStop; }; #endif // MAIN_H From 690f39ca3382f1e82a27c8a16dde1a4379f978f8 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 2 May 2020 19:41:03 +0200 Subject: [PATCH 023/105] enable savestate slots when saving a new savestate --- src/frontend/qt_sdl/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 5cc48262..bdf68bde 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -601,6 +601,8 @@ void MainWindow::onSaveState() if (Frontend::SaveState(filename)) { // TODO: OSD message + + actLoadState[slot]->setEnabled(true); } else { From aa4344e249d855bfc2ddd52af61d3213d9e99db3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 2 May 2020 20:25:39 +0200 Subject: [PATCH 024/105] add audio output. HARK HARK HARK --- src/CMakeLists.txt | 3 + src/frontend/FrontendUtil.h | 13 ++++ src/frontend/Util_Audio.cpp | 77 ++++++++++++++++++++++++ src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/main.cpp | 96 ++++++++++++++++++++++++++++-- 5 files changed, 184 insertions(+), 6 deletions(-) create mode 100644 src/frontend/Util_Audio.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dca0ca9f..245e6a2a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ add_library(core STATIC ARCodeList.cpp AREngine.cpp ARM.cpp + ARM_InstrTable.h ARMInterpreter.cpp ARMInterpreter_ALU.cpp ARMInterpreter_Branch.cpp @@ -12,11 +13,13 @@ add_library(core STATIC CP15.cpp CRC32.cpp DMA.cpp + FIFO.h GBACart.cpp GPU.cpp GPU2D.cpp GPU3D.cpp GPU3D_OpenGL.cpp + GPU3D_OpenGL_shaders.h GPU3D_Soft.cpp NDS.cpp NDSCart.cpp diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index d9f5c582..32f28d14 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -63,6 +63,19 @@ bool SaveState(const char* filename); // undo the latest savestate load void UndoStateLoad(); + +// initialize the audio utility +void Init_Audio(int outputfreq); + +// get how many samples to read from the core audio output +// based on how many are needed by the frontend (outlen in samples) +int AudioOut_GetNumSamples(int outlen); + +// resample audio from the core audio output to match the frontend's +// output frequency, and apply user-specified volume +// note: this assumes the output buffer is interleaved stereo +void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen); + } #endif // FRONTENDUTIL_H diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp new file mode 100644 index 00000000..fe0ecab6 --- /dev/null +++ b/src/frontend/Util_Audio.cpp @@ -0,0 +1,77 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include + +#include "FrontendUtil.h" +#include "Config.h" +#include "qt_sdl/PlatformConfig.h" // FIXME!!! +#include "Platform.h" + +#include "NDS.h" +#include "GBACart.h" + + +namespace Frontend +{ + +int AudioOut_Freq; +float AudioOut_SampleFrac; + + +void Init_Audio(int outputfreq) +{ + AudioOut_Freq = outputfreq; + AudioOut_SampleFrac = 0; +} + +int AudioOut_GetNumSamples(int outlen) +{ + float f_len_in = (outlen * 32823.6328125) / (float)AudioOut_Freq; + f_len_in += AudioOut_SampleFrac; + int len_in = (int)floor(f_len_in); + AudioOut_SampleFrac = f_len_in - len_in; + + return len_in; +} + +void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen) +{ + float res_incr = inlen / (float)outlen; + float res_timer = 0; + int res_pos = 0; + + int volume = Config::AudioVolume; + + for (int i = 0; i < outlen; i++) + { + outbuf[i*2 ] = (inbuf[res_pos*2 ] * volume) >> 8; + outbuf[i*2+1] = (inbuf[res_pos*2+1] * volume) >> 8; + + res_timer += res_incr; + while (res_timer >= 1.0) + { + res_timer -= 1.0; + res_pos++; + } + } +} + +} diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index fb9f5475..05a40292 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -6,6 +6,7 @@ SET(SOURCES_QT_SDL PlatformConfig.cpp ../Util_ROM.cpp + ../Util_Audio.cpp ../FrontendUtil.h ) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index bdf68bde..80c25b5c 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -48,6 +48,8 @@ #include "Savestate.h" +// TODO: uniform variable spelling + char* EmuDirectory; bool RunningSomething; @@ -55,6 +57,48 @@ bool RunningSomething; MainWindow* mainWindow; EmuThread* emuThread; +SDL_AudioDeviceID audioDevice; +int audioFreq; +SDL_cond* audioSync; +SDL_mutex* audioSyncLock; + + +void audioCallback(void* data, Uint8* stream, int len) +{ + len /= (sizeof(s16) * 2); + + // resample incoming audio to match the output sample rate + + int len_in = Frontend::AudioOut_GetNumSamples(len); + s16 buf_in[1024*2]; + int num_in; + + SDL_LockMutex(audioSyncLock); + num_in = SPU::ReadOutput(buf_in, len_in); + SDL_CondSignal(audioSync); + SDL_UnlockMutex(audioSyncLock); + + if (num_in < 1) + { + memset(stream, 0, len*sizeof(s16)*2); + return; + } + + int margin = 6; + if (num_in < len_in-margin) + { + int last = num_in-1; + if (last < 0) last = 0; + + for (int i = num_in; i < len_in-margin; i++) + ((u32*)buf_in)[i] = ((u32*)buf_in)[last]; + + num_in = len_in-margin; + } + + Frontend::AudioOut_Resample(buf_in, num_in, (s16*)stream, len); +} + EmuThread::EmuThread(QObject* parent) : QThread(parent) { @@ -213,18 +257,18 @@ void EmuThread::run() mainWindow->update(); bool fastforward = false; - /*bool fastforward = HotkeyDown(HK_FastForward); + //bool fastforward = HotkeyDown(HK_FastForward); - if (Config::AudioSync && !fastforward) + if (Config::AudioSync && (!fastforward) && audioDevice) { - SDL_LockMutex(AudioSyncLock); + SDL_LockMutex(audioSyncLock); while (SPU::GetOutputSize() > 1024) { - int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500); + int ret = SDL_CondWaitTimeout(audioSync, audioSyncLock, 500); if (ret == SDL_MUTEX_TIMEDOUT) break; } - SDL_UnlockMutex(AudioSyncLock); - }*/ + SDL_UnlockMutex(audioSyncLock); + } float framerate = (1000.0f * nlines) / (60.0f * 263.0f); @@ -338,6 +382,7 @@ void EmuThread::emuRun() // checkme emit windowEmuStart(); + if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); } void EmuThread::emuPause(bool refresh) @@ -348,6 +393,7 @@ void EmuThread::emuPause(bool refresh) while (EmuStatus != status); //emit windowEmuPause(); + if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); } void EmuThread::emuUnpause() @@ -355,11 +401,14 @@ void EmuThread::emuUnpause() EmuRunning = PrevEmuStatus; //emit windowEmuUnpause(); + if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); } void EmuThread::emuStop() { EmuRunning = 0; + + if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); } bool EmuThread::emuIsRunning() @@ -908,6 +957,32 @@ int main(int argc, char** argv) } #endif + audioSync = SDL_CreateCond(); + audioSyncLock = SDL_CreateMutex(); + + audioFreq = 48000; // TODO: make configurable? + SDL_AudioSpec whatIwant, whatIget; + memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); + whatIwant.freq = audioFreq; + whatIwant.format = AUDIO_S16LSB; + whatIwant.channels = 2; + whatIwant.samples = 1024; + whatIwant.callback = audioCallback; + audioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + if (!audioDevice) + { + printf("Audio init failed: %s\n", SDL_GetError()); + } + else + { + audioFreq = whatIget.freq; + printf("Audio output frequency: %d Hz\n", audioFreq); + SDL_PauseAudioDevice(audioDevice, 1); + } + + Frontend::Init_ROM(); + Frontend::Init_Audio(audioFreq); + mainWindow = new MainWindow(); mainWindow->show(); @@ -955,6 +1030,15 @@ int main(int argc, char** argv) emuThread->emuStop(); emuThread->wait(); + //if (Joystick) SDL_JoystickClose(Joystick); + if (audioDevice) SDL_CloseAudioDevice(audioDevice); + //if (MicDevice) SDL_CloseAudioDevice(MicDevice); + + SDL_DestroyCond(audioSync); + SDL_DestroyMutex(audioSyncLock); + + //if (MicWavBuffer) delete[] MicWavBuffer; + Config::Save(); SDL_Quit(); From 9432a9f3822f024e97185ac4b0a9df5c07987dd1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 3 May 2020 15:05:52 +0200 Subject: [PATCH 025/105] remove useless variables --- src/frontend/qt_sdl/main.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 80c25b5c..643cf90c 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -147,10 +147,6 @@ void EmuThread::run() u32 lasttick = starttick; u32 lastmeasuretick = lasttick; u32 fpslimitcount = 0; - u64 perfcount = SDL_GetPerformanceCounter(); - u64 perffreq = SDL_GetPerformanceFrequency(); - float samplesleft = 0; - u32 nsamples = 0; char melontitle[100]; @@ -288,7 +284,6 @@ void EmuThread::run() if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60)) { fpslimitcount = 0; - nsamples = 0; starttick = lasttick; } } From 5c5d280dd547958a37824809b7a038efbb3aee3b Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 10 May 2020 23:09:17 +0200 Subject: [PATCH 026/105] Add -flto as link flag, also fix missing include in main.cpp causing a build failure with gcc10 --- CMakeLists.txt | 1 + src/libui_sdl/libui/unix/CMakeLists.txt | 2 +- src/libui_sdl/main.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 048dd44a..e3f9cb63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ endif() if(ENABLE_LTO) add_compile_options(-O3 -flto) + add_link_options(-flto) set(CMAKE_AR "gcc-ar") set(CMAKE_C_ARCHIVE_CREATE " qcs ") set(CMAKE_C_ARCHIVE_FINISH true) diff --git a/src/libui_sdl/libui/unix/CMakeLists.txt b/src/libui_sdl/libui/unix/CMakeLists.txt index c69081ee..39f6c0a0 100644 --- a/src/libui_sdl/libui/unix/CMakeLists.txt +++ b/src/libui_sdl/libui/unix/CMakeLists.txt @@ -65,7 +65,7 @@ macro(_handle_static) OUTPUT ${_oname} DEPENDS ${_LIBUINAME} COMMAND - ld -r --whole-archive ${_aname} -o ${_oname} + ${CMAKE_LINKER} -r --whole-archive ${_aname} -o ${_oname} COMMAND objcopy --localize-hidden ${_oname} COMMENT "Removing hidden symbols") diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index 9dea9f17..80b86651 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #ifndef __WIN32__ #include From 675b3f882ff1c0cc66a34e571a64e028f269f4bc Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 10 May 2020 23:29:47 +0200 Subject: [PATCH 027/105] Fix building with Clang --- CMakeLists.txt | 13 ++++++++++++- src/libui_sdl/OSD.cpp | 4 ++-- src/libui_sdl/libui/unix/CMakeLists.txt | 20 +------------------- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3f9cb63..aa33d4b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,18 @@ endif() if(ENABLE_LTO) add_compile_options(-O3 -flto) add_link_options(-flto) - set(CMAKE_AR "gcc-ar") + + if (${CMAKE_CXX_COMPILER_ID} STREQUAL Clang) + find_program(LLD ld.lld) + if (LLD) + add_link_options(-fuse-ld=lld) + else() + add_link_options(-fuse-linker-plugin) + endif() + set(CMAKE_AR "llvm-ar") + else() + set(CMAKE_AR "gcc-ar") + endif() set(CMAKE_C_ARCHIVE_CREATE " qcs ") set(CMAKE_C_ARCHIVE_FINISH true) set(CMAKE_CXX_ARCHIVE_CREATE " qcs ") diff --git a/src/libui_sdl/OSD.cpp b/src/libui_sdl/OSD.cpp index a01e39b9..02418ccb 100644 --- a/src/libui_sdl/OSD.cpp +++ b/src/libui_sdl/OSD.cpp @@ -419,8 +419,8 @@ void Update(bool opengl, uiAreaDrawParams* params) item.DrawBitmapLoaded = true; } - uiRect rc_src = {0, 0, item.Width, item.Height}; - uiRect rc_dst = {kOSDMargin, y, item.Width, item.Height}; + uiRect rc_src = {0, 0, (int) item.Width, (int) item.Height}; + uiRect rc_dst = {kOSDMargin, (int) y, (int) item.Width, (int) item.Height}; uiDrawBitmapDraw(params->Context, item.DrawBitmap, &rc_src, &rc_dst, 0); } diff --git a/src/libui_sdl/libui/unix/CMakeLists.txt b/src/libui_sdl/libui/unix/CMakeLists.txt index 39f6c0a0..1f4ab865 100644 --- a/src/libui_sdl/libui/unix/CMakeLists.txt +++ b/src/libui_sdl/libui/unix/CMakeLists.txt @@ -54,27 +54,9 @@ set(_LIBUI_INCLUDEDIRS _LIBUI_INCLUDEDIRS PARENT_SCOPE) set(_LIBUINAME libui PARENT_SCOPE) if(NOT BUILD_SHARED_LIBS) - set(_LIBUINAME libui-temporary PARENT_SCOPE) + # set(_LIBUINAME libui-temporary PARENT_SCOPE) endif() macro(_handle_static) - set_target_properties(${_LIBUINAME} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") - set(_aname $) - set(_oname libui-combined.o) - add_custom_command( - OUTPUT ${_oname} - DEPENDS ${_LIBUINAME} - COMMAND - ${CMAKE_LINKER} -r --whole-archive ${_aname} -o ${_oname} - COMMAND - objcopy --localize-hidden ${_oname} - COMMENT "Removing hidden symbols") - add_library(libui STATIC ${_oname}) - # otherwise cmake won't know which linker to use - set_target_properties(libui PROPERTIES - LINKER_LANGUAGE C) - set(_aname) - set(_oname) endmacro() # TODO the other variables don't work? From b341514a221c49b0b444b6185947e4a4c00e9aeb Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 10 May 2020 23:45:59 +0200 Subject: [PATCH 028/105] Use -Og for debug builds --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa33d4b7..0aa558d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ else() option(ENABLE_LTO "Enable link-time optimization" OFF) endif() +if (CMAKE_BUILD_TYPE STREQUAL Debug) + add_compile_options(-Og) +endif() + if(ENABLE_LTO) add_compile_options(-O3 -flto) add_link_options(-flto) From 57f33c208c5d02aba5cad74c539882e35b61e539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Mon, 11 May 2020 23:20:45 -0400 Subject: [PATCH 029/105] fix package name in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a34b7ea4..cae06fa0 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ As for the rest, the interface should be pretty straightforward. If you have a q * Install dependencies: ```sh -sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev +sudo apt-get install libgtk-3-dev libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev ``` * Compile: From d6d49a9f708aa7fbba0556e0caf779b940498f73 Mon Sep 17 00:00:00 2001 From: lucasjome <15149319+lucasjome@users.noreply.github.com> Date: Thu, 14 May 2020 01:51:39 -0300 Subject: [PATCH 030/105] Removing CodeBlocks reference from README.md Removing CodeBlocks reference from README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index a34b7ea4..c3d5fe8f 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,6 @@ make -j$(nproc --all) ### Windows: - * use CodeBlocks - -#### MSYS2 and CMake - 1. Install [MSYS2](https://www.msys2.org/) 2. Open the **MSYS2 MinGW 64-bit** terminal 3. Update the packages using `pacman -Syu` and reopen the terminal if it asks you to From 978212e3e0b2d910ff3ca95464ad855f5872e500 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 16 May 2020 17:43:35 +0200 Subject: [PATCH 031/105] accept mouse events --- src/frontend/qt_sdl/main.cpp | 22 ++++++++++++++++++++++ src/frontend/qt_sdl/main.h | 4 ++++ 2 files changed, 26 insertions(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 643cf90c..11602a6f 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -447,6 +447,28 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) } +void MainWindowPanel::mousePressEvent(QMouseEvent* event) +{ + event->accept(); + + printf("mouse press %d,%d\n", event->pos().x(), event->pos().y()); +} + +void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event) +{ + event->accept(); + + printf("mouse release %d,%d\n", event->pos().x(), event->pos().y()); +} + +void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) +{ + event->accept(); + + printf("mouse move %d,%d %08X\n", event->pos().x(), event->pos().y(), event->buttons()); +} + + MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("melonDS " MELONDS_VERSION); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 30cef1f5..f8ad9a3f 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -68,6 +68,10 @@ public: protected: void paintEvent(QPaintEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; + private: QImage* screen[2]; }; From 2afa70b8172339266feabbb9a93f2f165521f7d8 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 02:37:23 +0200 Subject: [PATCH 032/105] miserable little attempt at adding a dialog --- src/frontend/qt_sdl/CMakeLists.txt | 3 + src/frontend/qt_sdl/EmuSettingsDialog.cpp | 31 ++++ src/frontend/qt_sdl/EmuSettingsDialog.h | 38 ++++ src/frontend/qt_sdl/EmuSettingsDialog.ui | 201 ++++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 15 ++ src/frontend/qt_sdl/main.h | 4 + 6 files changed, 292 insertions(+) create mode 100644 src/frontend/qt_sdl/EmuSettingsDialog.cpp create mode 100644 src/frontend/qt_sdl/EmuSettingsDialog.h create mode 100644 src/frontend/qt_sdl/EmuSettingsDialog.ui diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 05a40292..a6aeb0e1 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -2,6 +2,7 @@ project(qt_sdl) SET(SOURCES_QT_SDL main.cpp + EmuSettingsDialog.cpp Platform.cpp PlatformConfig.cpp @@ -19,6 +20,8 @@ find_package(Qt5 COMPONENTS Gui REQUIRED) find_package(Qt5 COMPONENTS Widgets REQUIRED) set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp new file mode 100644 index 00000000..c64f1927 --- /dev/null +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -0,0 +1,31 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include "EmuSettingsDialog.h" +#include "ui_EmuSettingsDialog.h" + + +EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::EmuSettingsDialog) +{ + ui->setupUi(this); +} + +EmuSettingsDialog::~EmuSettingsDialog() +{ + delete ui; +} diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.h b/src/frontend/qt_sdl/EmuSettingsDialog.h new file mode 100644 index 00000000..eb21aaaf --- /dev/null +++ b/src/frontend/qt_sdl/EmuSettingsDialog.h @@ -0,0 +1,38 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef EMUSETTINGSDIALOG_H +#define EMUSETTINGSDIALOG_H + +#include + +namespace Ui { class EmuSettingsDialog; } + +class EmuSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit EmuSettingsDialog(QWidget* parent); + ~EmuSettingsDialog(); + +private: + Ui::EmuSettingsDialog* ui; +}; + +#endif // EMUSETTINGSDIALOG_H diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.ui b/src/frontend/qt_sdl/EmuSettingsDialog.ui new file mode 100644 index 00000000..e4deaba9 --- /dev/null +++ b/src/frontend/qt_sdl/EmuSettingsDialog.ui @@ -0,0 +1,201 @@ + + + EmuSettingsDialog + + + + 0 + 0 + 490 + 243 + + + + + 0 + 0 + + + + Emu settings - melonDS + + + + QLayout::SetFixedSize + + + + + DS mode + + + + + + + 0 + 0 + + + + + 290 + 0 + + + + + + + <html><head/><body><p>DS-mode ARM9 BIOS</p><p>Size should be 4 KB</p></body></html> + + + + + + + DS firmware: + + + + + + + DS ARM7 BIOS: + + + + + + + DS ARM9 BIOS: + + + + + + + + 0 + 0 + + + + Browse... + + + true + + + + + + + <html><head/><body><p>DS-mode ARM7 BIOS</p><p>Size should be 16 KB</p></body></html> + + + + + + + Browse... + + + + + + + <html><head/><body><p>DS-mode firmware</p><p><br/></p><p>Possible firmwares:</p><p>* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.</p><p>* 256 KB: regular DS firmware.</p><p>* 512 KB: iQue DS firmware.</p></body></html> + + + + + + + Browse... + + + + + + + + + + Startup + + + + + + <html><head/><body><p>When loading a ROM, completely skip the regular boot process (&quot;Nintendo DS&quot; screen) to boot the ROM directly.</p><p><br/></p><p>Note: if your firmware dump isn't bootable, the ROM will be booted directly regardless of this setting.</p></body></html> + + + Boot game directly + + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + EmuSettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + EmuSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 11602a6f..39868765 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -31,6 +31,7 @@ #include #include "main.h" +#include "EmuSettingsDialog.h" #include "types.h" #include "version.h" @@ -545,6 +546,12 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actStop = menu->addAction("Stop"); connect(actStop, &QAction::triggered, this, &MainWindow::onStop); } + { + QMenu* menu = menubar->addMenu("Config"); + + actEmuSettings = menu->addAction("Emu settings"); + connect(actEmuSettings, &QAction::triggered, this, &MainWindow::onOpenEmuSettings); + } setMenuBar(menubar); panel = new MainWindowPanel(this); @@ -811,6 +818,14 @@ void MainWindow::onEmuUnpause() } +void MainWindow::onOpenEmuSettings() +{ + // TODO keep track of this pointer!! + EmuSettingsDialog* dlg = new EmuSettingsDialog(this); + dlg->show(); +} + + int main(int argc, char** argv) { srand(time(NULL)); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index f8ad9a3f..bb5e9037 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -107,6 +107,8 @@ private slots: void onEmuPause(); void onEmuUnpause(); + void onOpenEmuSettings(); + private: MainWindowPanel* panel; @@ -120,6 +122,8 @@ private: QAction* actPause; QAction* actReset; QAction* actStop; + + QAction* actEmuSettings; }; #endif // MAIN_H From 492a4b4b464b4b48bd821c126475c791e66b5c6d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 03:02:42 +0200 Subject: [PATCH 033/105] add config entries for BIOS/firmware paths --- src/frontend/qt_sdl/PlatformConfig.cpp | 16 ++++++++++++---- src/frontend/qt_sdl/PlatformConfig.h | 8 ++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index f78b1957..fba649cf 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -60,9 +60,13 @@ int SavestateRelocSRAM; int AudioVolume; int MicInputType; -char MicWavPath[512]; +char MicWavPath[1024]; -char LastROMFolder[512]; +char LastROMFolder[1024]; + +char BIOS9Path[1024]; +char BIOS7Path[1024]; +char FirmwarePath[1024]; ConfigEntry PlatformConfigFile[] = @@ -141,9 +145,13 @@ ConfigEntry PlatformConfigFile[] = {"AudioVolume", 0, &AudioVolume, 256, NULL, 0}, {"MicInputType", 0, &MicInputType, 1, NULL, 0}, - {"MicWavPath", 1, MicWavPath, 0, "", 511}, + {"MicWavPath", 1, MicWavPath, 0, "", 1023}, - {"LastROMFolder", 1, LastROMFolder, 0, "", 511}, + {"LastROMFolder", 1, LastROMFolder, 0, "", 1023}, + + {"BIOS9Path", 1, BIOS9Path, 0, "", 1023}, + {"BIOS7Path", 1, BIOS7Path, 0, "", 1023}, + {"FirmwarePath", 1, FirmwarePath, 0, "", 1023}, {"", -1, NULL, 0, NULL, 0} }; diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h index d0f765b2..e104015d 100644 --- a/src/frontend/qt_sdl/PlatformConfig.h +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -73,9 +73,13 @@ extern int SavestateRelocSRAM; extern int AudioVolume; extern int MicInputType; -extern char MicWavPath[512]; +extern char MicWavPath[1024]; -extern char LastROMFolder[512]; +extern char LastROMFolder[1024]; + +extern char BIOS9Path[1024]; +extern char BIOS7Path[1024]; +extern char FirmwarePath[1024]; } From 60ba163f08e0af4272c8de6141583238eb283fe8 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 04:02:16 +0200 Subject: [PATCH 034/105] take this somewhere --- src/frontend/qt_sdl/EmuSettingsDialog.cpp | 70 +++++++++++++++++++++++ src/frontend/qt_sdl/EmuSettingsDialog.h | 26 +++++++++ src/frontend/qt_sdl/main.cpp | 4 +- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index c64f1927..34cafb5e 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -16,16 +16,86 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ +#include + +#include "types.h" +#include "Config.h" +#include "PlatformConfig.h" + #include "EmuSettingsDialog.h" #include "ui_EmuSettingsDialog.h" +EmuSettingsDialog* EmuSettingsDialog::currentDlg = nullptr; + +extern char* EmuDirectory; + + EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::EmuSettingsDialog) { ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + ui->txtBIOS9Path->setText(Config::BIOS9Path); + ui->txtBIOS7Path->setText(Config::BIOS7Path); + ui->txtFirmwarePath->setText(Config::FirmwarePath); + ui->chkDirectBoot->setChecked(Config::DirectBoot != 0); } EmuSettingsDialog::~EmuSettingsDialog() { delete ui; } + +void EmuSettingsDialog::on_EmuSettingsDialog_accepted() +{ + strncpy(Config::BIOS9Path, ui->txtBIOS9Path->text().toStdString().c_str(), 1023); Config::BIOS9Path[1023] = '\0'; + strncpy(Config::BIOS7Path, ui->txtBIOS7Path->text().toStdString().c_str(), 1023); Config::BIOS7Path[1023] = '\0'; + strncpy(Config::FirmwarePath, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); Config::FirmwarePath[1023] = '\0'; + Config::DirectBoot = ui->chkDirectBoot->isChecked() ? 1:0; + + closeDlg(); +} + +void EmuSettingsDialog::on_EmuSettingsDialog_rejected() +{ + closeDlg(); +} + +void EmuSettingsDialog::on_btnBIOS9Browse_clicked() +{ + QString file = QFileDialog::getOpenFileName(this, + "Select DS-mode ARM9 BIOS...", + EmuDirectory, + "BIOS files (*.bin *.rom);;Any file (*.*)"); + + if (file.isEmpty()) return; + + ui->txtBIOS9Path->setText(file); +} + +void EmuSettingsDialog::on_btnBIOS7Browse_clicked() +{ + QString file = QFileDialog::getOpenFileName(this, + "Select DS-mode ARM7 BIOS...", + EmuDirectory, + "BIOS files (*.bin *.rom);;Any file (*.*)"); + + if (file.isEmpty()) return; + + ui->txtBIOS7Path->setText(file); +} + +void EmuSettingsDialog::on_btnFirmwareBrowse_clicked() +{ + QString file = QFileDialog::getOpenFileName(this, + "Select DS-mode firmware...", + EmuDirectory, + "Firmware files (*.bin *.rom);;Any file (*.*)"); + + if (file.isEmpty()) return; + + // TODO: check for shitty hacked firmware here? + + ui->txtFirmwarePath->setText(file); +} diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.h b/src/frontend/qt_sdl/EmuSettingsDialog.h index eb21aaaf..471e0fb0 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.h +++ b/src/frontend/qt_sdl/EmuSettingsDialog.h @@ -22,6 +22,7 @@ #include namespace Ui { class EmuSettingsDialog; } +class EmuSettingsDialog; class EmuSettingsDialog : public QDialog { @@ -31,6 +32,31 @@ public: explicit EmuSettingsDialog(QWidget* parent); ~EmuSettingsDialog(); + static EmuSettingsDialog* currentDlg; + static void openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return; + } + + currentDlg = new EmuSettingsDialog(parent); + currentDlg->show(); + } + static void closeDlg() + { + currentDlg = nullptr; + } + +private slots: + void on_EmuSettingsDialog_accepted(); + void on_EmuSettingsDialog_rejected(); + + void on_btnBIOS9Browse_clicked(); + void on_btnBIOS7Browse_clicked(); + void on_btnFirmwareBrowse_clicked(); + private: Ui::EmuSettingsDialog* ui; }; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 39868765..8b973201 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -820,9 +820,7 @@ void MainWindow::onEmuUnpause() void MainWindow::onOpenEmuSettings() { - // TODO keep track of this pointer!! - EmuSettingsDialog* dlg = new EmuSettingsDialog(this); - dlg->show(); + EmuSettingsDialog::openDlg(this); } From 17d30e91f01ea015caf5e28afe8ddca4aede45b1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 04:37:44 +0200 Subject: [PATCH 035/105] actually hook this up --- src/Config.cpp | 8 ++++ src/Config.h | 4 ++ src/NDS.cpp | 4 +- src/SPI.cpp | 16 ++++++-- src/frontend/qt_sdl/EmuSettingsDialog.cpp | 49 ++++++++++++++++++++++- src/frontend/qt_sdl/EmuSettingsDialog.h | 2 + src/frontend/qt_sdl/PlatformConfig.cpp | 8 ---- src/frontend/qt_sdl/PlatformConfig.h | 4 -- 8 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index f558ef64..7604785f 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -28,6 +28,10 @@ namespace Config const char* kConfigFile = "melonDS.ini"; +char BIOS9Path[1024]; +char BIOS7Path[1024]; +char FirmwarePath[1024]; + int _3DRenderer; int Threaded3D; @@ -36,6 +40,10 @@ int GL_Antialias; ConfigEntry ConfigFile[] = { + {"BIOS9Path", 1, BIOS9Path, 0, "", 1023}, + {"BIOS7Path", 1, BIOS7Path, 0, "", 1023}, + {"FirmwarePath", 1, FirmwarePath, 0, "", 1023}, + {"3DRenderer", 0, &_3DRenderer, 1, NULL, 0}, {"Threaded3D", 0, &Threaded3D, 1, NULL, 0}, diff --git a/src/Config.h b/src/Config.h index 0aeab852..05b9b8b9 100644 --- a/src/Config.h +++ b/src/Config.h @@ -42,6 +42,10 @@ bool HasConfigFile(const char* fileName); void Load(); void Save(); +extern char BIOS9Path[1024]; +extern char BIOS7Path[1024]; +extern char FirmwarePath[1024]; + extern int _3DRenderer; extern int Threaded3D; diff --git a/src/NDS.cpp b/src/NDS.cpp index a2ab6ce9..1d425a87 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -416,7 +416,7 @@ void Reset() RunningGame = false; LastSysClockCycles = 0; - f = Platform::OpenLocalFile("bios9.bin", "rb"); + f = Platform::OpenLocalFile(Config::BIOS9Path, "rb"); if (!f) { printf("ARM9 BIOS not found\n"); @@ -433,7 +433,7 @@ void Reset() fclose(f); } - f = Platform::OpenLocalFile("bios7.bin", "rb"); + f = Platform::OpenLocalFile(Config::BIOS7Path, "rb"); if (!f) { printf("ARM7 BIOS not found\n"); diff --git a/src/SPI.cpp b/src/SPI.cpp index 1a5873e1..056e8d54 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -28,6 +28,7 @@ namespace SPI_Firmware { +char FirmwarePath[1024]; u8* Firmware; u32 FirmwareLength; u32 FirmwareMask; @@ -76,6 +77,7 @@ bool VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset) bool Init() { + memset(FirmwarePath, 0, sizeof(FirmwarePath)); Firmware = NULL; return true; } @@ -90,10 +92,12 @@ void Reset() if (Firmware) delete[] Firmware; Firmware = NULL; - FILE* f = Platform::OpenLocalFile("firmware.bin", "rb"); + strncpy(FirmwarePath, Config::FirmwarePath, 1023); + + FILE* f = Platform::OpenLocalFile(FirmwarePath, "rb"); if (!f) { - printf("firmware.bin not found\n"); + printf("Firmware not found\n"); // TODO: generate default firmware return; @@ -129,7 +133,11 @@ void Reset() fclose(f); // take a backup - const char* firmbkp = "firmware.bin.bak"; + char firmbkp[1028]; + int fplen = strlen(FirmwarePath); + strncpy(&firmbkp[0], FirmwarePath, fplen); + strncpy(&firmbkp[fplen], ".bak", 1028-fplen); + firmbkp[fplen+4] = '\0'; f = Platform::OpenLocalFile(firmbkp, "rb"); if (f) fclose(f); else @@ -325,7 +333,7 @@ void Write(u8 val, u32 hold) if (!hold && (CurCmd == 0x02 || CurCmd == 0x0A)) { - FILE* f = Platform::OpenLocalFile("firmware.bin", "r+b"); + FILE* f = Platform::OpenLocalFile(FirmwarePath, "r+b"); if (f) { u32 cutoff = 0x7FA00 & FirmwareMask; diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index 34cafb5e..bce55138 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -16,9 +16,12 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ +#include #include +#include #include "types.h" +#include "Platform.h" #include "Config.h" #include "PlatformConfig.h" @@ -47,8 +50,52 @@ EmuSettingsDialog::~EmuSettingsDialog() delete ui; } +void EmuSettingsDialog::verifyFirmware() +{ + // verify the firmware + // + // there are dumps of an old hacked firmware floating around on the internet + // and those are problematic + // the hack predates WFC, and, due to this, any game that alters the WFC + // access point data will brick that firmware due to it having critical + // data in the same area. it has the same problem on hardware. + // + // but this should help stop users from reporting that issue over and over + // again, when the issue is not from melonDS but from their firmware dump. + // + // I don't know about all the firmware hacks in existence, but the one I + // looked at has 0x180 bytes from the header repeated at 0x3FC80, but + // bytes 0x0C-0x14 are different. + + char filename[1024]; + strncpy(filename, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); filename[1023] = '\0'; + FILE* f = Platform::OpenLocalFile(filename, "rb"); + u8 chk1[0x180], chk2[0x180]; + + fseek(f, 0, SEEK_SET); + fread(chk1, 1, 0x180, f); + fseek(f, -0x380, SEEK_END); + fread(chk2, 1, 0x180, f); + + memset(&chk1[0x0C], 0, 8); + memset(&chk2[0x0C], 0, 8); + + fclose(f); + + if (!memcmp(chk1, chk2, 0x180)) + { + QMessageBox::warning(this, + "Problematic firmware dump", + "You are using an old hacked firmware dump.\n" + "Firmware boot will stop working if you run any game that alters WFC settings.\n\n" + "Note that the issue is not from melonDS, it would also happen on an actual DS."); + } +} + void EmuSettingsDialog::on_EmuSettingsDialog_accepted() { + verifyFirmware(); + strncpy(Config::BIOS9Path, ui->txtBIOS9Path->text().toStdString().c_str(), 1023); Config::BIOS9Path[1023] = '\0'; strncpy(Config::BIOS7Path, ui->txtBIOS7Path->text().toStdString().c_str(), 1023); Config::BIOS7Path[1023] = '\0'; strncpy(Config::FirmwarePath, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); Config::FirmwarePath[1023] = '\0'; @@ -95,7 +142,5 @@ void EmuSettingsDialog::on_btnFirmwareBrowse_clicked() if (file.isEmpty()) return; - // TODO: check for shitty hacked firmware here? - ui->txtFirmwarePath->setText(file); } diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.h b/src/frontend/qt_sdl/EmuSettingsDialog.h index 471e0fb0..ce641454 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.h +++ b/src/frontend/qt_sdl/EmuSettingsDialog.h @@ -58,6 +58,8 @@ private slots: void on_btnFirmwareBrowse_clicked(); private: + void verifyFirmware(); + Ui::EmuSettingsDialog* ui; }; diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index fba649cf..1f6a8731 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -64,10 +64,6 @@ char MicWavPath[1024]; char LastROMFolder[1024]; -char BIOS9Path[1024]; -char BIOS7Path[1024]; -char FirmwarePath[1024]; - ConfigEntry PlatformConfigFile[] = { @@ -149,10 +145,6 @@ ConfigEntry PlatformConfigFile[] = {"LastROMFolder", 1, LastROMFolder, 0, "", 1023}, - {"BIOS9Path", 1, BIOS9Path, 0, "", 1023}, - {"BIOS7Path", 1, BIOS7Path, 0, "", 1023}, - {"FirmwarePath", 1, FirmwarePath, 0, "", 1023}, - {"", -1, NULL, 0, NULL, 0} }; diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h index e104015d..3704d149 100644 --- a/src/frontend/qt_sdl/PlatformConfig.h +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -77,10 +77,6 @@ extern char MicWavPath[1024]; extern char LastROMFolder[1024]; -extern char BIOS9Path[1024]; -extern char BIOS7Path[1024]; -extern char FirmwarePath[1024]; - } #endif // PLATFORMCONFIG_H From 49b24ea2b3b730b2d4acb20231989d1ace84a59b Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 04:42:15 +0200 Subject: [PATCH 036/105] this might be betterer --- src/frontend/qt_sdl/EmuSettingsDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index bce55138..6264d91c 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -84,7 +84,7 @@ void EmuSettingsDialog::verifyFirmware() if (!memcmp(chk1, chk2, 0x180)) { - QMessageBox::warning(this, + QMessageBox::warning((QWidget*)this->parent(), "Problematic firmware dump", "You are using an old hacked firmware dump.\n" "Firmware boot will stop working if you run any game that alters WFC settings.\n\n" From c5c9434ac9abaa0ae9c3125ee6e8bc4653846ebd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 05:42:09 +0200 Subject: [PATCH 037/105] verify BIOS and firmware before booting games/firmware --- src/NDS.cpp | 2 +- src/frontend/FrontendUtil.h | 22 +++++++- src/frontend/Util_ROM.cpp | 100 ++++++++++++++++++++++++++++++++--- src/frontend/qt_sdl/main.cpp | 41 +++++++++++--- src/frontend/qt_sdl/main.h | 2 + 5 files changed, 149 insertions(+), 18 deletions(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index 1d425a87..745ed28b 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -587,7 +587,7 @@ bool DoSavestate_Scheduler(Savestate* file) } if (funcid == -1) { - printf("savestate: VERY BAD!!!!! FUNCTION POINTER FOR EVENT %d NOT IN HACKY LIST. CANNOT SAVE. SMACK STAPLEBUTTER.\n", i); + printf("savestate: VERY BAD!!!!! FUNCTION POINTER FOR EVENT %d NOT IN HACKY LIST. CANNOT SAVE. SMACK ARISOTURA.\n", i); return false; } } diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 32f28d14..f4f68502 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -32,6 +32,24 @@ enum ROMSlot_MAX }; +enum +{ + Load_OK = 0, + + Load_BIOS9Missing, + Load_BIOS9Bad, + + Load_BIOS7Missing, + Load_BIOS7Bad, + + Load_FirmwareMissing, + Load_FirmwareBad, + Load_FirmwareNotBootable, + + // TODO: more precise errors for ROM loading + Load_ROMLoadError, +}; + extern char ROMPath [ROMSlot_MAX][1024]; extern char SRAMPath[ROMSlot_MAX][1024]; extern bool SavestateLoaded; @@ -41,11 +59,11 @@ extern bool SavestateLoaded; void Init_ROM(); // load the BIOS/firmware and boot from it -bool LoadBIOS(); +int LoadBIOS(); // load a ROM file to the specified cart slot // note: loading a ROM to the NDS slot resets emulation -bool LoadROM(const char* file, int slot); +int LoadROM(const char* file, int slot); // get the filename associated with the given savestate slot (1-8) void GetSavestateName(int slot, char* filename, int len); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 19c8eb91..3200de4c 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -57,8 +57,77 @@ void SetupSRAMPath(int slot) strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3); } -bool LoadBIOS() +int VerifyDSBIOS() { + FILE* f; + long len; + + f = Platform::OpenLocalFile(Config::BIOS9Path, "rb"); + if (!f) return Load_BIOS9Missing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x1000) + { + fclose(f); + return Load_BIOS9Bad; + } + + fclose(f); + + f = Platform::OpenLocalFile(Config::BIOS7Path, "rb"); + if (!f) return Load_BIOS7Missing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x4000) + { + fclose(f); + return Load_BIOS7Bad; + } + + fclose(f); + + return Load_OK; +} + +int VerifyDSFirmware() +{ + FILE* f; + long len; + + f = Platform::OpenLocalFile(Config::FirmwarePath, "rb"); + if (!f) return Load_FirmwareMissing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len == 0x20000) + { + // 128KB firmware, not bootable + fclose(f); + return Load_FirmwareNotBootable; + } + else if (len != 0x40000 && len != 0x80000) + { + fclose(f); + return Load_FirmwareBad; + } + + fclose(f); + + return Load_OK; +} + +int LoadBIOS() +{ + int res; + + res = VerifyDSBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSFirmware(); + if (res != Load_OK) return res; + // TODO: // original code in the libui frontend called NDS::LoadGBAROM() if needed // should this be carried over here? @@ -71,12 +140,26 @@ bool LoadBIOS() SavestateLoaded = false; - // TODO: error reporting? - return true; + return Load_OK; } -bool LoadROM(const char* file, int slot) +int LoadROM(const char* file, int slot) { + int res; + bool directboot = Config::DirectBoot != 0; + + res = VerifyDSBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSFirmware(); + if (res != Load_OK) + { + if (res == Load_FirmwareNotBootable) + directboot = true; + else + return res; + } + char oldpath[1024]; char oldsram[1024]; strncpy(oldpath, ROMPath[slot], 1024); @@ -88,28 +171,29 @@ bool LoadROM(const char* file, int slot) SetupSRAMPath(0); SetupSRAMPath(1); - if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot)) + if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], directboot)) { SavestateLoaded = false; // Reload the inserted GBA cartridge (if any) + // TODO: report failure there?? if (ROMPath[ROMSlot_GBA][0] != '\0') NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA]); strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety - return true; + return Load_OK; } else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) { SavestateLoaded = false; strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety - return true; + return Load_OK; } else { strncpy(ROMPath[slot], oldpath, 1024); strncpy(SRAMPath[slot], oldsram, 1024); - return false; + return Load_ROMLoadError; } } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 8b973201..ec4b04b1 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -570,6 +570,27 @@ void MainWindow::keyPressEvent(QKeyEvent* event) } +QString MainWindow::loadErrorStr(int error) +{ + switch (error) + { + case Frontend::Load_BIOS9Missing: return "DS ARM9 BIOS was not found or could not be accessed."; + case Frontend::Load_BIOS9Bad: return "DS ARM9 BIOS is not a valid BIOS dump."; + + case Frontend::Load_BIOS7Missing: return "DS ARM7 BIOS was not found or could not be accessed."; + case Frontend::Load_BIOS7Bad: return "DS ARM7 BIOS is not a valid BIOS dump."; + + case Frontend::Load_FirmwareMissing: return "DS firmware was not found or could not be accessed."; + case Frontend::Load_FirmwareBad: return "DS firmware is not a valid firmware dump."; + case Frontend::Load_FirmwareNotBootable: return "DS firmware is not bootable."; + + case Frontend::Load_ROMLoadError: return "Failed to load the ROM. Make sure the file is accessible and isn't used by another application."; + + default: return "Unknown error during launch; smack Arisotura."; + } +} + + void MainWindow::onOpenFile() { emuThread->emuPause(true); @@ -584,6 +605,11 @@ void MainWindow::onOpenFile() return; } + // TODO: validate the input file!! + // * check that it is a proper ROM + // * ensure the binary offsets are sane + // * etc + // this shit is stupid char file[1024]; strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0'; @@ -594,7 +620,7 @@ void MainWindow::onOpenFile() Config::LastROMFolder[pos] = '\0'; char* ext = &file[strlen(file)-3]; - int slot; bool res; + int slot; int res; if (!strcasecmp(ext, "gba")) { slot = 1; @@ -606,11 +632,11 @@ void MainWindow::onOpenFile() res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); } - if (!res) + if (res != Frontend::Load_OK) { QMessageBox::critical(this, "melonDS", - "Failed to load the ROM.\n\nMake sure the file is accessible and isn't used by another application."); + loadErrorStr(res)); emuThread->emuUnpause(); } else if (slot == 1) @@ -631,11 +657,12 @@ void MainWindow::onBootFirmware() emuThread->emuPause(true); - bool res = Frontend::LoadBIOS(); - if (!res) + int res = Frontend::LoadBIOS(); + if (res != Frontend::Load_OK) { - // TODO! - + QMessageBox::critical(this, + "melonDS", + loadErrorStr(res)); emuThread->emuUnpause(); } else diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index bb5e9037..ee0094f0 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -110,6 +110,8 @@ private slots: void onOpenEmuSettings(); private: + QString loadErrorStr(int error); + MainWindowPanel* panel; QAction* actOpenROM; From 0566c9e34c36f7f1841765b02147fd4c890e8550 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 13:04:02 +0200 Subject: [PATCH 038/105] minor fix --- src/NDSCart.cpp | 5 +++ src/frontend/qt_sdl/Platform.cpp | 2 +- src/frontend/qt_sdl/main.cpp | 68 +------------------------------- 3 files changed, 7 insertions(+), 68 deletions(-) diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 5a2a0d0c..585eadf3 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -867,6 +867,11 @@ bool ReadROMParams(u32 gamecode, u32* params) void DecryptSecureArea(u8* out) { + // TODO: source decryption data from different possible sources + // * original DS-mode ARM7 BIOS has the key data at 0x30 + // * .srl ROMs (VC dumps) have encrypted secure areas but have precomputed + // decryption data at 0x1000 (and at the beginning of the DSi region if any) + u32 gamecode = *(u32*)&CartROM[0x0C]; u32 arm9base = *(u32*)&CartROM[0x20]; diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 31b5277d..fea9166c 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -202,7 +202,7 @@ FILE* OpenLocalFile(const char* path, const char* mode) #ifdef __WIN32__ if (pathlen > 3) { - if (path[1] == ':' && path[2] == '\\') + if (path[1] == ':' && (path[2] == '\\' || path[2] == '/')) return OpenFile(path, mode); } #else diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index ec4b04b1..67eb3d83 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -915,74 +915,8 @@ int main(int argc, char** argv) //if (Config::AudioVolume < 0) Config::AudioVolume = 0; //else if (Config::AudioVolume > 256) Config::AudioVolume = 256; - // TODO: those should be checked before running anything - // (as to let the user specify their own BIOS/firmware path etc) + // TODO: this should be checked before running anything #if 0 - if (!Platform::LocalFileExists("bios7.bin") || - !Platform::LocalFileExists("bios9.bin") || - !Platform::LocalFileExists("firmware.bin")) - { -#if defined(__WIN32__) || defined(UNIX_PORTABLE) - const char* locationName = "the directory you run melonDS from"; -#else - char* locationName = EmuDirectory; -#endif - char msgboxtext[512]; - sprintf(msgboxtext, - "One or more of the following required files don't exist or couldn't be accessed:\n\n" - "bios7.bin -- ARM7 BIOS\n" - "bios9.bin -- ARM9 BIOS\n" - "firmware.bin -- firmware image\n\n" - "Dump the files from your DS and place them in %s.\n" - "Make sure that the files can be accessed.", - locationName - ); - - uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext); - - uiUninit(); - SDL_Quit(); - return 0; - } - if (!Platform::LocalFileExists("firmware.bin.bak")) - { - // verify the firmware - // - // there are dumps of an old hacked firmware floating around on the internet - // and those are problematic - // the hack predates WFC, and, due to this, any game that alters the WFC - // access point data will brick that firmware due to it having critical - // data in the same area. it has the same problem on hardware. - // - // but this should help stop users from reporting that issue over and over - // again, when the issue is not from melonDS but from their firmware dump. - // - // I don't know about all the firmware hacks in existence, but the one I - // looked at has 0x180 bytes from the header repeated at 0x3FC80, but - // bytes 0x0C-0x14 are different. - - FILE* f = Platform::OpenLocalFile("firmware.bin", "rb"); - u8 chk1[0x180], chk2[0x180]; - - fseek(f, 0, SEEK_SET); - fread(chk1, 1, 0x180, f); - fseek(f, -0x380, SEEK_END); - fread(chk2, 1, 0x180, f); - - memset(&chk1[0x0C], 0, 8); - memset(&chk2[0x0C], 0, 8); - - fclose(f); - - if (!memcmp(chk1, chk2, 0x180)) - { - uiMsgBoxError(NULL, - "Problematic firmware dump", - "You are using an old hacked firmware dump.\n" - "Firmware boot will stop working if you run any game that alters WFC settings.\n\n" - "Note that the issue is not from melonDS, it would also happen on an actual DS."); - } - } { const char* romlist_missing = "Save memory type detection will not work correctly.\n\n" "You should use the latest version of romlist.bin (provided in melonDS release packages)."; From c9a76edf210410dbf95d100690bad9c86aa5bd84 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 14:23:06 +0200 Subject: [PATCH 039/105] probably fix some pretty bad issue good one, Generic --- src/frontend/qt_sdl/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 67eb3d83..a7388a02 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -888,9 +888,12 @@ int main(int argc, char** argv) #else const char* confdir = g_get_user_config_dir(); const char* confname = "/melonDS"; - EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1]; - strcat(EmuDirectory, confdir); - strcat(EmuDirectory, confname); + int cdlen = strlen(confdir); + int cnlen = strlen(confname); + EmuDirectory = new char[cdlen + cnlen + 1]; + strncpy(&EmuDirectory[0], confdir, cdlen); + strncpy(&EmuDirectory[cdlen], confname, cnlen); + EmuDirectory[cdlen+cnlen] = '\0'; #endif QApplication melon(argc, argv); From 19566178ba7ee1fcd4207139286707cc3896493a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 17 May 2020 18:33:03 +0200 Subject: [PATCH 040/105] begin adding input dialog --- src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/EmuSettingsDialog.h | 5 +- src/frontend/qt_sdl/InputConfigDialog.cpp | 53 +++++++++ src/frontend/qt_sdl/InputConfigDialog.h | 63 +++++++++++ src/frontend/qt_sdl/InputConfigDialog.ui | 126 ++++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 21 +++- src/frontend/qt_sdl/main.h | 3 + 7 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 src/frontend/qt_sdl/InputConfigDialog.cpp create mode 100644 src/frontend/qt_sdl/InputConfigDialog.h create mode 100644 src/frontend/qt_sdl/InputConfigDialog.ui diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index a6aeb0e1..da3bb1dc 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -3,6 +3,7 @@ project(qt_sdl) SET(SOURCES_QT_SDL main.cpp EmuSettingsDialog.cpp + InputConfigDialog.cpp Platform.cpp PlatformConfig.cpp diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.h b/src/frontend/qt_sdl/EmuSettingsDialog.h index ce641454..73786417 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.h +++ b/src/frontend/qt_sdl/EmuSettingsDialog.h @@ -33,16 +33,17 @@ public: ~EmuSettingsDialog(); static EmuSettingsDialog* currentDlg; - static void openDlg(QWidget* parent) + static EmuSettingsDialog* openDlg(QWidget* parent) { if (currentDlg) { currentDlg->activateWindow(); - return; + return currentDlg; } currentDlg = new EmuSettingsDialog(parent); currentDlg->show(); + return currentDlg; } static void closeDlg() { diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp new file mode 100644 index 00000000..f7c0ab29 --- /dev/null +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -0,0 +1,53 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +// + +#include "types.h" +#include "Config.h" +#include "PlatformConfig.h" + +#include "InputConfigDialog.h" +#include "ui_InputConfigDialog.h" + + +InputConfigDialog* InputConfigDialog::currentDlg = nullptr; + + +InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new Ui::InputConfigDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + // +} + +InputConfigDialog::~InputConfigDialog() +{ + delete ui; +} + +void InputConfigDialog::on_InputConfigDialog_accepted() +{ + closeDlg(); +} + +void InputConfigDialog::on_InputConfigDialog_rejected() +{ + closeDlg(); +} diff --git a/src/frontend/qt_sdl/InputConfigDialog.h b/src/frontend/qt_sdl/InputConfigDialog.h new file mode 100644 index 00000000..2af73db0 --- /dev/null +++ b/src/frontend/qt_sdl/InputConfigDialog.h @@ -0,0 +1,63 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef INPUTCONFIGDIALOG_H +#define INPUTCONFIGDIALOG_H + +#include + +namespace Ui { class InputConfigDialog; } +class InputConfigDialog; + +class InputConfigDialog : public QDialog +{ + Q_OBJECT + +public: + explicit InputConfigDialog(QWidget* parent); + ~InputConfigDialog(); + + static InputConfigDialog* currentDlg; + static InputConfigDialog* openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return currentDlg; + } + + currentDlg = new InputConfigDialog(parent); + currentDlg->open(); + return currentDlg; + } + static void closeDlg() + { + currentDlg = nullptr; + } + +private slots: + void on_InputConfigDialog_accepted(); + void on_InputConfigDialog_rejected(); + + // + +private: + Ui::InputConfigDialog* ui; +}; + +#endif // INPUTCONFIGDIALOG_H diff --git a/src/frontend/qt_sdl/InputConfigDialog.ui b/src/frontend/qt_sdl/InputConfigDialog.ui new file mode 100644 index 00000000..c1422e9b --- /dev/null +++ b/src/frontend/qt_sdl/InputConfigDialog.ui @@ -0,0 +1,126 @@ + + + InputConfigDialog + + + + 0 + 0 + 488 + 365 + + + + TDAH + + + + QLayout::SetFixedSize + + + + + 1 + + + + DS input + + + + + General hotkeys + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Joystick: + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Selects which joystick will be used for joystick input, if any is present.</p></body></html> + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + InputConfigDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + InputConfigDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index a7388a02..cd7849df 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -32,6 +32,7 @@ #include "main.h" #include "EmuSettingsDialog.h" +#include "InputConfigDialog.h" #include "types.h" #include "version.h" @@ -551,6 +552,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actEmuSettings = menu->addAction("Emu settings"); connect(actEmuSettings, &QAction::triggered, this, &MainWindow::onOpenEmuSettings); + + actInputConfig = menu->addAction("Input and hotkeys"); + connect(actInputConfig, &QAction::triggered, this, &MainWindow::onOpenInputConfig); } setMenuBar(menubar); @@ -850,6 +854,19 @@ void MainWindow::onOpenEmuSettings() EmuSettingsDialog::openDlg(this); } +void MainWindow::onOpenInputConfig() +{ + emuThread->emuPause(true); + + InputConfigDialog* dlg = InputConfigDialog::openDlg(this); + connect(dlg, &InputConfigDialog::finished, this, &MainWindow::onInputConfigFinished); +} + +void MainWindow::onInputConfigFinished() +{printf("FARTO\n"); + emuThread->emuUnpause(); +} + int main(int argc, char** argv) { @@ -915,8 +932,8 @@ int main(int argc, char** argv) Config::Load(); - //if (Config::AudioVolume < 0) Config::AudioVolume = 0; - //else if (Config::AudioVolume > 256) Config::AudioVolume = 256; + if (Config::AudioVolume < 0) Config::AudioVolume = 0; + else if (Config::AudioVolume > 256) Config::AudioVolume = 256; // TODO: this should be checked before running anything #if 0 diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index ee0094f0..0324ecf5 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -108,6 +108,8 @@ private slots: void onEmuUnpause(); void onOpenEmuSettings(); + void onOpenInputConfig(); + void onInputConfigFinished(); private: QString loadErrorStr(int error); @@ -126,6 +128,7 @@ private: QAction* actStop; QAction* actEmuSettings; + QAction* actInputConfig; }; #endif // MAIN_H From 7026bb15f6688d4148932a7624baf2f3d5d22d8f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 12:06:25 +0200 Subject: [PATCH 041/105] input dialog progress. --- src/frontend/qt_sdl/InputConfigDialog.cpp | 245 +++++++++++++++++++++- src/frontend/qt_sdl/InputConfigDialog.h | 32 +++ src/frontend/qt_sdl/InputConfigDialog.ui | 11 +- src/frontend/qt_sdl/main.cpp | 4 +- src/frontend/qt_sdl/main.h | 2 +- 5 files changed, 286 insertions(+), 8 deletions(-) diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index f7c0ab29..3b006fd6 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -16,7 +16,9 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ -// +#include +#include +#include #include "types.h" #include "Config.h" @@ -28,13 +30,68 @@ InputConfigDialog* InputConfigDialog::currentDlg = nullptr; +const int dskeyorder[12] = {0, 1, 10, 11, 5, 4, 6, 7, 9, 8, 2, 3}; +const char* dskeylabels[12] = {"A", "B", "X", "Y", "Left", "Right", "Up", "Down", "L", "R", "Select", "Start"}; + +const int hk_addons[] = +{ + HK_SolarSensorIncrease, + HK_SolarSensorDecrease, +}; + +const char* hk_addons_labels[] = +{ + "[Boktai] Sunlight + ", + "[Boktai] Sunlight - ", +}; + +const int hk_general[] = +{ + HK_Pause, + HK_Reset, + HK_FastForward, + HK_FastForwardToggle, + HK_Lid, + HK_Mic, +}; + +const char* hk_general_labels[] = +{ + "Pause/resume", + "Reset", + "Fast forward", + "Toggle FPS limit", + "Close/open lid", + "Microphone", +}; + InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new Ui::InputConfigDialog) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - // + for (int i = 0; i < 12; i++) + { + keypadKeyMap[i] = Config::KeyMapping[dskeyorder[i]]; + keypadJoyMap[i] = Config::JoyMapping[dskeyorder[i]]; + } + + for (int i = 0; i < 2; i++) + { + addonsKeyMap[i] = Config::HKKeyMapping[hk_addons[i]]; + addonsJoyMap[i] = Config::HKJoyMapping[hk_addons[i]]; + } + + for (int i = 0; i < 6; i++) + { + hkGeneralKeyMap[i] = Config::HKKeyMapping[hk_general[i]]; + hkGeneralJoyMap[i] = Config::HKJoyMapping[hk_general[i]]; + } + + populatePage(ui->tabInput, 12, dskeylabels, keypadKeyMap, keypadJoyMap); + populatePage(ui->tabAddons, 2, hk_addons_labels, addonsKeyMap, addonsJoyMap); + populatePage(ui->tabHotkeysGeneral, 6, hk_general_labels, hkGeneralKeyMap, hkGeneralJoyMap); } InputConfigDialog::~InputConfigDialog() @@ -42,6 +99,109 @@ InputConfigDialog::~InputConfigDialog() delete ui; } +void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels, int* keymap, int* joymap) +{ + // kind of a hack + bool ishotkey = (page != ui->tabInput); + + QHBoxLayout* main_layout = new QHBoxLayout(); + + QGroupBox* group; + QGridLayout* group_layout; + + group = new QGroupBox("Keyboard mappings:"); + main_layout->addWidget(group); + group_layout = new QGridLayout(); + group_layout->setSpacing(1); + for (int i = 0; i < num; i++) + { + QLabel* label = new QLabel(QString(labels[i])+":"); + KeyMapButton* btn = new KeyMapButton(nullptr, &keymap[i], ishotkey); + + group_layout->addWidget(label, i, 0); + group_layout->addWidget(btn, i, 1); + } + group_layout->setRowStretch(num, 1); + group->setLayout(group_layout); + group->setMinimumWidth(275); + + group = new QGroupBox("Joystick mappings:"); + main_layout->addWidget(group); + group_layout = new QGridLayout(); + group_layout->setSpacing(1); + for (int i = 0; i < num; i++) + { + QLabel* label = new QLabel(QString(labels[i])+":"); + QPushButton* btn = new QPushButton(); + + group_layout->addWidget(label, i, 0); + group_layout->addWidget(btn, i, 1); + + btn->setText(joyMappingName(joymap[i])); + + //btn->setProperty("mapping", QVariant(&joymap[i])); + //btn->setProperty("isHotkey", QVariant(ishotkey)); + } + group_layout->setRowStretch(num, 1); + group->setLayout(group_layout); + group->setMinimumWidth(275); + + page->setLayout(main_layout); +} + +QString InputConfigDialog::joyMappingName(int id) +{ + if (id < 0) + { + return "None"; + } + + bool hasbtn = ((id & 0xFFFF) != 0xFFFF); + QString str; + + if (hasbtn) + { + if (id & 0x100) + { + int hatnum = ((id >> 4) & 0xF) + 1; + + switch (id & 0xF) + { + case 0x1: str = "Hat %1 up"; break; + case 0x2: str = "Hat %1 right"; break; + case 0x4: str = "Hat %1 down"; break; + case 0x8: str = "Hat %1 left"; break; + } + + str = str.arg(hatnum); + } + else + { + str = QString("Button %1").arg((id & 0xFFFF) + 1); + } + } + else + { + str = ""; + } + + if (id & 0x10000) + { + int axisnum = ((id >> 24) & 0xF) + 1; + + if (hasbtn) str += " / "; + + switch ((id >> 20) & 0xF) + { + case 0: str += QString("Axis %1 +").arg(axisnum); break; + case 1: str += QString("Axis %1 -").arg(axisnum); break; + case 2: str += QString("Trigger %1").arg(axisnum); break; + } + } + + return str; +} + void InputConfigDialog::on_InputConfigDialog_accepted() { closeDlg(); @@ -51,3 +211,84 @@ void InputConfigDialog::on_InputConfigDialog_rejected() { closeDlg(); } + + +KeyMapButton::KeyMapButton(QWidget* parent, int* mapping, bool hotkey) : QPushButton(parent) +{ + this->mapping = mapping; + this->isHotkey = hotkey; + + setCheckable(true); + setText(mappingText()); + + connect(this, &KeyMapButton::clicked, this, &KeyMapButton::onClick); +} + +KeyMapButton::~KeyMapButton() +{ +} + +void KeyMapButton::keyPressEvent(QKeyEvent* event) +{ + if (!isChecked()) return QPushButton::keyPressEvent(event); +printf("KEY PRESSED = %08X %08X | %08X %08X %08X | %08X\n", event->key(), event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode(), Qt::SHIFT); + int key = event->key(); + bool ismod = (key == Qt::Key_Control || + key == Qt::Key_Alt || + key == Qt::Key_Shift || + key == Qt::Key_Meta); + + if (isHotkey) + { + if (ismod) + return; + } + + if (!ismod) + key |= event->modifiers(); + + *mapping = key; + click(); +} + +void KeyMapButton::focusOutEvent(QFocusEvent* event) +{ + if (isChecked()) + { + // if we lost the focus while mapping, consider it 'done' + click(); + } + + QPushButton::focusOutEvent(event); +} + +void KeyMapButton::onClick() +{ + if (isChecked()) + { + setText("[press key]"); + } + else + { + setText(mappingText()); + } +} + +QString KeyMapButton::mappingText() +{ + int key = *mapping; + + switch (key) + { + case -1: return "None"; + + case Qt::Key_Control: return "Ctrl"; + case Qt::Key_Alt: return "Alt"; + case Qt::Key_Shift: return "Shift"; + case Qt::Key_Meta: return "Meta"; + } + + QKeySequence seq(key); + QString ret = seq.toString(); + return ret.replace("&", "&&"); +} diff --git a/src/frontend/qt_sdl/InputConfigDialog.h b/src/frontend/qt_sdl/InputConfigDialog.h index 2af73db0..b2ca3f28 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.h +++ b/src/frontend/qt_sdl/InputConfigDialog.h @@ -20,6 +20,7 @@ #define INPUTCONFIGDIALOG_H #include +#include namespace Ui { class InputConfigDialog; } class InputConfigDialog; @@ -57,7 +58,38 @@ private slots: // private: + void populatePage(QWidget* page, int num, const char** labels, int* keymap, int* joymap); + + QString joyMappingName(int id); + Ui::InputConfigDialog* ui; + + int keypadKeyMap[12], keypadJoyMap[12]; + int addonsKeyMap[2], addonsJoyMap[2]; + int hkGeneralKeyMap[6], hkGeneralJoyMap[6]; +}; + + +class KeyMapButton : public QPushButton +{ + Q_OBJECT + +public: + explicit KeyMapButton(QWidget* parent, int* mapping, bool hotkey); + ~KeyMapButton(); + +protected: + void keyPressEvent(QKeyEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; + +private slots: + void onClick(); + +private: + QString mappingText(); + + int* mapping; + bool isHotkey; }; #endif // INPUTCONFIGDIALOG_H diff --git a/src/frontend/qt_sdl/InputConfigDialog.ui b/src/frontend/qt_sdl/InputConfigDialog.ui index c1422e9b..655da16d 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.ui +++ b/src/frontend/qt_sdl/InputConfigDialog.ui @@ -11,7 +11,7 @@ - TDAH + Input and hotkeys - melonDS @@ -20,11 +20,16 @@ - 1 + 0 - DS input + DS keypad + + + + + Add-ons diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index cd7849df..d6641726 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -862,8 +862,8 @@ void MainWindow::onOpenInputConfig() connect(dlg, &InputConfigDialog::finished, this, &MainWindow::onInputConfigFinished); } -void MainWindow::onInputConfigFinished() -{printf("FARTO\n"); +void MainWindow::onInputConfigFinished(int res) +{ emuThread->emuUnpause(); } diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 0324ecf5..45538755 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -109,7 +109,7 @@ private slots: void onOpenEmuSettings(); void onOpenInputConfig(); - void onInputConfigFinished(); + void onInputConfigFinished(int res); private: QString loadErrorStr(int error); From 7d69699d648b93d76f14024705c4a86f5929ba3d Mon Sep 17 00:00:00 2001 From: StapleButter Date: Tue, 19 May 2020 14:37:54 +0200 Subject: [PATCH 042/105] fix Linux build error --- src/frontend/qt_sdl/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index d6641726..9d4c2747 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -868,6 +868,11 @@ void MainWindow::onInputConfigFinished(int res) } +// FIXME!!!! +#if (!defined(__WIN32__) && !defined(UNIX_PORTABLE)) +#include +#endif + int main(int argc, char** argv) { srand(time(NULL)); From d5f1633019b3cd14d7f5e5fb7d7d193d6bfe67ea Mon Sep 17 00:00:00 2001 From: StapleButter Date: Tue, 19 May 2020 14:41:11 +0200 Subject: [PATCH 043/105] remove LTO --- CMakeLists.txt | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 488da81d..ee021d97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,21 +14,6 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -if (CMAKE_BUILD_TYPE STREQUAL Release) - option(ENABLE_LTO "Enable link-time optimization" ON) -else() - option(ENABLE_LTO "Enable link-time optimization" OFF) -endif() - -if(ENABLE_LTO) - add_compile_options(-O3 -flto) - set(CMAKE_AR "gcc-ar") - set(CMAKE_C_ARCHIVE_CREATE " qcs ") - set(CMAKE_C_ARCHIVE_FINISH true) - set(CMAKE_CXX_ARCHIVE_CREATE " qcs ") - set(CMAKE_CXX_ARCHIVE_FINISH true) -endif() - add_compile_options(-fno-pic) add_link_options(-no-pie) From 9fbf9b997bb950a667d0af4583fd68098a7ed717 Mon Sep 17 00:00:00 2001 From: StapleButter Date: Tue, 19 May 2020 13:28:46 +0200 Subject: [PATCH 044/105] this might be a good idea --- src/frontend/qt_sdl/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 9d4c2747..7b50af47 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1045,6 +1045,7 @@ int main(int argc, char** argv) emuThread->emuStop(); emuThread->wait(); + delete emuThread; //if (Joystick) SDL_JoystickClose(Joystick); if (audioDevice) SDL_CloseAudioDevice(audioDevice); From 2a7027f794267effe651b242956ed669c242e9ca Mon Sep 17 00:00:00 2001 From: StapleButter Date: Tue, 19 May 2020 13:46:31 +0200 Subject: [PATCH 045/105] add AltGr, weak attempt at blocking garbage key names --- src/frontend/qt_sdl/InputConfigDialog.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index 3b006fd6..54251a18 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -235,6 +235,7 @@ printf("KEY PRESSED = %08X %08X | %08X %08X %08X | %08X\n", event->key(), event- int key = event->key(); bool ismod = (key == Qt::Key_Control || key == Qt::Key_Alt || + key == Qt::Key_AltGr || key == Qt::Key_Shift || key == Qt::Key_Meta); @@ -284,11 +285,17 @@ QString KeyMapButton::mappingText() case Qt::Key_Control: return "Ctrl"; case Qt::Key_Alt: return "Alt"; + case Qt::Key_AltGr: return "AltGr"; case Qt::Key_Shift: return "Shift"; case Qt::Key_Meta: return "Meta"; } QKeySequence seq(key); QString ret = seq.toString(); + + // weak attempt at detecting garbage key names + if (ret.length() == 2 && ret[0].unicode() > 0xFF) + return QString("[%1]").arg(key, 8, 16); + return ret.replace("&", "&&"); } From 23cc8c71a2c0ab3389b5208f49a25df0efc05a2e Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 14:15:11 +0200 Subject: [PATCH 046/105] distinguish left/right Ctrl and Shift --- src/frontend/qt_sdl/InputConfigDialog.cpp | 22 +++++++++++++++------- src/frontend/qt_sdl/main.h | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index 54251a18..0ef29bb7 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -24,6 +24,7 @@ #include "Config.h" #include "PlatformConfig.h" +#include "main.h" #include "InputConfigDialog.h" #include "ui_InputConfigDialog.h" @@ -231,7 +232,9 @@ KeyMapButton::~KeyMapButton() void KeyMapButton::keyPressEvent(QKeyEvent* event) { if (!isChecked()) return QPushButton::keyPressEvent(event); -printf("KEY PRESSED = %08X %08X | %08X %08X %08X | %08X\n", event->key(), event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode(), Qt::SHIFT); + + printf("KEY PRESSED = %08X %08X | %08X %08X %08X\n", event->key(), event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode()); + int key = event->key(); bool ismod = (key == Qt::Key_Control || key == Qt::Key_Alt || @@ -247,6 +250,8 @@ printf("KEY PRESSED = %08X %08X | %08X %08X %08X | %08X\n", event->key(), event- if (!ismod) key |= event->modifiers(); + else if (IsRightModKey(event)) + key |= (1<<31); *mapping = key; click(); @@ -279,23 +284,26 @@ QString KeyMapButton::mappingText() { int key = *mapping; + if (key == -1) return "None"; + + QString isright = (key & (1<<31)) ? "Right " : "Left "; + key &= ~(1<<31); + switch (key) { - case -1: return "None"; - - case Qt::Key_Control: return "Ctrl"; + case Qt::Key_Control: return isright + "Ctrl"; case Qt::Key_Alt: return "Alt"; case Qt::Key_AltGr: return "AltGr"; - case Qt::Key_Shift: return "Shift"; + case Qt::Key_Shift: return isright + "Shift"; case Qt::Key_Meta: return "Meta"; } QKeySequence seq(key); QString ret = seq.toString(); - + // weak attempt at detecting garbage key names if (ret.length() == 2 && ret[0].unicode() > 0xFF) return QString("[%1]").arg(key, 8, 16); - + return ret.replace("&", "&&"); } diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 45538755..5d6638c4 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -23,6 +23,7 @@ #include #include #include +#include class EmuThread : public QThread @@ -131,4 +132,24 @@ private: QAction* actInputConfig; }; + +// TODO: MacOS version of this! +// distinguish between left and right modifier keys (Ctrl, Alt, Shift) +// Qt provides no real cross-platform way to do this, so here we go +// for Windows and Linux we can distinguish via scancodes (but both +// provide different scancodes) +#ifdef __WIN32__ +inline bool IsRightModKey(QKeyEvent* event) +{ + quint32 scan = event->nativeScanCode(); + return (scan == 0x11D || scan == 0x138 || scan == 0x36); +} +#else +inline bool IsRightModKey(QKeyEvent* event) +{ + quint32 scan = event->nativeScanCode(); + return (scan == 0x69 || scan == 0x6C || scan == 0x3E); +} +#endif + #endif // MAIN_H From 04d38e5e66cee768e32864b37a5cf37d8109d481 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 14:16:35 +0200 Subject: [PATCH 047/105] axe the default key mappings (not too cross-platform and blargy) --- src/frontend/qt_sdl/PlatformConfig.cpp | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index 1f6a8731..3b4b4aad 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -67,18 +67,18 @@ char LastROMFolder[1024]; ConfigEntry PlatformConfigFile[] = { - {"Key_A", 0, &KeyMapping[0], 32, NULL, 0}, - {"Key_B", 0, &KeyMapping[1], 31, NULL, 0}, - {"Key_Select", 0, &KeyMapping[2], 57, NULL, 0}, - {"Key_Start", 0, &KeyMapping[3], 28, NULL, 0}, - {"Key_Right", 0, &KeyMapping[4], 333, NULL, 0}, - {"Key_Left", 0, &KeyMapping[5], 331, NULL, 0}, - {"Key_Up", 0, &KeyMapping[6], 328, NULL, 0}, - {"Key_Down", 0, &KeyMapping[7], 336, NULL, 0}, - {"Key_R", 0, &KeyMapping[8], 54, NULL, 0}, - {"Key_L", 0, &KeyMapping[9], 86, NULL, 0}, - {"Key_X", 0, &KeyMapping[10], 17, NULL, 0}, - {"Key_Y", 0, &KeyMapping[11], 30, NULL, 0}, + {"Key_A", 0, &KeyMapping[0], -1, NULL, 0}, + {"Key_B", 0, &KeyMapping[1], -1, NULL, 0}, + {"Key_Select", 0, &KeyMapping[2], -1, NULL, 0}, + {"Key_Start", 0, &KeyMapping[3], -1, NULL, 0}, + {"Key_Right", 0, &KeyMapping[4], -1, NULL, 0}, + {"Key_Left", 0, &KeyMapping[5], -1, NULL, 0}, + {"Key_Up", 0, &KeyMapping[6], -1, NULL, 0}, + {"Key_Down", 0, &KeyMapping[7], -1, NULL, 0}, + {"Key_R", 0, &KeyMapping[8], -1, NULL, 0}, + {"Key_L", 0, &KeyMapping[9], -1, NULL, 0}, + {"Key_X", 0, &KeyMapping[10], -1, NULL, 0}, + {"Key_Y", 0, &KeyMapping[11], -1, NULL, 0}, {"Joy_A", 0, &JoyMapping[0], -1, NULL, 0}, {"Joy_B", 0, &JoyMapping[1], -1, NULL, 0}, @@ -93,14 +93,14 @@ ConfigEntry PlatformConfigFile[] = {"Joy_X", 0, &JoyMapping[10], -1, NULL, 0}, {"Joy_Y", 0, &JoyMapping[11], -1, NULL, 0}, - {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0}, - {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0}, - {"HKKey_Pause", 0, &HKKeyMapping[HK_Pause], -1, NULL, 0}, - {"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0}, - {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0}, - {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, - {"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], 0x4B, NULL, 0}, - {"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], 0x4D, NULL, 0}, + {"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], -1, NULL, 0}, + {"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], -1, NULL, 0}, + {"HKKey_Pause", 0, &HKKeyMapping[HK_Pause], -1, NULL, 0}, + {"HKKey_Reset", 0, &HKKeyMapping[HK_Reset], -1, NULL, 0}, + {"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], -1, NULL, 0}, + {"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, + {"HKKey_SolarSensorDecrease", 0, &HKKeyMapping[HK_SolarSensorDecrease], -1, NULL, 0}, + {"HKKey_SolarSensorIncrease", 0, &HKKeyMapping[HK_SolarSensorIncrease], -1, NULL, 0}, {"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0}, {"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0}, From 4b038f5d370c961803666f418ebfeb775cfa2d2a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 14:24:57 +0200 Subject: [PATCH 048/105] re-add old special keys for mapping (Esc=cancel, Backspace=clear) --- src/frontend/qt_sdl/InputConfigDialog.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index 0ef29bb7..93204aa5 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -236,12 +236,19 @@ void KeyMapButton::keyPressEvent(QKeyEvent* event) printf("KEY PRESSED = %08X %08X | %08X %08X %08X\n", event->key(), event->modifiers(), event->nativeVirtualKey(), event->nativeModifiers(), event->nativeScanCode()); int key = event->key(); + int mod = event->modifiers(); bool ismod = (key == Qt::Key_Control || key == Qt::Key_Alt || key == Qt::Key_AltGr || key == Qt::Key_Shift || key == Qt::Key_Meta); + if (!mod) + { + if (key == Qt::Key_Escape) { click(); return; } + if (key == Qt::Key_Backspace) { *mapping = -1; click(); return; } + } + if (isHotkey) { if (ismod) @@ -249,7 +256,7 @@ void KeyMapButton::keyPressEvent(QKeyEvent* event) } if (!ismod) - key |= event->modifiers(); + key |= mod; else if (IsRightModKey(event)) key |= (1<<31); From 920ff9778d3fbdd18576ab473cca6212ee387cb1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 15:11:34 +0200 Subject: [PATCH 049/105] blarg --- src/Config.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Config.cpp b/src/Config.cpp index 7604785f..84c83d8e 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -90,7 +90,8 @@ void Load() while (!feof(f)) { fgets(linebuf, 1024, f); - int ret = sscanf(linebuf, "%32[A-Za-z_0-9]=%[^\t\n]", entryname, entryval); + int ret = sscanf(linebuf, "%31[A-Za-z_0-9]=%[^\t\n]", entryname, entryval); + entryname[31] = '\0'; if (ret < 2) continue; ConfigEntry* entry = &ConfigFile[0]; From 34506ff2bb1be880cf260e0c1b09efede14ac0d8 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 20:48:52 +0200 Subject: [PATCH 050/105] actually complete the input config dialog --- src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/Input.cpp | 119 +++++++++ src/frontend/qt_sdl/Input.h | 40 +++ src/frontend/qt_sdl/InputConfigDialog.cpp | 301 +++++++++++++++++----- src/frontend/qt_sdl/InputConfigDialog.h | 32 ++- src/frontend/qt_sdl/main.cpp | 15 +- src/frontend/qt_sdl/main.h | 21 -- 7 files changed, 434 insertions(+), 95 deletions(-) create mode 100644 src/frontend/qt_sdl/Input.cpp create mode 100644 src/frontend/qt_sdl/Input.h diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index da3bb1dc..42cf9128 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -4,6 +4,7 @@ SET(SOURCES_QT_SDL main.cpp EmuSettingsDialog.cpp InputConfigDialog.cpp + Input.cpp Platform.cpp PlatformConfig.cpp diff --git a/src/frontend/qt_sdl/Input.cpp b/src/frontend/qt_sdl/Input.cpp new file mode 100644 index 00000000..7caf24a1 --- /dev/null +++ b/src/frontend/qt_sdl/Input.cpp @@ -0,0 +1,119 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include + +#include "Input.h" +#include "PlatformConfig.h" + + +namespace Input +{ + +int JoystickID; +SDL_Joystick* Joystick = nullptr; + +u32 KeyInputMask, JoyInputMask; +u32 KeyHotkeyMask, JoyHotkeyMask; +u32 HotkeyMask, LastHotkeyMask; +u32 HotkeyPress, HotkeyRelease; + + +void OpenJoystick() +{ + if (Joystick) SDL_JoystickClose(Joystick); + + int num = SDL_NumJoysticks(); + if (num < 1) + { + Joystick = nullptr; + return; + } + + if (JoystickID >= num) + JoystickID = 0; + + Joystick = SDL_JoystickOpen(JoystickID); +} + +void CloseJoystick() +{ + if (Joystick) + { + SDL_JoystickClose(Joystick); + Joystick = nullptr; + } +} + + +void Process() +{ + SDL_JoystickUpdate(); + + if (Joystick) + { + if (!SDL_JoystickGetAttached(Joystick)) + { + SDL_JoystickClose(Joystick); + Joystick = NULL; + } + } + if (!Joystick && (SDL_NumJoysticks() > 0)) + { + JoystickID = Config::JoystickID; + OpenJoystick(); + } + + /*JoyInputMask = 0xFFF; + for (int i = 0; i < 12; i++) + if (JoystickButtonDown(Config::JoyMapping[i])) + JoyInputMask &= ~(1<nativeScanCode(); + return (scan == 0x11D || scan == 0x138 || scan == 0x36); +} +#else +bool IsRightModKey(QKeyEvent* event) +{ + quint32 scan = event->nativeScanCode(); + return (scan == 0x69 || scan == 0x6C || scan == 0x3E); +} +#endif + +} diff --git a/src/frontend/qt_sdl/Input.h b/src/frontend/qt_sdl/Input.h new file mode 100644 index 00000000..24ec3a79 --- /dev/null +++ b/src/frontend/qt_sdl/Input.h @@ -0,0 +1,40 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef INPUT_H +#define INPUT_H + +#include "types.h" + +namespace Input +{ + +extern int JoystickID; +extern SDL_Joystick* Joystick; + +// set joystickID before calling openJoystick() +void OpenJoystick(); +void CloseJoystick(); + +void Process(); + +bool IsRightModKey(QKeyEvent* event); + +} + +#endif // INPUT_H diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index 93204aa5..2c0afc44 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -20,11 +20,13 @@ #include #include +#include + #include "types.h" #include "Config.h" #include "PlatformConfig.h" -#include "main.h" +#include "Input.h" #include "InputConfigDialog.h" #include "ui_InputConfigDialog.h" @@ -93,6 +95,22 @@ InputConfigDialog::InputConfigDialog(QWidget* parent) : QDialog(parent), ui(new populatePage(ui->tabInput, 12, dskeylabels, keypadKeyMap, keypadJoyMap); populatePage(ui->tabAddons, 2, hk_addons_labels, addonsKeyMap, addonsJoyMap); populatePage(ui->tabHotkeysGeneral, 6, hk_general_labels, hkGeneralKeyMap, hkGeneralJoyMap); + + int njoy = SDL_NumJoysticks(); + if (njoy > 0) + { + for (int i = 0; i < njoy; i++) + { + const char* name = SDL_JoystickNameForIndex(i); + ui->cbxJoystick->addItem(QString(name)); + } + ui->cbxJoystick->setCurrentIndex(Input::JoystickID); + } + else + { + ui->cbxJoystick->addItem("(no joysticks available)"); + ui->cbxJoystick->setEnabled(false); + } } InputConfigDialog::~InputConfigDialog() @@ -117,7 +135,7 @@ void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels for (int i = 0; i < num; i++) { QLabel* label = new QLabel(QString(labels[i])+":"); - KeyMapButton* btn = new KeyMapButton(nullptr, &keymap[i], ishotkey); + KeyMapButton* btn = new KeyMapButton(&keymap[i], ishotkey); group_layout->addWidget(label, i, 0); group_layout->addWidget(btn, i, 1); @@ -133,15 +151,10 @@ void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels for (int i = 0; i < num; i++) { QLabel* label = new QLabel(QString(labels[i])+":"); - QPushButton* btn = new QPushButton(); + JoyMapButton* btn = new JoyMapButton(&joymap[i], ishotkey); group_layout->addWidget(label, i, 0); group_layout->addWidget(btn, i, 1); - - btn->setText(joyMappingName(joymap[i])); - - //btn->setProperty("mapping", QVariant(&joymap[i])); - //btn->setProperty("isHotkey", QVariant(ishotkey)); } group_layout->setRowStretch(num, 1); group->setLayout(group_layout); @@ -150,71 +163,48 @@ void InputConfigDialog::populatePage(QWidget* page, int num, const char** labels page->setLayout(main_layout); } -QString InputConfigDialog::joyMappingName(int id) -{ - if (id < 0) - { - return "None"; - } - - bool hasbtn = ((id & 0xFFFF) != 0xFFFF); - QString str; - - if (hasbtn) - { - if (id & 0x100) - { - int hatnum = ((id >> 4) & 0xF) + 1; - - switch (id & 0xF) - { - case 0x1: str = "Hat %1 up"; break; - case 0x2: str = "Hat %1 right"; break; - case 0x4: str = "Hat %1 down"; break; - case 0x8: str = "Hat %1 left"; break; - } - - str = str.arg(hatnum); - } - else - { - str = QString("Button %1").arg((id & 0xFFFF) + 1); - } - } - else - { - str = ""; - } - - if (id & 0x10000) - { - int axisnum = ((id >> 24) & 0xF) + 1; - - if (hasbtn) str += " / "; - - switch ((id >> 20) & 0xF) - { - case 0: str += QString("Axis %1 +").arg(axisnum); break; - case 1: str += QString("Axis %1 -").arg(axisnum); break; - case 2: str += QString("Trigger %1").arg(axisnum); break; - } - } - - return str; -} - void InputConfigDialog::on_InputConfigDialog_accepted() { + for (int i = 0; i < 12; i++) + { + Config::KeyMapping[dskeyorder[i]] = keypadKeyMap[i]; + Config::JoyMapping[dskeyorder[i]] = keypadJoyMap[i]; + } + + for (int i = 0; i < 2; i++) + { + Config::HKKeyMapping[hk_addons[i]] = addonsKeyMap[i]; + Config::HKJoyMapping[hk_addons[i]] = addonsJoyMap[i]; + } + + for (int i = 0; i < 6; i++) + { + Config::HKKeyMapping[hk_general[i]] = hkGeneralKeyMap[i]; + Config::HKJoyMapping[hk_general[i]] = hkGeneralJoyMap[i]; + } + + Config::JoystickID = Input::JoystickID; + Config::Save(); + closeDlg(); } void InputConfigDialog::on_InputConfigDialog_rejected() { + Input::JoystickID = Config::JoystickID; + Input::OpenJoystick(); + closeDlg(); } +void InputConfigDialog::on_cbxJoystick_currentIndexChanged(int id) +{ + Input::JoystickID = id; + Input::OpenJoystick(); +} -KeyMapButton::KeyMapButton(QWidget* parent, int* mapping, bool hotkey) : QPushButton(parent) + +KeyMapButton::KeyMapButton(int* mapping, bool hotkey) : QPushButton() { this->mapping = mapping; this->isHotkey = hotkey; @@ -257,7 +247,7 @@ void KeyMapButton::keyPressEvent(QKeyEvent* event) if (!ismod) key |= mod; - else if (IsRightModKey(event)) + else if (Input::IsRightModKey(event)) key |= (1<<31); *mapping = key; @@ -314,3 +304,188 @@ QString KeyMapButton::mappingText() return ret.replace("&", "&&"); } + + +JoyMapButton::JoyMapButton(int* mapping, bool hotkey) : QPushButton() +{ + this->mapping = mapping; + this->isHotkey = hotkey; + + setCheckable(true); + setText(mappingText()); + + connect(this, &JoyMapButton::clicked, this, &JoyMapButton::onClick); + + timerID = 0; +} + +JoyMapButton::~JoyMapButton() +{ +} + +void JoyMapButton::keyPressEvent(QKeyEvent* event) +{ + if (!isChecked()) return QPushButton::keyPressEvent(event); + + int key = event->key(); + int mod = event->modifiers(); + + if (!mod) + { + if (key == Qt::Key_Escape) { click(); return; } + if (key == Qt::Key_Backspace) { *mapping = -1; click(); return; } + } +} + +void JoyMapButton::focusOutEvent(QFocusEvent* event) +{ + if (isChecked()) + { + // if we lost the focus while mapping, consider it 'done' + click(); + } + + QPushButton::focusOutEvent(event); +} + +void JoyMapButton::timerEvent(QTimerEvent* event) +{ + SDL_Joystick* joy = Input::Joystick; + if (!joy) { click(); return; } + if (!SDL_JoystickGetAttached(joy)) { click(); return; } + + int oldmap; + if (*mapping == -1) oldmap = 0xFFFF; + else oldmap = *mapping; + + int nbuttons = SDL_JoystickNumButtons(joy); + for (int i = 0; i < nbuttons; i++) + { + if (SDL_JoystickGetButton(joy, i)) + { + *mapping = (oldmap & 0xFFFF0000) | i; + click(); + return; + } + } + + int nhats = SDL_JoystickNumHats(joy); + if (nhats > 16) nhats = 16; + for (int i = 0; i < nhats; i++) + { + Uint8 blackhat = SDL_JoystickGetHat(joy, i); + if (blackhat) + { + if (blackhat & 0x1) blackhat = 0x1; + else if (blackhat & 0x2) blackhat = 0x2; + else if (blackhat & 0x4) blackhat = 0x4; + else blackhat = 0x8; + + *mapping = (oldmap & 0xFFFF0000) | 0x100 | blackhat | (i << 4); + click(); + return; + } + } + + int naxes = SDL_JoystickNumAxes(joy); + if (naxes > 16) naxes = 16; + for (int i = 0; i < naxes; i++) + { + Sint16 axisval = SDL_JoystickGetAxis(joy, i); + int diff = abs(axisval - axesRest[i]); + + if (axesRest[i] < -16384 && axisval >= 0) + { + *mapping = (oldmap & 0xFFFF) | 0x10000 | (2 << 20) | (i << 24); + click(); + return; + } + else if (diff > 16384) + { + int axistype; + if (axisval > 0) axistype = 0; + else axistype = 1; + + *mapping = (oldmap & 0xFFFF) | 0x10000 | (axistype << 20) | (i << 24); + click(); + return; + } + } +} + +void JoyMapButton::onClick() +{ + if (isChecked()) + { + setText("[press button/axis]"); + timerID = startTimer(50); + + memset(axesRest, 0, sizeof(axesRest)); + if (Input::Joystick && SDL_JoystickGetAttached(Input::Joystick)) + { + int naxes = SDL_JoystickNumAxes(Input::Joystick); + if (naxes > 16) naxes = 16; + for (int a = 0; a < naxes; a++) + { + axesRest[a] = SDL_JoystickGetAxis(Input::Joystick, a); + } + } + } + else + { + setText(mappingText()); + if (timerID) { killTimer(timerID); timerID = 0; } + } +} + +QString JoyMapButton::mappingText() +{ + int id = *mapping; + + if (id == -1) return "None"; + + bool hasbtn = ((id & 0xFFFF) != 0xFFFF); + QString str; + + if (hasbtn) + { + if (id & 0x100) + { + int hatnum = ((id >> 4) & 0xF) + 1; + + switch (id & 0xF) + { + case 0x1: str = "Hat %1 up"; break; + case 0x2: str = "Hat %1 right"; break; + case 0x4: str = "Hat %1 down"; break; + case 0x8: str = "Hat %1 left"; break; + } + + str = str.arg(hatnum); + } + else + { + str = QString("Button %1").arg((id & 0xFFFF) + 1); + } + } + else + { + str = ""; + } + + if (id & 0x10000) + { + int axisnum = ((id >> 24) & 0xF) + 1; + + if (hasbtn) str += " / "; + + switch ((id >> 20) & 0xF) + { + case 0: str += QString("Axis %1 +").arg(axisnum); break; + case 1: str += QString("Axis %1 -").arg(axisnum); break; + case 2: str += QString("Trigger %1").arg(axisnum); break; + } + } + + return str; +} diff --git a/src/frontend/qt_sdl/InputConfigDialog.h b/src/frontend/qt_sdl/InputConfigDialog.h index b2ca3f28..82e37bc3 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.h +++ b/src/frontend/qt_sdl/InputConfigDialog.h @@ -55,13 +55,11 @@ private slots: void on_InputConfigDialog_accepted(); void on_InputConfigDialog_rejected(); - // + void on_cbxJoystick_currentIndexChanged(int id); private: void populatePage(QWidget* page, int num, const char** labels, int* keymap, int* joymap); - QString joyMappingName(int id); - Ui::InputConfigDialog* ui; int keypadKeyMap[12], keypadJoyMap[12]; @@ -75,7 +73,7 @@ class KeyMapButton : public QPushButton Q_OBJECT public: - explicit KeyMapButton(QWidget* parent, int* mapping, bool hotkey); + explicit KeyMapButton(int* mapping, bool hotkey); ~KeyMapButton(); protected: @@ -92,4 +90,30 @@ private: bool isHotkey; }; +class JoyMapButton : public QPushButton +{ + Q_OBJECT + +public: + explicit JoyMapButton(int* mapping, bool hotkey); + ~JoyMapButton(); + +protected: + void keyPressEvent(QKeyEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; + void timerEvent(QTimerEvent* event) override; + +private slots: + void onClick(); + +private: + QString mappingText(); + + int* mapping; + bool isHotkey; + + int timerID; + int axesRest[16]; +}; + #endif // INPUTCONFIGDIALOG_H diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 7b50af47..8fe776ec 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -27,10 +27,12 @@ #include #include #include +#include #include #include "main.h" +#include "Input.h" #include "EmuSettingsDialog.h" #include "InputConfigDialog.h" @@ -136,12 +138,6 @@ void EmuThread::run() } /*Touching = false; - KeyInputMask = 0xFFF; - JoyInputMask = 0xFFF; - KeyHotkeyMask = 0; - JoyHotkeyMask = 0; - HotkeyMask = 0; - LastHotkeyMask = 0; LidStatus = false;*/ u32 nframes = 0; @@ -154,6 +150,7 @@ void EmuThread::run() while (EmuRunning != 0) { + Input::Process(); /*ProcessInput(); if (HotkeyPressed(HK_FastForwardToggle)) @@ -999,6 +996,9 @@ int main(int argc, char** argv) Frontend::Init_ROM(); Frontend::Init_Audio(audioFreq); + Input::JoystickID = Config::JoystickID; + Input::OpenJoystick(); + mainWindow = new MainWindow(); mainWindow->show(); @@ -1047,7 +1047,8 @@ int main(int argc, char** argv) emuThread->wait(); delete emuThread; - //if (Joystick) SDL_JoystickClose(Joystick); + Input::CloseJoystick(); + if (audioDevice) SDL_CloseAudioDevice(audioDevice); //if (MicDevice) SDL_CloseAudioDevice(MicDevice); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 5d6638c4..45538755 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -23,7 +23,6 @@ #include #include #include -#include class EmuThread : public QThread @@ -132,24 +131,4 @@ private: QAction* actInputConfig; }; - -// TODO: MacOS version of this! -// distinguish between left and right modifier keys (Ctrl, Alt, Shift) -// Qt provides no real cross-platform way to do this, so here we go -// for Windows and Linux we can distinguish via scancodes (but both -// provide different scancodes) -#ifdef __WIN32__ -inline bool IsRightModKey(QKeyEvent* event) -{ - quint32 scan = event->nativeScanCode(); - return (scan == 0x11D || scan == 0x138 || scan == 0x36); -} -#else -inline bool IsRightModKey(QKeyEvent* event) -{ - quint32 scan = event->nativeScanCode(); - return (scan == 0x69 || scan == 0x6C || scan == 0x3E); -} -#endif - #endif // MAIN_H From 9df8d91bdc12ab2e65569e26dc7c57246e384a8f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 21:34:24 +0200 Subject: [PATCH 051/105] keep the ugliness confined in Platform.cpp --- src/Platform.h | 3 ++ src/frontend/qt_sdl/Platform.cpp | 49 +++++++++++++++++++++++++++++++- src/frontend/qt_sdl/main.cpp | 47 ++---------------------------- 3 files changed, 53 insertions(+), 46 deletions(-) diff --git a/src/Platform.h b/src/Platform.h index b6effdc4..fea98dd5 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -24,6 +24,9 @@ namespace Platform { +void Init(int argc, char** argv); +void DeInit(); + void StopEmu(); // fopen() wrappers diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index fea9166c..6a5b4663 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -53,7 +53,7 @@ #endif -extern char* EmuDirectory; +char* EmuDirectory; void Stop(bool internal); @@ -84,6 +84,53 @@ u8 PacketBuffer[2048]; #define NIFI_VER 1 +void Init(int argc, char** argv) +{ +#if defined(__WIN32__) || defined(UNIX_PORTABLE) + if (argc > 0 && strlen(argv[0]) > 0) + { + int len = strlen(argv[0]); + while (len > 0) + { + if (argv[0][len] == '/') break; + if (argv[0][len] == '\\') break; + len--; + } + if (len > 0) + { + EmuDirectory = new char[len+1]; + strncpy(EmuDirectory, argv[0], len); + EmuDirectory[len] = '\0'; + } + else + { + EmuDirectory = new char[2]; + strcpy(EmuDirectory, "."); + } + } + else + { + EmuDirectory = new char[2]; + strcpy(EmuDirectory, "."); + } +#else + const char* confdir = g_get_user_config_dir(); + const char* confname = "/melonDS"; + int cdlen = strlen(confdir); + int cnlen = strlen(confname); + EmuDirectory = new char[cdlen + cnlen + 1]; + strncpy(&EmuDirectory[0], confdir, cdlen); + strncpy(&EmuDirectory[cdlen], confname, cnlen); + EmuDirectory[cdlen+cnlen] = '\0'; +#endif +} + +void DeInit() +{ + delete[] EmuDirectory; +} + + void StopEmu() { //Stop(true); diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 8fe776ec..a68f9334 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -54,8 +54,6 @@ // TODO: uniform variable spelling -char* EmuDirectory; - bool RunningSomething; MainWindow* mainWindow; @@ -865,11 +863,6 @@ void MainWindow::onInputConfigFinished(int res) } -// FIXME!!!! -#if (!defined(__WIN32__) && !defined(UNIX_PORTABLE)) -#include -#endif - int main(int argc, char** argv) { srand(time(NULL)); @@ -877,43 +870,7 @@ int main(int argc, char** argv) printf("melonDS " MELONDS_VERSION "\n"); printf(MELONDS_URL "\n"); -#if defined(__WIN32__) || defined(UNIX_PORTABLE) - if (argc > 0 && strlen(argv[0]) > 0) - { - int len = strlen(argv[0]); - while (len > 0) - { - if (argv[0][len] == '/') break; - if (argv[0][len] == '\\') break; - len--; - } - if (len > 0) - { - EmuDirectory = new char[len+1]; - strncpy(EmuDirectory, argv[0], len); - EmuDirectory[len] = '\0'; - } - else - { - EmuDirectory = new char[2]; - strcpy(EmuDirectory, "."); - } - } - else - { - EmuDirectory = new char[2]; - strcpy(EmuDirectory, "."); - } -#else - const char* confdir = g_get_user_config_dir(); - const char* confname = "/melonDS"; - int cdlen = strlen(confdir); - int cnlen = strlen(confname); - EmuDirectory = new char[cdlen + cnlen + 1]; - strncpy(&EmuDirectory[0], confdir, cdlen); - strncpy(&EmuDirectory[cdlen], confname, cnlen); - EmuDirectory[cdlen+cnlen] = '\0'; -#endif + Platform::Init(argc, argv); QApplication melon(argc, argv); @@ -1060,7 +1017,7 @@ int main(int argc, char** argv) Config::Save(); SDL_Quit(); - delete[] EmuDirectory; + Platform::DeInit(); return ret; } From b262313816b9fac581353f74dd71e1dde1f23013 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 22:22:21 +0200 Subject: [PATCH 052/105] actually hook up input to the core also unbotch CMakeLists.txt --- CMakeLists.txt | 8 +++ src/frontend/qt_sdl/Input.cpp | 124 +++++++++++++++++++++++++++++++++- src/frontend/qt_sdl/Input.h | 7 ++ src/frontend/qt_sdl/main.cpp | 14 +++- src/frontend/qt_sdl/main.h | 1 + 5 files changed, 150 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee021d97..e640a487 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,14 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() +if (CMAKE_BUILD_TYPE STREQUAL Debug) + add_compile_options(-Og) +endif() + +if (CMAKE_BUILD_TYPE STREQUAL Release) + add_compile_options(-O3) +endif() + add_compile_options(-fno-pic) add_link_options(-no-pie) diff --git a/src/frontend/qt_sdl/Input.cpp b/src/frontend/qt_sdl/Input.cpp index 7caf24a1..d60271cb 100644 --- a/src/frontend/qt_sdl/Input.cpp +++ b/src/frontend/qt_sdl/Input.cpp @@ -34,6 +34,21 @@ u32 KeyHotkeyMask, JoyHotkeyMask; u32 HotkeyMask, LastHotkeyMask; u32 HotkeyPress, HotkeyRelease; +u32 InputMask; + + +void Init() +{ + KeyInputMask = 0xFFF; + JoyInputMask = 0xFFF; + InputMask = 0xFFF; + + KeyHotkeyMask = 0; + JoyHotkeyMask = 0; + HotkeyMask = 0; + LastHotkeyMask = 0; +} + void OpenJoystick() { @@ -62,6 +77,109 @@ void CloseJoystick() } +int GetEventKeyVal(QKeyEvent* event) +{ + int key = event->key(); + int mod = event->modifiers(); + bool ismod = (key == Qt::Key_Control || + key == Qt::Key_Alt || + key == Qt::Key_AltGr || + key == Qt::Key_Shift || + key == Qt::Key_Meta); + + if (!ismod) + key |= mod; + else if (Input::IsRightModKey(event)) + key |= (1<<31); + + return key; +} + +void KeyPress(QKeyEvent* event) +{ + int keyHK = GetEventKeyVal(event); + int keyKP = keyHK & ~event->modifiers(); + + for (int i = 0; i < 12; i++) + if (keyKP == Config::KeyMapping[i]) + KeyInputMask &= ~(1<modifiers(); + + for (int i = 0; i < 12; i++) + if (keyKP == Config::KeyMapping[i]) + KeyInputMask |= (1<> 4) & 0xF; + int hatdir = val & 0xF; + Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum); + + bool pressed = false; + if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP); + else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN); + else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT); + else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT); + + if (pressed) return true; + } + else + { + int btnnum = val & 0xFFFF; + Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum); + + if (btnval) return true; + } + } + + if (val & 0x10000) + { + int axisnum = (val >> 24) & 0xF; + int axisdir = (val >> 20) & 0xF; + Sint16 axisval = SDL_JoystickGetAxis(Joystick, axisnum); + + switch (axisdir) + { + case 0: // positive + if (axisval > 16384) return true; + break; + + case 1: // negative + if (axisval < -16384) return true; + break; + + case 2: // trigger + if (axisval > 0) return true; + break; + } + } + + return false; +} + void Process() { SDL_JoystickUpdate(); @@ -80,11 +198,13 @@ void Process() OpenJoystick(); } - /*JoyInputMask = 0xFFF; + JoyInputMask = 0xFFF; for (int i = 0; i < 12; i++) if (JoystickButtonDown(Config::JoyMapping[i])) JoyInputMask &= ~(1<key(), event->nativeScanCode(), event->modifiers(), event->nativeModifiers()); + if (event->isAutoRepeat()) return; + + Input::KeyPress(event); +} + +void MainWindow::keyReleaseEvent(QKeyEvent* event) +{ + if (event->isAutoRepeat()) return; + + Input::KeyRelease(event); } diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 45538755..a3125cc3 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -87,6 +87,7 @@ public: protected: void keyPressEvent(QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; private slots: void onOpenFile(); From 95f9698077fe50d2567aacd8728ff2625f88f228 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 22:37:48 +0200 Subject: [PATCH 053/105] add back some hotkeys. remove some legacy cruft from NDS.cpp. --- src/NDS.cpp | 18 ++++++------- src/NDS.h | 3 +-- src/frontend/qt_sdl/Input.cpp | 5 ++++ src/frontend/qt_sdl/Input.h | 4 +++ src/frontend/qt_sdl/main.cpp | 48 ++++++++++++++++------------------- 5 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index 745ed28b..e89aa669 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -951,23 +951,15 @@ void CancelEvent(u32 id) } -void PressKey(u32 key) -{ - KeyInput &= ~(1 << key); -} - -void ReleaseKey(u32 key) -{ - KeyInput |= (1 << key); -} - void TouchScreen(u16 x, u16 y) { + KeyInput &= ~(1<<22); SPI_TSC::SetTouchCoords(x, y); } void ReleaseScreen() { + KeyInput |= (1<<22); SPI_TSC::SetTouchCoords(0x000, 0xFFF); } @@ -981,6 +973,12 @@ void SetKeyMask(u32 mask) KeyInput |= key_lo | (key_hi << 16); } +bool IsLidClosed() +{ + if (KeyInput & (1<<23)) return true; + return false; +} + void SetLidClosed(bool closed) { if (closed) diff --git a/src/NDS.h b/src/NDS.h index c7b455ee..daeadc44 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -142,13 +142,12 @@ void RelocateSave(const char* path, bool write); u32 RunFrame(); -void PressKey(u32 key); -void ReleaseKey(u32 key); void TouchScreen(u16 x, u16 y); void ReleaseScreen(); void SetKeyMask(u32 mask); +bool IsLidClosed(); void SetLidClosed(bool closed); void MicInputFrame(s16* data, int samples); diff --git a/src/frontend/qt_sdl/Input.cpp b/src/frontend/qt_sdl/Input.cpp index d60271cb..84d20adf 100644 --- a/src/frontend/qt_sdl/Input.cpp +++ b/src/frontend/qt_sdl/Input.cpp @@ -217,6 +217,11 @@ void Process() } +bool HotkeyDown(int id) { return HotkeyMask & (1< 0) GBACart_SolarSensor::LightLevel--; - char msg[64]; - sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - OSD::AddMessage(0, msg); + //char msg[64]; + //sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + //OSD::AddMessage(0, msg); } - if (HotkeyPressed(HK_SolarSensorIncrease)) + if (Input::HotkeyPressed(HK_SolarSensorIncrease)) { if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; - char msg[64]; - sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - OSD::AddMessage(0, msg); + //char msg[64]; + //sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + //OSD::AddMessage(0, msg); } - }*/ + } if (EmuRunning == 1) { @@ -186,14 +184,13 @@ void EmuThread::run() // process input and hotkeys NDS::SetKeyMask(Input::InputMask); - /*NDS::SetKeyMask(KeyInputMask & JoyInputMask); - if (HotkeyPressed(HK_Lid)) + if (Input::HotkeyPressed(HK_Lid)) { - LidStatus = !LidStatus; - NDS::SetLidClosed(LidStatus); - OSD::AddMessage(0, LidStatus ? "Lid closed" : "Lid opened"); - }*/ + bool lid = !NDS::IsLidClosed(); + NDS::SetLidClosed(lid); + //OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened"); + } // microphone input /*FeedMicInput(); @@ -250,8 +247,7 @@ void EmuThread::run() uiAreaQueueRedrawAll(MainDrawArea);*/ mainWindow->update(); - bool fastforward = false; - //bool fastforward = HotkeyDown(HK_FastForward); + bool fastforward = Input::HotkeyDown(HK_FastForward); if (Config::AudioSync && (!fastforward) && audioDevice) { From 68a7865096a17b7a10a9dc521c99c7eb042582ec Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 19 May 2020 22:57:15 +0200 Subject: [PATCH 054/105] basic touchscreen support --- src/frontend/qt_sdl/main.cpp | 42 +++++++++++++++++++++++++++++++++--- src/frontend/qt_sdl/main.h | 3 +++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 67ac92c3..3b0b35d6 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -410,6 +410,8 @@ MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) { screen[0] = new QImage(256, 192, QImage::Format_RGB32); screen[1] = new QImage(256, 192, QImage::Format_RGB32); + + touching = false; } MainWindowPanel::~MainWindowPanel() @@ -441,25 +443,59 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) } +void MainWindowPanel::transformTSCoords(int& x, int& y) +{ + // TODO: actual screen de-transform taking screen layout/rotation/etc into account + + y -= 192; + + // clamp to screen range + if (x < 0) x = 0; + else if (x > 255) x = 255; + if (y < 0) y = 0; + else if (y > 191) y = 191; +} + void MainWindowPanel::mousePressEvent(QMouseEvent* event) { event->accept(); + if (event->button() != Qt::LeftButton) return; - printf("mouse press %d,%d\n", event->pos().x(), event->pos().y()); + int x = event->pos().x(); + int y = event->pos().y(); + + if (x >= 0 && x < 256 && y >= 192 && y < 384) + { + touching = true; + + transformTSCoords(x, y); + NDS::TouchScreen(x, y); + } } void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event) { event->accept(); + if (event->button() != Qt::LeftButton) return; - printf("mouse release %d,%d\n", event->pos().x(), event->pos().y()); + if (touching) + { + touching = false; + NDS::ReleaseScreen(); + } } void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) { event->accept(); + if (!(event->buttons() & Qt::LeftButton)) return; + if (!touching) return; - printf("mouse move %d,%d %08X\n", event->pos().x(), event->pos().y(), event->buttons()); + int x = event->pos().x(); + int y = event->pos().y(); + + transformTSCoords(x, y); + NDS::TouchScreen(x, y); } diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index a3125cc3..54437806 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -74,6 +74,9 @@ protected: private: QImage* screen[2]; + bool touching; + + void transformTSCoords(int& x, int& y); }; From 34133ef75c8f6f735604d7368a79a54724f06b99 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 01:09:58 +0200 Subject: [PATCH 055/105] make it able to map the Tab key --- src/NDSCart.cpp | 1 + src/frontend/qt_sdl/InputConfigDialog.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 585eadf3..8ced842f 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -903,6 +903,7 @@ bool LoadROM(const char* path, const char* sram, bool direct) { // TODO: streaming mode? for really big ROMs or systems with limited RAM // for now we're lazy + // also TODO: validate what we're loading!! FILE* f = Platform::OpenFile(path, "rb"); if (!f) diff --git a/src/frontend/qt_sdl/InputConfigDialog.h b/src/frontend/qt_sdl/InputConfigDialog.h index 82e37bc3..de57414b 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.h +++ b/src/frontend/qt_sdl/InputConfigDialog.h @@ -80,6 +80,8 @@ protected: void keyPressEvent(QKeyEvent* event) override; void focusOutEvent(QFocusEvent* event) override; + bool focusNextPrevChild(bool next) override { return false; } + private slots: void onClick(); @@ -103,6 +105,8 @@ protected: void focusOutEvent(QFocusEvent* event) override; void timerEvent(QTimerEvent* event) override; + bool focusNextPrevChild(bool next) override { return false; } + private slots: void onClick(); From a2f9472e5dff77039d66783ffda9ee0fc2de77f8 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 01:11:57 +0200 Subject: [PATCH 056/105] might help fix crashes on exit? --- src/frontend/qt_sdl/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 3b0b35d6..70a6ec10 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -502,6 +502,7 @@ void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("melonDS " MELONDS_VERSION); + setAttribute(Qt::WA_DeleteOnClose); QMenuBar* menubar = new QMenuBar(); { From 4dae6d8928b57792c4ba746a7078c9f7dcac44af Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 01:49:40 +0200 Subject: [PATCH 057/105] load shit from command line --- src/frontend/qt_sdl/main.cpp | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 70a6ec10..0cd9f707 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1006,7 +1006,6 @@ int main(int argc, char** argv) emuThread->start(); emuThread->emuPause(true); - #if 0 if (argc > 1) { char* file = argv[1]; @@ -1014,32 +1013,25 @@ int main(int argc, char** argv) if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl")) { - strncpy(ROMPath[0], file, 1023); - ROMPath[0][1023] = '\0'; + int res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS); - //SetupSRAMPath(0); - - //if (NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot)) - // Run(); - } - - if (argc > 2) - { - file = argv[2]; - ext = &file[strlen(file)-3]; - - if (!strcasecmp(ext, "gba")) + if (res == Frontend::Load_OK) { - strncpy(ROMPath[1], file, 1023); - ROMPath[1][1023] = '\0'; + if (argc > 2) + { + file = argv[2]; + ext = &file[strlen(file)-3]; - //SetupSRAMPath(1); + if (!strcasecmp(ext, "gba")) + { + Frontend::LoadROM(file, Frontend::ROMSlot_GBA); + } + } - //NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]); + emuThread->emuRun(); } } } - #endif int ret = melon.exec(); From 5ed87a634afcff941aad2769496784249a568723 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 02:36:48 +0200 Subject: [PATCH 058/105] add drag-drop support --- src/frontend/qt_sdl/main.cpp | 62 ++++++++++++++++++++++++++++++++++++ src/frontend/qt_sdl/main.h | 3 ++ 2 files changed, 65 insertions(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 0cd9f707..d38a73ec 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -503,6 +504,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("melonDS " MELONDS_VERSION); setAttribute(Qt::WA_DeleteOnClose); + setAcceptDrops(true); QMenuBar* menubar = new QMenuBar(); { @@ -612,6 +614,66 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event) } +void MainWindow::dragEnterEvent(QDragEnterEvent* event) +{ + if (!event->mimeData()->hasUrls()) return; + + QList urls = event->mimeData()->urls(); + if (urls.count() > 1) return; // not handling more than one file at once + + QString filename = urls.at(0).toLocalFile(); + QString ext = filename.right(3); + + if (ext == "nds" || ext == "srl" || (ext == "gba" && RunningSomething)) + event->acceptProposedAction(); +} + +void MainWindow::dropEvent(QDropEvent* event) +{ + if (!event->mimeData()->hasUrls()) return; + + QList urls = event->mimeData()->urls(); + if (urls.count() > 1) return; // not handling more than one file at once + + emuThread->emuPause(true); + + QString filename = urls.at(0).toLocalFile(); + QString ext = filename.right(3); + + char _filename[1024]; + strncpy(_filename, filename.toStdString().c_str(), 1023); _filename[1023] = '\0'; + + int slot; int res; + if (ext == "gba") + { + slot = 1; + res = Frontend::LoadROM(_filename, Frontend::ROMSlot_GBA); + } + else + { + slot = 0; + res = Frontend::LoadROM(_filename, Frontend::ROMSlot_NDS); + } + + if (res != Frontend::Load_OK) + { + QMessageBox::critical(this, + "melonDS", + loadErrorStr(res)); + emuThread->emuUnpause(); + } + else if (slot == 1) + { + // checkme + emuThread->emuUnpause(); + } + else + { + emuThread->emuRun(); + } +} + + QString MainWindow::loadErrorStr(int error) { switch (error) diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 54437806..83777bda 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -92,6 +92,9 @@ protected: void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; + void dragEnterEvent(QDragEnterEvent* event) override; + void dropEvent(QDropEvent* event) override; + private slots: void onOpenFile(); void onBootFirmware(); From 700b1a8b9dfb3cb7502a2f0941cea0090ddbdf44 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 03:01:09 +0200 Subject: [PATCH 059/105] add window icon --- melon.qrc | 6 ++++++ src/frontend/qt_sdl/CMakeLists.txt | 18 ++++++++++-------- src/frontend/qt_sdl/main.cpp | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 melon.qrc diff --git a/melon.qrc b/melon.qrc new file mode 100644 index 00000000..b1ea3641 --- /dev/null +++ b/melon.qrc @@ -0,0 +1,6 @@ + + + + icon/melon_32x32.png + + \ No newline at end of file diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 42cf9128..c3d0959b 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -11,6 +11,8 @@ SET(SOURCES_QT_SDL ../Util_ROM.cpp ../Util_Audio.cpp ../FrontendUtil.h + + ../../../melon.qrc ) if (WIN32) @@ -66,12 +68,12 @@ elseif (WIN32) target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 Qt5::Core Qt5::Gui Qt5::Widgets) endif () -install(FILES ../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) -install(FILES ../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_32x32.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/32x32/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) +install(FILES ../../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) +install(FILES ../../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../../icon/melon_32x32.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/32x32/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png) +install(FILES ../../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index d38a73ec..b81fc86a 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -978,6 +978,7 @@ int main(int argc, char** argv) Platform::Init(argc, argv); QApplication melon(argc, argv); + melon.setWindowIcon(QIcon(":/melon-icon")); // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); From 7be662b2dd1e7f99cf5a31c18c115c1106300964 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 20:57:12 +0200 Subject: [PATCH 060/105] finish fleshing out the menus --- src/frontend/qt_sdl/main.cpp | 256 ++++++++++++++++++++++++++++++----- src/frontend/qt_sdl/main.h | 41 +++++- 2 files changed, 258 insertions(+), 39 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index b81fc86a..7ab7f0e8 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -524,9 +524,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) for (int i = 1; i < 9; i++) { - char title[16]; - sprintf(title, "%d", i); - actSaveState[i] = submenu->addAction(title); + actSaveState[i] = submenu->addAction(QString("%1").arg(i)); actSaveState[i]->setShortcut(QKeySequence(Qt::ShiftModifier | (Qt::Key_F1+i-1))); actSaveState[i]->setData(QVariant(i)); connect(actSaveState[i], &QAction::triggered, this, &MainWindow::onSaveState); @@ -542,9 +540,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) for (int i = 1; i < 9; i++) { - char title[16]; - sprintf(title, "%d", i); - actLoadState[i] = submenu->addAction(title); + actLoadState[i] = submenu->addAction(QString("%1").arg(i)); actLoadState[i]->setShortcut(QKeySequence(Qt::Key_F1+i-1)); actLoadState[i]->setData(QVariant(i)); connect(actLoadState[i], &QAction::triggered, this, &MainWindow::onLoadState); @@ -586,6 +582,125 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actInputConfig = menu->addAction("Input and hotkeys"); connect(actInputConfig, &QAction::triggered, this, &MainWindow::onOpenInputConfig); + + actVideoSettings = menu->addAction("Video settings"); + connect(actVideoSettings, &QAction::triggered, this, &MainWindow::onOpenVideoSettings); + + actAudioSettings = menu->addAction("Audio settings"); + connect(actAudioSettings, &QAction::triggered, this, &MainWindow::onOpenAudioSettings); + + actWifiSettings = menu->addAction("Wifi settings"); + connect(actWifiSettings, &QAction::triggered, this, &MainWindow::onOpenWifiSettings); + + { + QMenu* submenu = menu->addMenu("Savestate settings"); + + actSavestateSRAMReloc = submenu->addAction("Separate savefiles"); + actSavestateSRAMReloc->setCheckable(true); + connect(actSavestateSRAMReloc, &QAction::triggered, this, &MainWindow::onChangeSavestateSRAMReloc); + } + + menu->addSeparator(); + + { + QMenu* submenu = menu->addMenu("Screen size"); + + for (int i = 0; i < 4; i++) + { + int data = i+1; + actScreenSize[i] = submenu->addAction(QString("%1x").arg(data)); + actScreenSize[i]->setData(QVariant(data)); + connect(actScreenSize[i], &QAction::triggered, this, &MainWindow::onChangeScreenSize); + } + } + { + QMenu* submenu = menu->addMenu("Screen rotation"); + grpScreenRotation = new QActionGroup(submenu); + + for (int i = 0; i < 4; i++) + { + int data = i*90; + actScreenRotation[i] = submenu->addAction(QString("%1°").arg(data)); + actScreenRotation[i]->setActionGroup(grpScreenRotation); + actScreenRotation[i]->setData(QVariant(data)); + actScreenRotation[i]->setCheckable(true); + } + + connect(grpScreenRotation, &QActionGroup::triggered, this, &MainWindow::onChangeScreenRotation); + } + { + QMenu* submenu = menu->addMenu("Screen gap"); + grpScreenGap = new QActionGroup(submenu); + + const int screengap[] = {0, 1, 8, 64, 90, 128}; + + for (int i = 0; i < 6; i++) + { + int data = screengap[i]; + actScreenGap[i] = submenu->addAction(QString("%1 px").arg(data)); + actScreenGap[i]->setActionGroup(grpScreenGap); + actScreenGap[i]->setData(QVariant(data)); + actScreenGap[i]->setCheckable(true); + } + + connect(grpScreenGap, &QActionGroup::triggered, this, &MainWindow::onChangeScreenGap); + } + { + QMenu* submenu = menu->addMenu("Screen layout"); + grpScreenLayout = new QActionGroup(submenu); + + const char* screenlayout[] = {"Natural", "Vertical", "Horizontal"}; + + for (int i = 0; i < 3; i++) + { + actScreenLayout[i] = submenu->addAction(QString(screenlayout[i])); + actScreenLayout[i]->setActionGroup(grpScreenLayout); + actScreenLayout[i]->setData(QVariant(i)); + actScreenLayout[i]->setCheckable(true); + } + + connect(grpScreenLayout, &QActionGroup::triggered, this, &MainWindow::onChangeScreenLayout); + } + { + QMenu* submenu = menu->addMenu("Screen sizing"); + grpScreenSizing = new QActionGroup(submenu); + + const char* screensizing[] = {"Even", "Emphasize top", "Emphasize bottom", "Auto"}; + + for (int i = 0; i < 4; i++) + { + actScreenSizing[i] = submenu->addAction(QString(screensizing[i])); + actScreenSizing[i]->setActionGroup(grpScreenSizing); + actScreenSizing[i]->setData(QVariant(i)); + actScreenSizing[i]->setCheckable(true); + } + + connect(grpScreenSizing, &QActionGroup::triggered, this, &MainWindow::onChangeScreenSizing); + + submenu->addSeparator(); + + actIntegerScaling = submenu->addAction("Force integer scaling"); + actIntegerScaling->setCheckable(true); + connect(actIntegerScaling, &QAction::triggered, this, &MainWindow::onChangeIntegerScaling); + } + + actScreenFiltering = menu->addAction("Screen filtering"); + actScreenFiltering->setCheckable(true); + connect(actScreenFiltering, &QAction::triggered, this, &MainWindow::onChangeScreenFiltering); + + actShowOSD = menu->addAction("Show OSD"); + actShowOSD->setCheckable(true); + connect(actShowOSD, &QAction::triggered, this, &MainWindow::onChangeShowOSD); + + menu->addSeparator(); + + actLimitFramerate = menu->addAction("Limit framerate"); + actLimitFramerate->setCheckable(true); + connect(actLimitFramerate, &QAction::triggered, this, &MainWindow::onChangeLimitFramerate); + + actAudioSync = menu->addAction("Audio sync"); + actAudioSync->setCheckable(true); + connect(actAudioSync, &QAction::triggered, this, &MainWindow::onChangeAudioSync); } setMenuBar(menubar); @@ -756,7 +871,6 @@ void MainWindow::onOpenFile() void MainWindow::onBootFirmware() { - // TODO: ensure the firmware is actually bootable!! // TODO: check the whole GBA cart shito emuThread->emuPause(true); @@ -902,6 +1016,106 @@ void MainWindow::onStop() } +void MainWindow::onEmuPause() +{ + // +} + +void MainWindow::onEmuUnpause() +{ + // +} + + +void MainWindow::onOpenEmuSettings() +{ + EmuSettingsDialog::openDlg(this); +} + +void MainWindow::onOpenInputConfig() +{ + emuThread->emuPause(true); + + InputConfigDialog* dlg = InputConfigDialog::openDlg(this); + connect(dlg, &InputConfigDialog::finished, this, &MainWindow::onInputConfigFinished); +} + +void MainWindow::onInputConfigFinished(int res) +{ + emuThread->emuUnpause(); +} + +void MainWindow::onOpenVideoSettings() +{ + // +} + +void MainWindow::onOpenAudioSettings() +{ + // +} + +void MainWindow::onOpenWifiSettings() +{ + // +} + +void MainWindow::onChangeSavestateSRAMReloc(bool checked) +{ + // +} + +void MainWindow::onChangeScreenSize() +{ + // +} + +void MainWindow::onChangeScreenRotation(QAction* act) +{ + printf("DATABOTTE %p\n", act); +} + +void MainWindow::onChangeScreenGap(QAction* act) +{ + // +} + +void MainWindow::onChangeScreenLayout(QAction* act) +{ + // +} + +void MainWindow::onChangeScreenSizing(QAction* act) +{ + // +} + +void MainWindow::onChangeIntegerScaling(bool checked) +{ + // +} + +void MainWindow::onChangeScreenFiltering(bool checked) +{ + // +} + +void MainWindow::onChangeShowOSD(bool checked) +{ + // +} + +void MainWindow::onChangeLimitFramerate(bool checked) +{ + // +} + +void MainWindow::onChangeAudioSync(bool checked) +{ + // +} + + void MainWindow::onTitleUpdate(QString title) { setWindowTitle(title); @@ -938,34 +1152,6 @@ void MainWindow::onEmuStop() actStop->setEnabled(false); } -void MainWindow::onEmuPause() -{ - // -} - -void MainWindow::onEmuUnpause() -{ - // -} - - -void MainWindow::onOpenEmuSettings() -{ - EmuSettingsDialog::openDlg(this); -} - -void MainWindow::onOpenInputConfig() -{ - emuThread->emuPause(true); - - InputConfigDialog* dlg = InputConfigDialog::openDlg(this); - connect(dlg, &InputConfigDialog::finished, this, &MainWindow::onInputConfigFinished); -} - -void MainWindow::onInputConfigFinished(int res) -{ - emuThread->emuUnpause(); -} int main(int argc, char** argv) diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 83777bda..b478f4e6 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -23,6 +23,7 @@ #include #include #include +#include class EmuThread : public QThread @@ -107,6 +108,24 @@ private slots: void onReset(); void onStop(); + void onOpenEmuSettings(); + void onOpenInputConfig(); + void onInputConfigFinished(int res); + void onOpenVideoSettings(); + void onOpenAudioSettings(); + void onOpenWifiSettings(); + void onChangeSavestateSRAMReloc(bool checked); + void onChangeScreenSize(); + void onChangeScreenRotation(QAction* act); + void onChangeScreenGap(QAction* act); + void onChangeScreenLayout(QAction* act); + void onChangeScreenSizing(QAction* act); + void onChangeIntegerScaling(bool checked); + void onChangeScreenFiltering(bool checked); + void onChangeShowOSD(bool checked); + void onChangeLimitFramerate(bool checked); + void onChangeAudioSync(bool checked); + void onTitleUpdate(QString title); void onEmuStart(); @@ -114,10 +133,6 @@ private slots: void onEmuPause(); void onEmuUnpause(); - void onOpenEmuSettings(); - void onOpenInputConfig(); - void onInputConfigFinished(int res); - private: QString loadErrorStr(int error); @@ -136,6 +151,24 @@ private: QAction* actEmuSettings; QAction* actInputConfig; + QAction* actVideoSettings; + QAction* actAudioSettings; + QAction* actWifiSettings; + QAction* actSavestateSRAMReloc; + QAction* actScreenSize[4]; + QActionGroup* grpScreenRotation; + QAction* actScreenRotation[4]; + QActionGroup* grpScreenGap; + QAction* actScreenGap[6]; + QActionGroup* grpScreenLayout; + QAction* actScreenLayout[3]; + QActionGroup* grpScreenSizing; + QAction* actScreenSizing[4]; + QAction* actIntegerScaling; + QAction* actScreenFiltering; + QAction* actShowOSD; + QAction* actLimitFramerate; + QAction* actAudioSync; }; #endif // MAIN_H From d761db005694899342beee101b12aaa6d6cbf711 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 21:19:04 +0200 Subject: [PATCH 061/105] populate the menus with the config data --- src/frontend/qt_sdl/PlatformConfig.cpp | 4 ++-- src/frontend/qt_sdl/PlatformConfig.h | 2 +- src/frontend/qt_sdl/main.cpp | 33 ++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index 3b4b4aad..28c224d5 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -40,11 +40,11 @@ int ScreenRotation; int ScreenGap; int ScreenLayout; int ScreenSizing; +int IntegerScaling; int ScreenFilter; int ScreenUseGL; int ScreenVSync; -int ScreenRatio; int LimitFPS; int AudioSync; @@ -121,11 +121,11 @@ ConfigEntry PlatformConfigFile[] = {"ScreenGap", 0, &ScreenGap, 0, NULL, 0}, {"ScreenLayout", 0, &ScreenLayout, 0, NULL, 0}, {"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0}, + {"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0}, {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0}, {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, - {"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0}, {"LimitFPS", 0, &LimitFPS, 0, NULL, 0}, {"AudioSync", 0, &AudioSync, 1, NULL, 0}, diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h index 3704d149..539f9a45 100644 --- a/src/frontend/qt_sdl/PlatformConfig.h +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -53,11 +53,11 @@ extern int ScreenRotation; extern int ScreenGap; extern int ScreenLayout; extern int ScreenSizing; +extern int IntegerScaling; extern int ScreenFilter; extern int ScreenUseGL; extern int ScreenVSync; -extern int ScreenRatio; extern int LimitFPS; extern int AudioSync; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 7ab7f0e8..af95c49f 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -707,6 +707,30 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) panel = new MainWindowPanel(this); setCentralWidget(panel); panel->setMinimumSize(256, 384); + + + actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0); + + actScreenRotation[Config::ScreenRotation]->setChecked(true); + + for (int i = 0; i < 6; i++) + { + if (actScreenGap[i]->data().toInt() == Config::ScreenGap) + { + actScreenGap[i]->setChecked(true); + break; + } + } + + actScreenLayout[Config::ScreenLayout]->setChecked(true); + actScreenSizing[Config::ScreenSizing]->setChecked(true); + actIntegerScaling->setChecked(Config::IntegerScaling != 0); + + actScreenFiltering->setChecked(Config::ScreenFilter != 0); + actShowOSD->setChecked(Config::ShowOSD != 0); + + actLimitFramerate->setChecked(Config::LimitFPS != 0); + actAudioSync->setChecked(Config::AudioSync != 0); } MainWindow::~MainWindow() @@ -1183,8 +1207,13 @@ int main(int argc, char** argv) Config::Load(); - if (Config::AudioVolume < 0) Config::AudioVolume = 0; - else if (Config::AudioVolume > 256) Config::AudioVolume = 256; +#define SANITIZE(var, min, max) { if (var < min) var = min; else if (var > max) var = max; } + SANITIZE(Config::AudioVolume, 0, 256); + SANITIZE(Config::ScreenRotation, 0, 3); + SANITIZE(Config::ScreenGap, 0, 500); + SANITIZE(Config::ScreenLayout, 0, 2); + SANITIZE(Config::ScreenSizing, 0, 3); +#undef SANITIZE // TODO: this should be checked before running anything #if 0 From 26dcc95c20b13eac0c2c55529507cf0ab881cb0a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 21:23:15 +0200 Subject: [PATCH 062/105] do the easy menus --- src/frontend/qt_sdl/main.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index af95c49f..35eac70f 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1040,17 +1040,6 @@ void MainWindow::onStop() } -void MainWindow::onEmuPause() -{ - // -} - -void MainWindow::onEmuUnpause() -{ - // -} - - void MainWindow::onOpenEmuSettings() { EmuSettingsDialog::openDlg(this); @@ -1086,7 +1075,7 @@ void MainWindow::onOpenWifiSettings() void MainWindow::onChangeSavestateSRAMReloc(bool checked) { - // + Config::SavestateRelocSRAM = checked?1:0; } void MainWindow::onChangeScreenSize() @@ -1096,7 +1085,7 @@ void MainWindow::onChangeScreenSize() void MainWindow::onChangeScreenRotation(QAction* act) { - printf("DATABOTTE %p\n", act); + // } void MainWindow::onChangeScreenGap(QAction* act) @@ -1121,22 +1110,22 @@ void MainWindow::onChangeIntegerScaling(bool checked) void MainWindow::onChangeScreenFiltering(bool checked) { - // + Config::ScreenFilter = checked?1:0; } void MainWindow::onChangeShowOSD(bool checked) { - // + Config::ShowOSD = checked?1:0; } void MainWindow::onChangeLimitFramerate(bool checked) { - // + Config::LimitFPS = checked?1:0; } void MainWindow::onChangeAudioSync(bool checked) { - // + Config::AudioSync = checked?1:0; } @@ -1176,6 +1165,16 @@ void MainWindow::onEmuStop() actStop->setEnabled(false); } +void MainWindow::onEmuPause() +{ + // +} + +void MainWindow::onEmuUnpause() +{ + // +} + int main(int argc, char** argv) From 2ebb21ce3bcf1a445dce7b13f64e44d6098a3acd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 22:22:22 +0200 Subject: [PATCH 063/105] hook up pause and reset, w/ relevant hotkeys --- src/frontend/FrontendUtil.h | 3 ++ src/frontend/Util_ROM.cpp | 47 +++++++++++++++++- src/frontend/qt_sdl/main.cpp | 93 +++++++++++++++++++----------------- src/frontend/qt_sdl/main.h | 10 ++-- 4 files changed, 104 insertions(+), 49 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index f4f68502..d838b634 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -65,6 +65,9 @@ int LoadBIOS(); // note: loading a ROM to the NDS slot resets emulation int LoadROM(const char* file, int slot); +// reset execution of the current ROM +int Reset(); + // get the filename associated with the given savestate slot (1-8) void GetSavestateName(int slot, char* filename, int len); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index 3200de4c..e13eb2c6 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -50,6 +50,11 @@ void Init_ROM() memset(PrevSRAMPath[ROMSlot_GBA], 0, 1024); } +// TODO: currently, when failing to load a ROM for whatever reason, we attempt +// to revert to the previous state and resume execution; this may not be a very +// good thing, depending on what state the core was left in. +// should we do a better state revert (via the savestate system)? completely stop? + void SetupSRAMPath(int slot) { strncpy(SRAMPath[slot], ROMPath[slot], 1023); @@ -184,7 +189,7 @@ int LoadROM(const char* file, int slot) } else if (slot == ROMSlot_GBA && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot])) { - SavestateLoaded = false; + SavestateLoaded = false; // checkme?? strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety return Load_OK; @@ -197,6 +202,46 @@ int LoadROM(const char* file, int slot) } } +int Reset() +{ + int res; + bool directboot = Config::DirectBoot != 0; + + res = VerifyDSBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSFirmware(); + if (res != Load_OK) + { + if (res == Load_FirmwareNotBootable) + directboot = true; + else + return res; + } + + SavestateLoaded = false; + + if (ROMPath[ROMSlot_NDS][0] == '\0') + { + NDS::LoadBIOS(); + } + else + { + SetupSRAMPath(0); + if (!NDS::LoadROM(ROMPath[ROMSlot_NDS], SRAMPath[ROMSlot_NDS], directboot)) + return Load_ROMLoadError; + } + + if (ROMPath[ROMSlot_GBA][0] != '\0') + { + SetupSRAMPath(1); + if (!NDS::LoadGBAROM(ROMPath[ROMSlot_GBA], SRAMPath[ROMSlot_GBA])) + return Load_ROMLoadError; + } + + return Load_OK; +} + // SAVESTATE TODO // * configurable paths. not everyone wants their ROM directory to be polluted, I guess. diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 35eac70f..a73362dc 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -113,6 +113,8 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); + connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger())); + connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); emit windowEmuStop(); } @@ -152,14 +154,10 @@ void EmuThread::run() { Input::Process(); - /*if (Input::HotkeyPressed(HK_FastForwardToggle)) - { - Config::LimitFPS = !Config::LimitFPS; - // TODO: reflect in UI! - }*/ + if (Input::HotkeyPressed(HK_FastForwardToggle)) emit windowLimitFPSChange(); - //if (Input::HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL); - //if (Input::HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL); + if (Input::HotkeyPressed(HK_Pause)) emit windowEmuPause(); + if (Input::HotkeyPressed(HK_Reset)) emit windowEmuReset(); if (GBACart::CartInserted && GBACart::HasSolarSensor) { @@ -318,18 +316,15 @@ void EmuThread::run() lastmeasuretick = lasttick; fpslimitcount = 0; - if (EmuRunning == 2) + /*if (Screen_UseGL) { - /*if (Screen_UseGL) - { - uiGLBegin(GLContext); - uiGLMakeContextCurrent(GLContext); - GLScreen_DrawScreen(); - uiGLEnd(GLContext); - } - uiAreaQueueRedrawAll(MainDrawArea);*/ - mainWindow->update(); + uiGLBegin(GLContext); + uiGLMakeContextCurrent(GLContext); + GLScreen_DrawScreen(); + uiGLEnd(GLContext); } + uiAreaQueueRedrawAll(MainDrawArea);*/ + mainWindow->update(); //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); @@ -338,7 +333,7 @@ void EmuThread::run() sprintf(melontitle, "melonDS " MELONDS_VERSION); changeWindowTitle(melontitle); - SDL_Delay(100); + SDL_Delay(75); } } @@ -375,12 +370,11 @@ void EmuThread::emuRun() if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); } -void EmuThread::emuPause(bool refresh) +void EmuThread::emuPause() { - int status = refresh ? 2:3; PrevEmuStatus = EmuRunning; - EmuRunning = status; - while (EmuStatus != status); + EmuRunning = 2; + while (EmuStatus != 2); //emit windowEmuPause(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); @@ -774,7 +768,7 @@ void MainWindow::dropEvent(QDropEvent* event) QList urls = event->mimeData()->urls(); if (urls.count() > 1) return; // not handling more than one file at once - emuThread->emuPause(true); + emuThread->emuPause(); QString filename = urls.at(0).toLocalFile(); QString ext = filename.right(3); @@ -836,7 +830,7 @@ QString MainWindow::loadErrorStr(int error) void MainWindow::onOpenFile() { - emuThread->emuPause(true); + emuThread->emuPause(); QString filename = QFileDialog::getOpenFileName(this, "Open ROM", @@ -897,7 +891,7 @@ void MainWindow::onBootFirmware() { // TODO: check the whole GBA cart shito - emuThread->emuPause(true); + emuThread->emuPause(); int res = Frontend::LoadBIOS(); if (res != Frontend::Load_OK) @@ -917,7 +911,7 @@ void MainWindow::onSaveState() { int slot = ((QAction*)sender())->data().toInt(); - emuThread->emuPause(true); + emuThread->emuPause(); char filename[1024]; if (slot > 0) @@ -958,7 +952,7 @@ void MainWindow::onLoadState() { int slot = ((QAction*)sender())->data().toInt(); - emuThread->emuPause(true); + emuThread->emuPause(); char filename[1024]; if (slot > 0) @@ -1006,7 +1000,7 @@ void MainWindow::onLoadState() void MainWindow::onUndoStateLoad() { - emuThread->emuPause(true); + emuThread->emuPause(); Frontend::UndoStateLoad(); emuThread->emuUnpause(); } @@ -1019,9 +1013,11 @@ void MainWindow::onQuit() void MainWindow::onPause(bool checked) { - if (emuThread->emuIsRunning()) + if (!RunningSomething) return; + + if (checked) { - emuThread->emuPause(true); + emuThread->emuPause(); } else { @@ -1031,7 +1027,26 @@ void MainWindow::onPause(bool checked) void MainWindow::onReset() { - // + if (!RunningSomething) return; + + emuThread->emuPause(); + + actUndoStateLoad->setEnabled(false); + + int res = Frontend::Reset(); + if (res != Frontend::Load_OK) + { + QMessageBox::critical(this, + "melonDS", + loadErrorStr(res)); + emuThread->emuUnpause(); + } + else + { + // OSD::AddMessage(0, "Reset"); + + emuThread->emuRun(); + } } void MainWindow::onStop() @@ -1047,7 +1062,7 @@ void MainWindow::onOpenEmuSettings() void MainWindow::onOpenInputConfig() { - emuThread->emuPause(true); + emuThread->emuPause(); InputConfigDialog* dlg = InputConfigDialog::openDlg(this); connect(dlg, &InputConfigDialog::finished, this, &MainWindow::onInputConfigFinished); @@ -1143,7 +1158,7 @@ void MainWindow::onEmuStart() } actSaveState[0]->setEnabled(true); actLoadState[0]->setEnabled(true); - actUndoStateLoad->setEnabled(true); + actUndoStateLoad->setEnabled(false); actPause->setEnabled(true); actPause->setChecked(false); @@ -1165,16 +1180,6 @@ void MainWindow::onEmuStop() actStop->setEnabled(false); } -void MainWindow::onEmuPause() -{ - // -} - -void MainWindow::onEmuUnpause() -{ - // -} - int main(int argc, char** argv) @@ -1281,7 +1286,7 @@ int main(int argc, char** argv) emuThread = new EmuThread(); emuThread->start(); - emuThread->emuPause(true); + emuThread->emuPause(); if (argc > 1) { diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index b478f4e6..22f045f7 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -38,7 +38,7 @@ public: // to be called from the UI thread void emuRun(); - void emuPause(bool refresh); + void emuPause(); void emuUnpause(); void emuStop(); @@ -49,7 +49,10 @@ signals: void windowEmuStart(); void windowEmuStop(); - void windowPauseToggle(); + void windowEmuPause(); + void windowEmuReset(); + + void windowLimitFPSChange(); private: volatile int EmuStatus; @@ -130,14 +133,13 @@ private slots: void onEmuStart(); void onEmuStop(); - void onEmuPause(); - void onEmuUnpause(); private: QString loadErrorStr(int error); MainWindowPanel* panel; +public: QAction* actOpenROM; QAction* actBootFirmware; QAction* actSaveState[9]; From a9b275bc253510d77b8b6fcd80e6d24b56bc8680 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 22:58:04 +0200 Subject: [PATCH 064/105] reimplement Stop --- src/SPU.cpp | 3 +++ src/frontend/FrontendUtil.h | 4 ++++ src/frontend/Util_ROM.cpp | 14 ++++++++++++ src/frontend/qt_sdl/Platform.cpp | 4 ++-- src/frontend/qt_sdl/main.cpp | 37 ++++++++++++++++++++++++++------ 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/SPU.cpp b/src/SPU.cpp index 710533ef..1ebfd4ce 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -116,6 +116,9 @@ void Reset() void Stop() { memset(OutputBuffer, 0, 2*OutputBufferSize*2); + + OutputReadOffset = 0; + OutputWriteOffset = 0; } void DoSavestate(Savestate* file) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index d838b634..faa29de1 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -65,6 +65,10 @@ int LoadBIOS(); // note: loading a ROM to the NDS slot resets emulation int LoadROM(const char* file, int slot); +// unload the ROM loaded in the specified cart slot +// simulating ejection of the cartridge +void UnloadROM(int slot); + // reset execution of the current ROM int Reset(); diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index e13eb2c6..ec3186a8 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -202,6 +202,20 @@ int LoadROM(const char* file, int slot) } } +void UnloadROM(int slot) +{ + if (slot == ROMSlot_NDS) + { + // TODO! + } + else if (slot == ROMSlot_GBA) + { + GBACart::Eject(); + } + + ROMPath[slot][0] = '\0'; +} + int Reset() { int res; diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 6a5b4663..dd838d75 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -55,7 +55,7 @@ char* EmuDirectory; -void Stop(bool internal); +void emuStop(); namespace Platform @@ -133,7 +133,7 @@ void DeInit() void StopEmu() { - //Stop(true); + emuStop(); } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index a73362dc..67272afe 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -115,8 +115,6 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger())); connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); - - emit windowEmuStop(); } void EmuThread::run() @@ -140,7 +138,6 @@ void EmuThread::run() } Input::Init(); - /*Touching = false;*/ u32 nframes = 0; u32 starttick = SDL_GetTicks(); @@ -376,7 +373,6 @@ void EmuThread::emuPause() EmuRunning = 2; while (EmuStatus != 2); - //emit windowEmuPause(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); } @@ -384,7 +380,6 @@ void EmuThread::emuUnpause() { EmuRunning = PrevEmuStatus; - //emit windowEmuUnpause(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); } @@ -703,6 +698,18 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) panel->setMinimumSize(256, 384); + for (int i = 0; i < 9; i++) + { + actSaveState[i]->setEnabled(false); + actLoadState[i]->setEnabled(false); + } + actUndoStateLoad->setEnabled(false); + + actPause->setEnabled(false); + actReset->setEnabled(false); + actStop->setEnabled(false); + + actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0); actScreenRotation[Config::ScreenRotation]->setChecked(true); @@ -1051,7 +1058,10 @@ void MainWindow::onReset() void MainWindow::onStop() { - // + if (!RunningSomething) return; + + emuThread->emuPause(); + NDS::Stop(); } @@ -1168,6 +1178,8 @@ void MainWindow::onEmuStart() void MainWindow::onEmuStop() { + emuThread->emuPause(); + for (int i = 0; i < 9; i++) { actSaveState[i]->setEnabled(false); @@ -1181,6 +1193,19 @@ void MainWindow::onEmuStop() } +void emuStop() +{ + RunningSomething = false; + + Frontend::UnloadROM(Frontend::ROMSlot_NDS); + Frontend::UnloadROM(Frontend::ROMSlot_GBA); + + emit emuThread->windowEmuStop(); + + //OSD::AddMessage(0xFFC040, "Shutdown"); +} + + int main(int argc, char** argv) { From 9e43c85b4d86cdb79242045c5fcf3929e3568322 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 20 May 2020 23:55:18 +0200 Subject: [PATCH 065/105] hook up microphone shit. I did my best. --- src/frontend/FrontendUtil.h | 11 +++ src/frontend/Util_Audio.cpp | 64 ++++++++++++- src/frontend/qt_sdl/main.cpp | 177 ++++++++++++++++++++++++++++++++++- 3 files changed, 247 insertions(+), 5 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index faa29de1..6a6f8ea4 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -101,6 +101,17 @@ int AudioOut_GetNumSamples(int outlen); // note: this assumes the output buffer is interleaved stereo void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen); +// feed silence to the microphone input +void Mic_FeedSilence(); + +// feed random noise to the microphone input +void Mic_FeedNoise(); + +// feed an external buffer to the microphone input +// buffer should be mono +void Mic_FeedExternalBuffer(); +void Mic_SetExternalBuffer(s16* buffer, u32 len); + } #endif // FRONTENDUTIL_H diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp index fe0ecab6..2088efed 100644 --- a/src/frontend/Util_Audio.cpp +++ b/src/frontend/Util_Audio.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -26,7 +27,6 @@ #include "Platform.h" #include "NDS.h" -#include "GBACart.h" namespace Frontend @@ -35,13 +35,22 @@ namespace Frontend int AudioOut_Freq; float AudioOut_SampleFrac; +s16* MicBuffer; +u32 MicBufferLength; +u32 MicBufferReadPos; + void Init_Audio(int outputfreq) { AudioOut_Freq = outputfreq; AudioOut_SampleFrac = 0; + + MicBuffer = nullptr; + MicBufferLength = 0; + MicBufferReadPos = 0; } + int AudioOut_GetNumSamples(int outlen) { float f_len_in = (outlen * 32823.6328125) / (float)AudioOut_Freq; @@ -74,4 +83,57 @@ void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen) } } + +void Mic_FeedSilence() +{ + MicBufferReadPos = 0; + NDS::MicInputFrame(NULL, 0); +} + +void Mic_FeedNoise() +{ + // note: DS games seem to expect very saturated 'blowing into mic' noise + + s16 tmp[735]; + + for (int i = 0; i < 735; i++) + { + int val = rand() >> 8; + if (val < -0x8000) val = -0x8000; + else if (val > 0x7FFF) val = 0x7FFF; + + tmp[i] = val; + } + + NDS::MicInputFrame(tmp, 735); +} + +void Mic_FeedExternalBuffer() +{ + if (!MicBuffer) return Mic_FeedSilence(); + + if ((MicBufferReadPos + 735) > MicBufferLength) + { + s16 tmp[735]; + u32 len1 = MicBufferLength - MicBufferReadPos; + memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16)); + memcpy(&tmp[len1], &MicBuffer[0], (735 - len1)*sizeof(s16)); + + NDS::MicInputFrame(tmp, 735); + MicBufferReadPos = 735 - len1; + } + else + { + NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735); + MicBufferReadPos += 735; + } +} + +void Mic_SetExternalBuffer(s16* buffer, u32 len) +{ + MicBuffer = buffer; + MicBufferLength = len; + MicBufferReadPos = 0; +} + } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 67272afe..1615fa30 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -66,6 +66,13 @@ int audioFreq; SDL_cond* audioSync; SDL_mutex* audioSyncLock; +SDL_AudioDeviceID micDevice; +s16 micExtBuffer[2048]; +u32 micExtBufferWritePos; + +u32 micWavLength; +s16* micWavBuffer; + void audioCallback(void* data, Uint8* stream, int len) { @@ -104,6 +111,133 @@ void audioCallback(void* data, Uint8* stream, int len) } +void micLoadWav(const char* name) +{ + SDL_AudioSpec format; + memset(&format, 0, sizeof(SDL_AudioSpec)); + + if (micWavBuffer) delete[] micWavBuffer; + micWavBuffer = nullptr; + micWavLength = 0; + + u8* buf; + u32 len; + if (!SDL_LoadWAV(name, &format, &buf, &len)) + return; + + const u64 dstfreq = 44100; + + if (format.format == AUDIO_S16 || format.format == AUDIO_U16) + { + int srcinc = format.channels; + len /= (2 * srcinc); + + micWavLength = (len * dstfreq) / format.freq; + if (micWavLength < 735) micWavLength = 735; + micWavBuffer = new s16[micWavLength]; + + float res_incr = len / (float)micWavLength; + float res_timer = 0; + int res_pos = 0; + + for (int i = 0; i < micWavLength; i++) + { + u16 val = ((u16*)buf)[res_pos]; + if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000; + + micWavBuffer[i] = val; + + res_timer += res_incr; + while (res_timer >= 1.0) + { + res_timer -= 1.0; + res_pos += srcinc; + } + } + } + else if (format.format == AUDIO_S8 || format.format == AUDIO_U8) + { + int srcinc = format.channels; + len /= srcinc; + + micWavLength = (len * dstfreq) / format.freq; + if (micWavLength < 735) micWavLength = 735; + micWavBuffer = new s16[micWavLength]; + + float res_incr = len / (float)micWavLength; + float res_timer = 0; + int res_pos = 0; + + for (int i = 0; i < micWavLength; i++) + { + u16 val = buf[res_pos] << 8; + if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000; + + micWavBuffer[i] = val; + + res_timer += res_incr; + while (res_timer >= 1.0) + { + res_timer -= 1.0; + res_pos += srcinc; + } + } + } + else + printf("bad WAV format %08X\n", format.format); + + SDL_FreeWAV(buf); +} + +void micCallback(void* data, Uint8* stream, int len) +{ + s16* input = (s16*)stream; + len /= sizeof(s16); + + int maxlen = sizeof(micExtBuffer) / sizeof(s16); + + if ((micExtBufferWritePos + len) > maxlen) + { + u32 len1 = maxlen - micExtBufferWritePos; + memcpy(&micExtBuffer[micExtBufferWritePos], &input[0], len1*sizeof(s16)); + memcpy(&micExtBuffer[0], &input[len1], (len - len1)*sizeof(s16)); + micExtBufferWritePos = len - len1; + } + else + { + memcpy(&micExtBuffer[micExtBufferWritePos], input, len*sizeof(s16)); + micExtBufferWritePos += len; + } +} + +void micProcess() +{ + int type = Config::MicInputType; + bool cmd = Input::HotkeyDown(HK_Mic); + + if (type != 1 && !cmd) + { + type = 0; + } + + switch (type) + { + case 0: // no mic + Frontend::Mic_FeedSilence(); + break; + + case 1: // host mic + case 3: // WAV + Frontend::Mic_FeedExternalBuffer(); + break; + + case 2: // white noise + Frontend::Mic_FeedNoise(); + break; + } +} + + EmuThread::EmuThread(QObject* parent) : QThread(parent) { EmuStatus = 0; @@ -189,9 +323,9 @@ void EmuThread::run() } // microphone input - /*FeedMicInput(); + micProcess(); - if (Screen_UseGL) + /*if (Screen_UseGL) { uiGLBegin(GLContext); uiGLMakeContextCurrent(GLContext); @@ -365,6 +499,7 @@ void EmuThread::emuRun() // checkme emit windowEmuStart(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); + if (micDevice) SDL_PauseAudioDevice(micDevice, 0); } void EmuThread::emuPause() @@ -374,6 +509,7 @@ void EmuThread::emuPause() while (EmuStatus != 2); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); + if (micDevice) SDL_PauseAudioDevice(micDevice, 1); } void EmuThread::emuUnpause() @@ -381,6 +517,7 @@ void EmuThread::emuUnpause() EmuRunning = PrevEmuStatus; if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); + if (micDevice) SDL_PauseAudioDevice(micDevice, 0); } void EmuThread::emuStop() @@ -388,6 +525,7 @@ void EmuThread::emuStop() EmuRunning = 0; if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); + if (micDevice) SDL_PauseAudioDevice(micDevice, 1); } bool EmuThread::emuIsRunning() @@ -1300,9 +1438,40 @@ int main(int argc, char** argv) SDL_PauseAudioDevice(audioDevice, 1); } + memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); + whatIwant.freq = 44100; + whatIwant.format = AUDIO_S16LSB; + whatIwant.channels = 1; + whatIwant.samples = 1024; + whatIwant.callback = micCallback; + micDevice = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0); + if (!micDevice) + { + printf("Mic init failed: %s\n", SDL_GetError()); + } + else + { + SDL_PauseAudioDevice(micDevice, 1); + } + + + memset(micExtBuffer, 0, sizeof(micExtBuffer)); + micExtBufferWritePos = 0; + micWavBuffer = nullptr; + Frontend::Init_ROM(); Frontend::Init_Audio(audioFreq); + if (Config::MicInputType == 1) + { + Frontend::Mic_SetExternalBuffer(micExtBuffer, sizeof(micExtBuffer)/sizeof(s16)); + } + else if (Config::MicInputType == 3) + { + micLoadWav(Config::MicWavPath); + Frontend::Mic_SetExternalBuffer(micWavBuffer, micWavLength); + } + Input::JoystickID = Config::JoystickID; Input::OpenJoystick(); @@ -1349,12 +1518,12 @@ int main(int argc, char** argv) Input::CloseJoystick(); if (audioDevice) SDL_CloseAudioDevice(audioDevice); - //if (MicDevice) SDL_CloseAudioDevice(MicDevice); + if (micDevice) SDL_CloseAudioDevice(micDevice); SDL_DestroyCond(audioSync); SDL_DestroyMutex(audioSyncLock); - //if (MicWavBuffer) delete[] MicWavBuffer; + if (micWavBuffer) delete[] micWavBuffer; Config::Save(); From 108647e03320788729bcfa229d81c0f7678fe1fb Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 21 May 2020 01:39:41 +0200 Subject: [PATCH 066/105] * add audio settings dialog * attempt at betterer mic noise that doesn't work worth a damn --- src/frontend/Util_Audio.cpp | 8 +- src/frontend/qt_sdl/AudioSettingsDialog.cpp | 103 +++++++++++++ src/frontend/qt_sdl/AudioSettingsDialog.h | 69 +++++++++ src/frontend/qt_sdl/AudioSettingsDialog.ui | 162 ++++++++++++++++++++ src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/EmuSettingsDialog.cpp | 1 + src/frontend/qt_sdl/EmuSettingsDialog.ui | 15 +- src/frontend/qt_sdl/main.cpp | 24 ++- src/frontend/qt_sdl/main.h | 1 + 9 files changed, 366 insertions(+), 18 deletions(-) create mode 100644 src/frontend/qt_sdl/AudioSettingsDialog.cpp create mode 100644 src/frontend/qt_sdl/AudioSettingsDialog.h create mode 100644 src/frontend/qt_sdl/AudioSettingsDialog.ui diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp index 2088efed..3f03810b 100644 --- a/src/frontend/Util_Audio.cpp +++ b/src/frontend/Util_Audio.cpp @@ -93,14 +93,16 @@ void Mic_FeedSilence() void Mic_FeedNoise() { // note: DS games seem to expect very saturated 'blowing into mic' noise + s16 noisesample[8] = {-0x8000, -0x8000, 0x7FFF, -0x8000, 0x7FFF, 0x7FFF, -0x8000, 0x7FFF}; + int j = 0; s16 tmp[735]; for (int i = 0; i < 735; i++) { - int val = rand() >> 8; - if (val < -0x8000) val = -0x8000; - else if (val > 0x7FFF) val = 0x7FFF; + int val = noisesample[j]; + j++; + if (j >= 8) j = rand() & 7; tmp[i] = val; } diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.cpp b/src/frontend/qt_sdl/AudioSettingsDialog.cpp new file mode 100644 index 00000000..2ff5307d --- /dev/null +++ b/src/frontend/qt_sdl/AudioSettingsDialog.cpp @@ -0,0 +1,103 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include + +#include "types.h" +#include "Platform.h" +#include "Config.h" +#include "PlatformConfig.h" + +#include "AudioSettingsDialog.h" +#include "ui_AudioSettingsDialog.h" + + +AudioSettingsDialog* AudioSettingsDialog::currentDlg = nullptr; + +extern char* EmuDirectory; + + +AudioSettingsDialog::AudioSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AudioSettingsDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + oldVolume = Config::AudioVolume; + + ui->slVolume->setValue(Config::AudioVolume); + + grpMicMode = new QButtonGroup(this); + grpMicMode->addButton(ui->rbMicNone, 0); + grpMicMode->addButton(ui->rbMicExternal, 1); + grpMicMode->addButton(ui->rbMicNoise, 2); + grpMicMode->addButton(ui->rbMicWav, 3); + connect(grpMicMode, SIGNAL(buttonClicked(int)), this, SLOT(onChangeMicMode(int))); + grpMicMode->button(Config::MicInputType)->setChecked(true); + + ui->txtMicWavPath->setText(Config::MicWavPath); + + bool iswav = (Config::MicInputType == 3); + ui->txtMicWavPath->setEnabled(iswav); + ui->btnMicWavBrowse->setEnabled(iswav); +} + +AudioSettingsDialog::~AudioSettingsDialog() +{ + delete ui; +} + +void AudioSettingsDialog::on_AudioSettingsDialog_accepted() +{ + Config::MicInputType = grpMicMode->checkedId(); + strncpy(Config::MicWavPath, ui->txtMicWavPath->text().toStdString().c_str(), 1023); Config::MicWavPath[1023] = '\0'; + Config::Save(); + + closeDlg(); +} + +void AudioSettingsDialog::on_AudioSettingsDialog_rejected() +{ + Config::AudioVolume = oldVolume; + + closeDlg(); +} + +void AudioSettingsDialog::on_slVolume_valueChanged(int val) +{ + Config::AudioVolume = val; +} + +void AudioSettingsDialog::onChangeMicMode(int mode) +{ + bool iswav = (mode == 3); + ui->txtMicWavPath->setEnabled(iswav); + ui->btnMicWavBrowse->setEnabled(iswav); +} + +void AudioSettingsDialog::on_btnMicWavBrowse_clicked() +{ + QString file = QFileDialog::getOpenFileName(this, + "Select WAV file...", + EmuDirectory, + "WAV files (*.wav);;Any file (*.*)"); + + if (file.isEmpty()) return; + + ui->txtMicWavPath->setText(file); +} diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.h b/src/frontend/qt_sdl/AudioSettingsDialog.h new file mode 100644 index 00000000..3bafa303 --- /dev/null +++ b/src/frontend/qt_sdl/AudioSettingsDialog.h @@ -0,0 +1,69 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef AUDIOSETTINGSDIALOG_H +#define AUDIOSETTINGSDIALOG_H + +#include +#include + +namespace Ui { class AudioSettingsDialog; } +class AudioSettingsDialog; + +class AudioSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit AudioSettingsDialog(QWidget* parent); + ~AudioSettingsDialog(); + + static AudioSettingsDialog* currentDlg; + static AudioSettingsDialog* openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return currentDlg; + } + + currentDlg = new AudioSettingsDialog(parent); + currentDlg->show(); + return currentDlg; + } + static void closeDlg() + { + currentDlg = nullptr; + } + +private slots: + void on_AudioSettingsDialog_accepted(); + void on_AudioSettingsDialog_rejected(); + + void on_slVolume_valueChanged(int val); + void onChangeMicMode(int mode); + void on_btnMicWavBrowse_clicked(); + +private: + Ui::AudioSettingsDialog* ui; + + int oldVolume; + QButtonGroup* grpMicMode; +}; + +#endif // AUDIOSETTINGSDIALOG_H diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.ui b/src/frontend/qt_sdl/AudioSettingsDialog.ui new file mode 100644 index 00000000..b6c215e0 --- /dev/null +++ b/src/frontend/qt_sdl/AudioSettingsDialog.ui @@ -0,0 +1,162 @@ + + + AudioSettingsDialog + + + + 0 + 0 + 482 + 230 + + + + Audio settings - melonDS + + + + + + Audio output + + + + + + Volume: + + + + + + + <html><head/><body><p>Controls the volume of the audio output.</p></body></html> + + + 256 + + + 16 + + + Qt::Horizontal + + + + + + + + + + Microphone input + + + + + + + 290 + 0 + + + + + + + + <html><head/><body><p>Forward a WAV file to the emulated microphone.</p></body></html> + + + WAV file: + + + + + + + Browse... + + + + + + + <html><head/><body><p>Input from an external microphone, if available, will be forwarded to the emulated microphone.</p></body></html> + + + External microphone + + + + + + + <html><head/><body><p>Noise will be forwarded to the emulated microphone, simulating blowing into the microphone.</p></body></html> + + + White noise + + + + + + + <html><head/><body><p>No microphone input.</p></body></html> + + + None + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AudioSettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AudioSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index c3d0959b..caa78e9f 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -4,6 +4,7 @@ SET(SOURCES_QT_SDL main.cpp EmuSettingsDialog.cpp InputConfigDialog.cpp + AudioSettingsDialog.cpp Input.cpp Platform.cpp PlatformConfig.cpp diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index 6264d91c..5c2efc0e 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -100,6 +100,7 @@ void EmuSettingsDialog::on_EmuSettingsDialog_accepted() strncpy(Config::BIOS7Path, ui->txtBIOS7Path->text().toStdString().c_str(), 1023); Config::BIOS7Path[1023] = '\0'; strncpy(Config::FirmwarePath, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); Config::FirmwarePath[1023] = '\0'; Config::DirectBoot = ui->chkDirectBoot->isChecked() ? 1:0; + Config::Save(); closeDlg(); } diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.ui b/src/frontend/qt_sdl/EmuSettingsDialog.ui index e4deaba9..c70c3a23 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.ui +++ b/src/frontend/qt_sdl/EmuSettingsDialog.ui @@ -7,7 +7,7 @@ 0 0 490 - 243 + 217 @@ -138,19 +138,6 @@ - - - - Qt::Vertical - - - - 20 - 20 - - - - diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 1615fa30..245324f6 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -36,6 +36,7 @@ #include "Input.h" #include "EmuSettingsDialog.h" #include "InputConfigDialog.h" +#include "AudioSettingsDialog.h" #include "types.h" #include "version.h" @@ -1228,7 +1229,27 @@ void MainWindow::onOpenVideoSettings() void MainWindow::onOpenAudioSettings() { - // + AudioSettingsDialog* dlg = AudioSettingsDialog::openDlg(this); + connect(dlg, &AudioSettingsDialog::finished, this, &MainWindow::onAudioSettingsFinished); +} + +void MainWindow::onAudioSettingsFinished(int res) +{ + if (Config::MicInputType == 3) + { + micLoadWav(Config::MicWavPath); + Frontend::Mic_SetExternalBuffer(micWavBuffer, micWavLength); + } + else + { + delete[] micWavBuffer; + micWavBuffer = nullptr; + + if (Config::MicInputType == 1) + Frontend::Mic_SetExternalBuffer(micExtBuffer, sizeof(micExtBuffer)/sizeof(s16)); + else + Frontend::Mic_SetExternalBuffer(NULL, 0); + } } void MainWindow::onOpenWifiSettings() @@ -1376,6 +1397,7 @@ int main(int argc, char** argv) #define SANITIZE(var, min, max) { if (var < min) var = min; else if (var > max) var = max; } SANITIZE(Config::AudioVolume, 0, 256); + SANITIZE(Config::MicInputType, 0, 3); SANITIZE(Config::ScreenRotation, 0, 3); SANITIZE(Config::ScreenGap, 0, 500); SANITIZE(Config::ScreenLayout, 0, 2); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 22f045f7..7051a088 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -116,6 +116,7 @@ private slots: void onInputConfigFinished(int res); void onOpenVideoSettings(); void onOpenAudioSettings(); + void onAudioSettingsFinished(int res); void onOpenWifiSettings(); void onChangeSavestateSRAMReloc(bool checked); void onChangeScreenSize(); From f79583bf1697b4c6a5b40c1e727e2a40c789757d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 21 May 2020 02:33:48 +0200 Subject: [PATCH 067/105] add actual blow-into-mic sample that actually works --- src/frontend/Util_Audio.cpp | 15 +- src/frontend/mic_blow.h | 5539 ++++++++++++++++++++ src/frontend/qt_sdl/AudioSettingsDialog.ui | 2 +- src/frontend/qt_sdl/CMakeLists.txt | 1 + 4 files changed, 5548 insertions(+), 9 deletions(-) create mode 100644 src/frontend/mic_blow.h diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp index 3f03810b..d4c33332 100644 --- a/src/frontend/Util_Audio.cpp +++ b/src/frontend/Util_Audio.cpp @@ -28,6 +28,8 @@ #include "NDS.h" +#include "mic_blow.h" + namespace Frontend { @@ -92,19 +94,16 @@ void Mic_FeedSilence() void Mic_FeedNoise() { - // note: DS games seem to expect very saturated 'blowing into mic' noise - s16 noisesample[8] = {-0x8000, -0x8000, 0x7FFF, -0x8000, 0x7FFF, 0x7FFF, -0x8000, 0x7FFF}; - int j = 0; + int sample_len = sizeof(mic_blow) / sizeof(u16); + static int sample_pos = 0; s16 tmp[735]; for (int i = 0; i < 735; i++) { - int val = noisesample[j]; - j++; - if (j >= 8) j = rand() & 7; - - tmp[i] = val; + tmp[i] = mic_blow[sample_pos]; + sample_pos++; + if (sample_pos >= sample_len) sample_pos = 0; } NDS::MicInputFrame(tmp, 735); diff --git a/src/frontend/mic_blow.h b/src/frontend/mic_blow.h new file mode 100644 index 00000000..cee92fe0 --- /dev/null +++ b/src/frontend/mic_blow.h @@ -0,0 +1,5539 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MIC_BLOW_H +#define MIC_BLOW_H + +const u16 mic_blow[] = +{ + 0x1840, 0x1EF0, 0x24F0, 0x2A60, 0x2F60, 0x33F0, 0x3800, 0x3BC0, 0x3FB0, 0x43E0, 0x48A0, 0x4EC0, 0x5490, 0x5A30, 0x6040, 0x6490, + 0x6960, 0x6E40, 0x7220, 0x76B0, 0x79B0, 0x7CA0, 0x7E60, 0x7F00, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F30, + 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F30, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, + 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F50, 0x7EF0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, 0x7E90, + 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7EB0, 0x7F20, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F80, 0x7EB0, 0x7220, 0x66D0, 0x5BD0, 0x5190, 0x4680, + 0x3D70, 0x3470, 0x2C70, 0x2640, 0x2090, 0x1D00, 0x1A40, 0x1910, 0x1810, 0x17A0, 0x1860, 0x19C0, 0x1C10, 0x1F30, 0x22E0, 0x2930, + 0x2FA0, 0x3720, 0x3EC0, 0x46B0, 0x4E80, 0x5660, 0x5ED0, 0x6710, 0x7000, 0x7720, 0x7D10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7E80, 0x7D30, 0x7C00, 0x7AA0, 0x7890, + 0x7610, 0x73F0, 0x71A0, 0x6F60, 0x6CD0, 0x6970, 0x6670, 0x6310, 0x5F90, 0x5D10, 0x5A20, 0x5720, 0x5410, 0x4FB0, 0x4AC0, 0x4670, + 0x4250, 0x3E40, 0x39F0, 0x3540, 0x2FB0, 0x28E0, 0x2260, 0x1BB0, 0x15F0, 0x10B0, 0x0C60, 0x08B0, 0x05B0, 0x0300, 0x00F0, 0xFEB0, + 0xFC00, 0xF8E0, 0xF570, 0xF170, 0xED60, 0xE8E0, 0xE4C0, 0xDFF0, 0xDB90, 0xD650, 0xD090, 0xCAB0, 0xC570, 0xC0C0, 0xBD00, 0xBA30, + 0xB790, 0xB4C0, 0xB1B0, 0xAF40, 0xAD00, 0xAC10, 0xAB70, 0xAA70, 0xA9C0, 0xA800, 0xA640, 0xA520, 0xA420, 0xA2C0, 0xA1D0, 0xA000, + 0x9E60, 0x9CF0, 0x9B80, 0x9A10, 0x97F0, 0x9550, 0x9340, 0x9170, 0x8F80, 0x8DA0, 0x8C40, 0x8B10, 0x89E0, 0x8890, 0x87B0, 0x86F0, + 0x8660, 0x8640, 0x8600, 0x85F0, 0x85D0, 0x85B0, 0x8580, 0x8560, 0x8550, 0x8550, 0x8540, 0x8530, 0x8530, 0x8520, 0x8510, 0x8510, + 0x8500, 0x8500, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x8510, 0x84E0, 0x84E0, 0x8500, 0x84F0, + 0x84F0, 0x84C0, 0x84F0, 0x8500, 0x8500, 0x8510, 0x8520, 0x8530, 0x8550, 0x8580, 0x8590, 0x85D0, 0x8610, 0x8690, 0x8730, 0x8820, + 0x8970, 0x8BC0, 0x8E40, 0x9190, 0x9560, 0x9990, 0x9E30, 0xA1E0, 0xA540, 0xA890, 0xAAB0, 0xADB0, 0xB0E0, 0xB370, 0xB5E0, 0xB860, + 0xBB30, 0xBEB0, 0xC230, 0xC5E0, 0xC930, 0xCD20, 0xCFA0, 0xD130, 0xD310, 0xD530, 0xD8C0, 0xDC80, 0xE0D0, 0xE520, 0xE880, 0xEBF0, + 0xEEB0, 0xF160, 0xF460, 0xF6F0, 0xF970, 0xFBC0, 0xFE90, 0x0250, 0x04C0, 0x06E0, 0x0910, 0x0AB0, 0x0C90, 0x0DA0, 0x0F80, 0x1210, + 0x1400, 0x1550, 0x1680, 0x1770, 0x18A0, 0x1A10, 0x1C90, 0x1E80, 0x2060, 0x22B0, 0x2360, 0x2540, 0x2600, 0x26C0, 0x2920, 0x2B40, + 0x2D50, 0x2EF0, 0x30C0, 0x31D0, 0x3210, 0x3330, 0x33E0, 0x35C0, 0x36F0, 0x37D0, 0x38A0, 0x3990, 0x39F0, 0x39C0, 0x39C0, 0x3950, + 0x3820, 0x3730, 0x36A0, 0x3610, 0x35A0, 0x3490, 0x3270, 0x30B0, 0x2E20, 0x2C60, 0x2A90, 0x2890, 0x2760, 0x2490, 0x2330, 0x20C0, + 0x1F20, 0x1E10, 0x1D30, 0x1D70, 0x1D20, 0x1D10, 0x1E40, 0x1F00, 0x2010, 0x2110, 0x21B0, 0x23C0, 0x25E0, 0x2810, 0x2A20, 0x2C10, + 0x2DF0, 0x2E20, 0x2E60, 0x2F10, 0x2FB0, 0x30F0, 0x3200, 0x31F0, 0x31B0, 0x3070, 0x2F50, 0x2DC0, 0x2BD0, 0x29F0, 0x27C0, 0x2650, + 0x2470, 0x2290, 0x2090, 0x1DF0, 0x1B60, 0x18C0, 0x1670, 0x1490, 0x1220, 0x10E0, 0x0EA0, 0x0D60, 0x0C90, 0x0B10, 0x09B0, 0x0860, + 0x06C0, 0x0630, 0x0520, 0x0520, 0x04F0, 0x0430, 0x0340, 0x0180, 0x0150, 0x0100, 0xFFE0, 0x00A0, 0xFFC0, 0xFFF0, 0xFFF0, 0xFFF0, + 0x00B0, 0x00C0, 0x0150, 0x0190, 0x00D0, 0x0170, 0x01F0, 0x0330, 0x03F0, 0x0480, 0x0510, 0x0580, 0x0570, 0x05C0, 0x0630, 0x06E0, + 0x0810, 0x0910, 0x0A50, 0x0B20, 0x0BD0, 0x0CD0, 0x0E70, 0x1070, 0x1280, 0x1520, 0x17B0, 0x18F0, 0x2120, 0x2240, 0x2340, 0x23B0, + 0x2560, 0x2640, 0x27F0, 0x29F0, 0x2AB0, 0x2BC0, 0x2C50, 0x2CE0, 0x2E20, 0x2F50, 0x3150, 0x3360, 0x33E0, 0x3510, 0x3500, 0x3520, + 0x34F0, 0x33B0, 0x3320, 0x3200, 0x3210, 0x3150, 0x30E0, 0x3010, 0x2ED0, 0x2DE0, 0x2D20, 0x2AF0, 0x2A50, 0x28D0, 0x2760, 0x26C0, + 0x2560, 0x2540, 0x2460, 0x2350, 0x2290, 0x2170, 0x21A0, 0x2110, 0x2090, 0x2000, 0x1F50, 0x1F80, 0x1F40, 0x21A0, 0x21D0, 0x21B0, + 0x21E0, 0x21C0, 0x2260, 0x2370, 0x24F0, 0x2630, 0x2700, 0x2760, 0x2810, 0x2930, 0x2AE0, 0x2C40, 0x2D20, 0x2D80, 0x2DF0, 0x2F00, + 0x30A0, 0x31F0, 0x3510, 0x36B0, 0x3950, 0x3AB0, 0x3B70, 0x3DA0, 0x3F90, 0x4310, 0x4640, 0x4840, 0x4B10, 0x4D20, 0x4FE0, 0x5270, + 0x5590, 0x5900, 0x5C00, 0x5ED0, 0x6110, 0x63A0, 0x66F0, 0x69A0, 0x6CA0, 0x6F40, 0x7090, 0x7290, 0x7440, 0x75F0, 0x7800, 0x79C0, + 0x7BA0, 0x7C90, 0x7D90, 0x7E00, 0x7E70, 0x7ED0, 0x7EF0, 0x7F70, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EA0, + 0x7E40, 0x7C70, 0x7AA0, 0x7890, 0x76F0, 0x74E0, 0x71F0, 0x6EC0, 0x6A00, 0x6630, 0x61E0, 0x5D10, 0x5A30, 0x5560, 0x5160, 0x4D50, + 0x4990, 0x46E0, 0x4400, 0x4130, 0x3DE0, 0x3A00, 0x3790, 0x3480, 0x31E0, 0x2F80, 0x2CD0, 0x2B30, 0x27C0, 0x24D0, 0x2220, 0x2020, + 0x1F00, 0x1D10, 0x1B10, 0x1830, 0x1520, 0x12F0, 0x1160, 0x10A0, 0x0FC0, 0x0E30, 0x0BB0, 0x0900, 0x05F0, 0x0350, 0x00E0, 0xFF50, + 0xFD70, 0xFA30, 0xF600, 0xF1C0, 0xEE10, 0xEA30, 0xE5E0, 0xE1F0, 0xDDB0, 0xD8C0, 0xD3C0, 0xCE10, 0xC850, 0xC2C0, 0xBD40, 0xB720, + 0xAFF0, 0xA880, 0xA0D0, 0x99A0, 0x9250, 0x8C50, 0x88B0, 0x86A0, 0x85B0, 0x8540, 0x8510, 0x84F0, 0x84E0, 0x84D0, 0x84D0, 0x84C0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84F0, 0x84F0, + 0x84D0, 0x84D0, 0x8490, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8510, 0x8520, 0x8540, 0x8560, 0x8590, 0x85E0, 0x8630, 0x8680, 0x8700, + 0x87C0, 0x88C0, 0x89D0, 0x8BA0, 0x8DF0, 0x9050, 0x9320, 0x9620, 0x9930, 0x9BE0, 0x9E30, 0xA0F0, 0xA300, 0xA5B0, 0xA8C0, 0xABC0, + 0xAE30, 0xB140, 0xB3E0, 0xB660, 0xB7B0, 0xB990, 0xBB30, 0xBDC0, 0xBF70, 0xC0A0, 0xC200, 0xC310, 0xC410, 0xC5A0, 0xC710, 0xC7F0, + 0xC910, 0xC960, 0xCA30, 0xCA70, 0xCB70, 0xCB90, 0xCBF0, 0xCCB0, 0xCD00, 0xCE40, 0xCEA0, 0xCEF0, 0xD010, 0xD0F0, 0xD2F0, 0xD360, + 0xD470, 0xD570, 0xD660, 0xD740, 0xD7B0, 0xD820, 0xD820, 0xD880, 0xD810, 0xD910, 0xDA60, 0xDB80, 0xDC90, 0xDD20, 0xDD40, 0xDDA0, + 0xDE00, 0xDE90, 0xDF60, 0xDFD0, 0xE030, 0xE070, 0xE010, 0xE070, 0xE130, 0xE1F0, 0xE240, 0xE1C0, 0xE1A0, 0xE1C0, 0xE1C0, 0xE210, + 0xE270, 0xE1E0, 0xE1D0, 0xE1A0, 0xE0E0, 0xE0A0, 0xDFF0, 0xE010, 0xDFC0, 0xDF60, 0xDEB0, 0xDDB0, 0xDC70, 0xDC10, 0xDB70, 0xDA80, + 0xD990, 0xD8B0, 0xD790, 0xD7E0, 0xD860, 0xD800, 0xD7B0, 0xD650, 0xD580, 0xD470, 0xD3F0, 0xD380, 0xD3D0, 0xD3D0, 0xD300, 0xD1B0, + 0xD030, 0xCFA0, 0xCF60, 0xCF10, 0xCF30, 0xCEE0, 0xCEE0, 0xCEA0, 0xCEF0, 0xCEE0, 0xCF10, 0xCF80, 0xD030, 0xD0A0, 0xD150, 0xD230, + 0xD2A0, 0xD3E0, 0xD4F0, 0xD5E0, 0xD6C0, 0xD7C0, 0xD9C0, 0xDC50, 0xDDE0, 0xDF70, 0xDFD0, 0xDFF0, 0xDFB0, 0xE020, 0xE070, 0xE130, + 0xE280, 0xE3B0, 0xE480, 0xE530, 0xE500, 0xE4D0, 0xE3F0, 0xE370, 0xE270, 0xE1C0, 0xE110, 0xE170, 0xE240, 0xE2F0, 0xE310, 0xE260, + 0xE0C0, 0xDF00, 0xDCB0, 0xDB60, 0xDA20, 0xD950, 0xD730, 0xD550, 0xD290, 0xCE90, 0xCBB0, 0xC980, 0xC750, 0xC4E0, 0xC210, 0xBED0, + 0xBC10, 0xBA10, 0xB8A0, 0xB780, 0xB690, 0xB520, 0xB410, 0xB240, 0xB110, 0xB100, 0xB0D0, 0xB140, 0xB180, 0xB290, 0xB320, 0xB460, + 0xB680, 0xB8C0, 0xBB70, 0xBCE0, 0xBF30, 0xC140, 0xC3D0, 0xC750, 0xCA50, 0xCD20, 0xCFA0, 0xD1A0, 0xD370, 0xD530, 0xD710, 0xD930, + 0xDB50, 0xDCA0, 0xDD30, 0xDCF0, 0xDD00, 0xDDF0, 0xDE50, 0xDDB0, 0xDC70, 0xD9E0, 0xD660, 0xD250, 0xCDB0, 0xC8D0, 0xC410, 0xBE00, + 0xB810, 0xB180, 0xAB00, 0xA410, 0x9DB0, 0x9650, 0x8FB0, 0x8AE0, 0x87D0, 0x8670, 0x85D0, 0x8590, 0x8580, 0x8580, 0x85A0, 0x85D0, + 0x8640, 0x8730, 0x8950, 0x8E80, 0x9630, 0x9E10, 0xA5B0, 0xAD40, 0xB370, 0xB8D0, 0xBE30, 0xC2E0, 0xC740, 0xCBF0, 0xD040, 0xD470, + 0xDA20, 0xDEE0, 0xE3C0, 0xE770, 0xEA30, 0xED30, 0xEFC0, 0xF250, 0xF480, 0xF720, 0xF9F0, 0xFC00, 0xFE60, 0x0060, 0x0210, 0x03B0, + 0x04E0, 0x0600, 0x0790, 0x07B0, 0x08A0, 0x08E0, 0x08D0, 0x08E0, 0x0940, 0x0950, 0x08B0, 0x0780, 0x0700, 0x05D0, 0x0590, 0x05E0, + 0x05C0, 0x0640, 0x0580, 0x0540, 0x0490, 0x0490, 0x0420, 0x0410, 0x0510, 0x0550, 0x05F0, 0x06F0, 0x0730, 0x07A0, 0x0700, 0x0630, + 0x0580, 0x03C0, 0x0350, 0x0290, 0x0160, 0x00B0, 0x0010, 0xFF60, 0xFDC0, 0xFC40, 0xFA80, 0xF880, 0xF740, 0xF5F0, 0xF450, 0xF270, + 0xF090, 0xEEF0, 0xEDE0, 0xEC60, 0xEC20, 0xEAF0, 0xE8E0, 0xE720, 0xE450, 0xE290, 0xDFE0, 0xDDC0, 0xDA50, 0xD710, 0xD330, 0xCEE0, + 0xCA80, 0xC640, 0xC1C0, 0xBCD0, 0xB7D0, 0xB240, 0xAC90, 0xA620, 0xA0B0, 0x9AE0, 0x93F0, 0x8EA0, 0x8A40, 0x87A0, 0x8610, 0x8560, + 0x8510, 0x84F0, 0x84E0, 0x84C0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x84B0, + 0x8490, 0x8470, 0x8470, 0x8450, 0x8470, 0x8470, 0x84A0, 0x8480, 0x84B0, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, + 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x8500, 0x8510, 0x8530, 0x8530, 0x8550, + 0x8560, 0x8570, 0x8590, 0x8590, 0x8590, 0x85B0, 0x85C0, 0x85E0, 0x85F0, 0x8660, 0x86D0, 0x8750, 0x87C0, 0x8800, 0x8860, 0x88C0, + 0x88E0, 0x88F0, 0x8940, 0x8920, 0x88C0, 0x8800, 0x8740, 0x86A0, 0x8600, 0x8580, 0x8550, 0x8500, 0x84E0, 0x84F0, 0x84B0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8470, + 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83C0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, 0x83C0, 0x83A0, 0x83C0, 0x83C0, 0x83F0, + 0x83F0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, + 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x8490, + 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x84F0, 0x8510, 0x8540, 0x85B0, 0x8680, 0x88E0, 0x8F80, 0x9A70, 0xA590, + 0xB2D0, 0xC030, 0xCE40, 0xDD10, 0xEAF0, 0xF910, 0x0560, 0x1130, 0x1B90, 0x2650, 0x2F70, 0x3730, 0x3E60, 0x4460, 0x49D0, 0x4EF0, + 0x5380, 0x5800, 0x5CB0, 0x6030, 0x6400, 0x6740, 0x6AC0, 0x6EB0, 0x7280, 0x7710, 0x7B10, 0x7E40, 0x7EF0, 0x7F10, 0x7F00, 0x7EE0, + 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F70, + 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F20, + 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F80, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, + 0x7F80, 0x7EF0, 0x7F20, 0x7ED0, 0x7F10, 0x7F70, 0x7F20, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, + 0x7F20, 0x7EC0, 0x7ED0, 0x7F00, 0x7F30, 0x7F10, 0x7E90, 0x7EB0, 0x7EA0, 0x7EF0, 0x7F10, 0x7EB0, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, + 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7F30, 0x7EF0, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, + 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F00, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7C80, 0x70C0, 0x65B0, 0x5AD0, 0x5000, 0x4640, 0x3E30, 0x3790, + 0x3330, 0x2FB0, 0x2D80, 0x2B70, 0x2980, 0x2A40, 0x2D00, 0x3230, 0x39A0, 0x43C0, 0x5030, 0x5BE0, 0x66C0, 0x7150, 0x7A30, 0x7EF0, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F90, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F30, 0x7F20, 0x7E80, + 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, + 0x7F00, 0x7F00, 0x7EF0, 0x7E90, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, + 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F20, 0x7F30, 0x7F00, 0x7F30, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F30, 0x7EE0, 0x7ED0, + 0x7EF0, 0x7F20, 0x7F60, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7F30, 0x7EE0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, + 0x7F00, 0x7F10, 0x7F10, 0x7EB0, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EF0, + 0x7F10, 0x7EF0, 0x7EF0, 0x7F70, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, + 0x7EF0, 0x7F00, 0x7F40, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E70, 0x7ED0, 0x7F10, 0x7F20, 0x7EF0, 0x7E90, 0x7F00, + 0x7F20, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F40, + 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F70, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EC0, + 0x7F10, 0x7EF0, 0x7F70, 0x7EF0, 0x7EC0, 0x7F00, 0x7ED0, 0x7F10, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F00, 0x7F20, 0x7ED0, 0x7EB0, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F10, + 0x7F10, 0x7F20, 0x7EE0, 0x7F70, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7F10, 0x7EF0, + 0x7EF0, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, 0x7F00, + 0x7EC0, 0x7ED0, 0x7EF0, 0x7F30, 0x7EF0, 0x7ED0, 0x7F00, 0x7EE0, 0x7F30, 0x7F10, 0x7E90, 0x7EC0, 0x7EF0, 0x7F30, 0x7EE0, 0x7E90, + 0x7ED0, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, + 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x75F0, 0x6B10, 0x60B0, 0x5570, + 0x4AC0, 0x3EF0, 0x33B0, 0x29C0, 0x2050, 0x1890, 0x1230, 0x0B40, 0x03D0, 0xFC70, 0xF320, 0xEB50, 0xE4B0, 0xDF20, 0xDA40, 0xD4D0, + 0xCFB0, 0xC940, 0xC240, 0xB9A0, 0xB050, 0xA640, 0x9B60, 0x90F0, 0x89C0, 0x8690, 0x8560, 0x8510, 0x84E0, 0x84D0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, + 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84F0, 0x84D0, 0x84C0, 0x84C0, 0x8460, 0x84D0, 0x84E0, + 0x8500, 0x8510, 0x8530, 0x8580, 0x8600, 0x86F0, 0x8850, 0x8A40, 0x8CC0, 0x9010, 0x9360, 0x9730, 0x9B10, 0xA020, 0xA4A0, 0xA7D0, + 0xAA70, 0xAC90, 0xAFD0, 0xB350, 0xB710, 0xBB50, 0xBEA0, 0xC240, 0xC4A0, 0xC7C0, 0xCA60, 0xCD30, 0xD0D0, 0xD4C0, 0xD7F0, 0xDAD0, + 0xDD30, 0xDFA0, 0xE250, 0xE4F0, 0xE860, 0xEAE0, 0xECF0, 0xEF70, 0xF130, 0xF3A0, 0xF450, 0xF5B0, 0xF560, 0xF3F0, 0xF310, 0xF170, + 0xF120, 0xF190, 0xF1B0, 0xF1E0, 0xF1C0, 0xF0C0, 0xEEA0, 0xEC10, 0xE950, 0xE680, 0xE360, 0xDFA0, 0xDA40, 0xD500, 0xCF20, 0xC8C0, + 0xC250, 0xBB70, 0xB440, 0xAC40, 0xA3E0, 0x9C10, 0x94D0, 0x8ED0, 0x89D0, 0x8710, 0x85E0, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x84D0, + 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, + 0x84E0, 0x84F0, 0x84F0, 0x8510, 0x8500, 0x8510, 0x8520, 0x8570, 0x8550, 0x8570, 0x8590, 0x85B0, 0x85E0, 0x8600, 0x8650, 0x86C0, + 0x8730, 0x87C0, 0x8850, 0x88A0, 0x88F0, 0x89C0, 0x8A70, 0x8B80, 0x8C20, 0x8D00, 0x8DC0, 0x8E60, 0x8F80, 0x9080, 0x9240, 0x9400, + 0x9530, 0x96C0, 0x97A0, 0x9980, 0x9BA0, 0x9ED0, 0xA240, 0xA600, 0xA920, 0xACC0, 0xAFE0, 0xB370, 0xB650, 0xB8C0, 0xBA90, 0xBB80, + 0xBBD0, 0xBBD0, 0xBB80, 0xBBE0, 0xBB10, 0xBA40, 0xB960, 0xB8B0, 0xB710, 0xB5D0, 0xB400, 0xB1C0, 0xAEF0, 0xABC0, 0xA930, 0xA7A0, + 0xA6E0, 0xA610, 0xA440, 0xA230, 0xA080, 0x9EC0, 0x9CE0, 0x9C00, 0x9AB0, 0x9A30, 0x9A40, 0x9A90, 0x9A80, 0x9A50, 0x9A60, 0x9A50, + 0x9AE0, 0x9C10, 0x9D60, 0x9E30, 0x9EF0, 0x9F50, 0x9FA0, 0x9FF0, 0xA000, 0xA030, 0xA140, 0xA210, 0xA260, 0xA260, 0xA250, 0xA1F0, + 0xA190, 0xA1B0, 0xA260, 0xA290, 0xA310, 0xA2D0, 0xA2F0, 0xA200, 0xA1A0, 0xA210, 0xA1B0, 0xA190, 0xA110, 0xA050, 0x9FE0, 0x9FF0, + 0xA0C0, 0xA200, 0xA310, 0xA330, 0xA340, 0xA330, 0xA370, 0xA500, 0xA730, 0xA930, 0xABB0, 0xADF0, 0xB030, 0xB2D0, 0xB560, 0xB7E0, + 0xBA50, 0xBC50, 0xBDC0, 0xBFE0, 0xC310, 0xC5E0, 0xC900, 0xCC50, 0xCF60, 0xD1D0, 0xD4E0, 0xD780, 0xDAA0, 0xDE10, 0xE0E0, 0xE3F0, + 0xE630, 0xE910, 0xEC00, 0xEF10, 0xF270, 0xF580, 0xF800, 0xFA70, 0xFB90, 0xFD30, 0xFF20, 0x01E0, 0x04F0, 0x07F0, 0x09C0, 0x0B50, + 0x0B90, 0x0C50, 0x0DA0, 0x0F90, 0x11D0, 0x1400, 0x1610, 0x17B0, 0x18F0, 0x1A60, 0x1BC0, 0x1D00, 0x1EA0, 0x2000, 0x2120, 0x2200, + 0x22D0, 0x2360, 0x23D0, 0x22B0, 0x2120, 0x1FD0, 0x1DF0, 0x1C80, 0x1AA0, 0x18D0, 0x16D0, 0x1430, 0x1170, 0x0DF0, 0x0AB0, 0x0860, + 0x0680, 0x0500, 0x0380, 0x01B0, 0x0060, 0xFF40, 0xFF70, 0x00A0, 0x02A0, 0x0600, 0x0AD0, 0x1100, 0x1820, 0x20D0, 0x2A10, 0x34C0, + 0x3FF0, 0x4BD0, 0x5830, 0x64A0, 0x7140, 0x7C80, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7EE0, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F70, 0x7EF0, 0x7EB0, 0x7F20, 0x7F40, 0x7F40, + 0x7ED0, 0x7E70, 0x7EF0, 0x7F10, 0x7EF0, 0x7E70, 0x7E60, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7BF0, + 0x6A00, 0x5660, 0x3CF0, 0x1E60, 0xFDE0, 0xDB20, 0xC030, 0xACE0, 0xA1C0, 0xA010, 0xA950, 0xBD40, 0xDC30, 0x0280, 0x32B0, 0x5F20, + 0x7ED0, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7F10, + 0x7F00, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F10, 0x7EF0, 0x7E90, 0x7EF0, 0x7F20, 0x7E50, 0x7A90, 0x7900, 0x79A0, 0x7B90, 0x7C90, 0x7DA0, + 0x7E00, 0x7EE0, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7EF0, 0x7F40, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, + 0x7F50, 0x7F00, 0x7F20, 0x74D0, 0x6630, 0x5CA0, 0x5540, 0x4F50, 0x4970, 0x41E0, 0x3950, 0x2E50, 0x2180, 0x12F0, 0x0550, 0xF8E0, + 0xF020, 0xEAC0, 0xE880, 0xE6D0, 0xE3A0, 0xDE80, 0xD430, 0xC620, 0xB530, 0xA1C0, 0x8E40, 0x8600, 0x84E0, 0x84B0, 0x8480, 0x8470, + 0x8450, 0x8440, 0x8430, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x8410, + 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x8400, 0x8430, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8480, 0x8460, 0x8470, 0x8480, 0x8490, + 0x8490, 0x84B0, 0x84D0, 0x84E0, 0x8520, 0x85C0, 0x8800, 0x8E80, 0x98F0, 0xA360, 0xAC50, 0xB560, 0xBD90, 0xC520, 0xCBB0, 0xCFE0, + 0xD3C0, 0xD570, 0xD5D0, 0xD670, 0xD6A0, 0xD650, 0xD550, 0xD320, 0xD060, 0xCCD0, 0xC9E0, 0xC680, 0xC2F0, 0xBF70, 0xBA80, 0xB400, + 0xAD50, 0xA690, 0xA050, 0x88A0, 0x8670, 0x8590, 0x8530, 0x8510, 0x8500, 0x8510, 0x84F0, 0x84F0, 0x84E0, 0x84F0, 0x8510, 0x8530, + 0x8560, 0x85B0, 0x8640, 0x8750, 0x88F0, 0x8BA0, 0x9020, 0x9490, 0x9740, 0x9920, 0x99E0, 0x9B50, 0x9C60, 0x9E30, 0xA040, 0xA1E0, + 0xA340, 0xA3B0, 0xA3A0, 0xA3B0, 0xA4F0, 0xA620, 0xA790, 0xA870, 0xAA50, 0xAC90, 0xB120, 0xB720, 0xBEF0, 0xC790, 0xD030, 0xDAC0, + 0xE540, 0xF220, 0xFE50, 0x0A30, 0x1590, 0x1E70, 0x2510, 0x2A80, 0x2E70, 0x3130, 0x31D0, 0x2FB0, 0x2B60, 0x2470, 0x1CF0, 0x14E0, + 0x0C40, 0x05A0, 0xFEF0, 0xF860, 0xF0E0, 0xE870, 0xE050, 0xD7E0, 0xCF90, 0xC7B0, 0xBF90, 0xB770, 0xAEF0, 0xA800, 0xA1B0, 0x9C00, + 0x9720, 0x92B0, 0x8E60, 0x8AB0, 0x8800, 0x8680, 0x85C0, 0x85A0, 0x8550, 0x8540, 0x8550, 0x8590, 0x85B0, 0x8620, 0x8730, 0x8930, + 0x8CA0, 0x90C0, 0x9610, 0x9BD0, 0xA290, 0xAA90, 0xB2D0, 0xBC70, 0xC500, 0xCE90, 0xD810, 0xE260, 0xEC00, 0xF5F0, 0xFFD0, 0x0900, + 0x12D0, 0x1C10, 0x24D0, 0x2E60, 0x37B0, 0x4070, 0x4970, 0x5160, 0x59D0, 0x6230, 0x68E0, 0x6F50, 0x7430, 0x79A0, 0x7D60, 0x7EF0, + 0x7F10, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, + 0x7F00, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7D30, 0x78B0, 0x7360, 0x6CC0, 0x64D0, 0x5C00, 0x50E0, 0x4520, 0x3830, 0x2D40, 0x22A0, + 0x1950, 0x1100, 0x09E0, 0x0410, 0xFEB0, 0xF8F0, 0xF250, 0xE970, 0xDF70, 0xD250, 0xC330, 0xB1D0, 0x9E20, 0x8B50, 0x8580, 0x84E0, + 0x84C0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, + 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8530, 0x8650, 0x8DA0, 0xA210, 0xB6B0, 0xCBF0, 0xDF70, 0xF270, 0x0360, 0x13F0, 0x22D0, + 0x3130, 0x3E60, 0x4960, 0x5470, 0x5C70, 0x62F0, 0x6850, 0x6B10, 0x6DB0, 0x6F10, 0x6F50, 0x6F90, 0x6EC0, 0x6E80, 0x6DA0, 0x6C60, + 0x6BE0, 0x6AD0, 0x6990, 0x6720, 0x6320, 0x5D70, 0x55C0, 0x4E10, 0x4600, 0x3EB0, 0x3920, 0x3540, 0x33D0, 0x33B0, 0x3400, 0x35F0, + 0x3860, 0x3CB0, 0x4240, 0x4890, 0x5030, 0x5700, 0x5D60, 0x6410, 0x68C0, 0x6D20, 0x6F90, 0x70B0, 0x7160, 0x70C0, 0x6F50, 0x6DE0, + 0x6AF0, 0x6880, 0x6530, 0x6260, 0x5FE0, 0x5ED0, 0x6210, 0x6800, 0x7370, 0x7E70, 0x7F30, 0x7EF0, 0x7E90, 0x7ED0, 0x7F00, 0x7F00, + 0x7F10, 0x7E90, 0x7ED0, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x1390, 0xF4A0, 0xD8C0, 0xC0E0, 0xACE0, 0x9B10, + 0x8CE0, 0x86C0, 0x8530, 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, + 0x8420, 0x8430, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, + 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8470, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x84B0, 0x84A0, 0x84C0, 0x84F0, 0x8580, 0x88C0, 0x9930, 0xAA80, 0xB8D0, 0xC600, 0xD160, + 0xDA50, 0xE3B0, 0xEC10, 0xF470, 0xFD80, 0x0600, 0x0EB0, 0x1890, 0x2130, 0x2930, 0x30A0, 0x3620, 0x3AF0, 0x3E30, 0x4100, 0x4360, + 0x4630, 0x4900, 0x4A60, 0x4A70, 0x49F0, 0x4870, 0x4640, 0x4390, 0x4030, 0x3CE0, 0x3890, 0x33F0, 0x2F50, 0x2AE0, 0x26E0, 0x2290, + 0x1E70, 0x1A50, 0x14D0, 0x0F50, 0x0960, 0x03F0, 0xFE10, 0xF890, 0xF2E0, 0xECE0, 0xE670, 0xDEE0, 0xD780, 0xCFF0, 0xC7D0, 0xC070, + 0xBA50, 0xB580, 0xB1F0, 0xB0D0, 0xB0F0, 0xB290, 0xB5C0, 0xB9E0, 0xBDF0, 0xC1D0, 0xC5C0, 0xCA60, 0xCFA0, 0xD650, 0xDC60, 0xE2E0, + 0xE950, 0xEE50, 0xF370, 0xF7C0, 0xFB40, 0xFE10, 0xFFF0, 0x0250, 0x0540, 0x0710, 0x08A0, 0x0A00, 0x0AD0, 0x0A70, 0x0960, 0x07B0, + 0x0630, 0x0620, 0x05C0, 0x0610, 0x06D0, 0x0720, 0x0940, 0x0C50, 0x11A0, 0x17C0, 0x1F90, 0x2870, 0x3240, 0x3C90, 0x4780, 0x5170, + 0x5BA0, 0x64F0, 0x6BB0, 0x70A0, 0x73C0, 0x75D0, 0x77F0, 0x7A20, 0x7CA0, 0x7E40, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7EA0, 0x7F20, + 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F80, 0x7F10, + 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F00, 0x7EE0, + 0x7ED0, 0x7EF0, 0x7F60, 0x7F20, 0x7E90, 0x7EB0, 0x7EE0, 0x7F30, 0x7F10, 0x7E70, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, + 0x7F00, 0x7F00, 0x7F10, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7F10, + 0x7F20, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F80, 0x7EF0, 0x7EE0, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7ED0, + 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F30, 0x7ED0, 0x7E90, 0x7F10, + 0x7F20, 0x7F10, 0x7F10, 0x7EB0, 0x7F20, 0x7EF0, 0x6610, 0x45A0, 0x2240, 0xFEF0, 0xDFA0, 0xC6D0, 0xB8F0, 0xB570, 0xBD60, 0xCD60, + 0xDF10, 0xEEF0, 0xF900, 0xFD00, 0xFBF0, 0xF830, 0xF470, 0xF300, 0xF530, 0xFAB0, 0x0180, 0x0940, 0x0F10, 0x1270, 0x1400, 0x1290, + 0x10F0, 0x0EC0, 0x0D50, 0x0C90, 0x0CD0, 0x0E40, 0x0E90, 0x0DD0, 0x0CB0, 0x0B00, 0x0980, 0x08E0, 0x0920, 0x0A40, 0x0C30, 0x1060, + 0x1520, 0x1BC0, 0x24B0, 0x3000, 0x3B40, 0x6860, 0x70C0, 0x7760, 0x7C40, 0x7ED0, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, + 0x7ED0, 0x7F00, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7EF0, + 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7EB0, 0x7CE0, 0x79C0, + 0x7780, 0x7590, 0x7370, 0x72E0, 0x7100, 0x6F10, 0x6C20, 0x6910, 0x6730, 0x6460, 0x61C0, 0x5E80, 0x5AF0, 0x5860, 0x55A0, 0x51D0, + 0x4E60, 0x49A0, 0x4510, 0x3F10, 0x38B0, 0x31A0, 0x29F0, 0x22F0, 0x1B20, 0x1380, 0x0C90, 0x0540, 0xFEE0, 0xF850, 0xF1B0, 0xEB00, + 0xE4E0, 0xDEF0, 0xD930, 0xD340, 0xCCC0, 0xC5D0, 0xBF30, 0xB740, 0xAEF0, 0xA670, 0x9CD0, 0x9460, 0x8D20, 0x8850, 0x8620, 0x8550, + 0x8500, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84F0, 0x8540, 0x8660, 0x8B40, + 0x98D0, 0xA700, 0xB570, 0xC2F0, 0xCFC0, 0xDC10, 0xE730, 0xF1F0, 0xFAF0, 0x0250, 0x0740, 0x0A40, 0x0B10, 0x0870, 0x0400, 0xFCC0, + 0xF260, 0xE690, 0xD980, 0xCC80, 0xBFD0, 0xB5E0, 0xAF70, 0xAC90, 0xAEE0, 0xB5D0, 0xBFF0, 0xCC60, 0xDB00, 0xEBA0, 0xFC80, 0x0DF0, + 0x2000, 0x30D0, 0x4280, 0x51E0, 0x6140, 0x6EF0, 0x7AB0, 0x7EF0, 0x7EF0, 0x7F90, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F70, 0x7F10, + 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F00, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F50, 0x7F10, 0x7EB0, + 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F00, + 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EE0, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, + 0x7EF0, 0x7F00, 0x7F10, 0x7F70, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, 0x7EF0, 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7EA0, + 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F00, 0x7EC0, 0x7F40, + 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F80, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, + 0x7590, 0x6980, 0x5C20, 0x4D80, 0x3DC0, 0x2DD0, 0x1DA0, 0x0BF0, 0xFCB0, 0xEDA0, 0xDE80, 0xD010, 0xC190, 0xB440, 0xA720, 0x9AF0, + 0x8F40, 0x88D0, 0x8630, 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84F0, 0x8500, 0x8520, 0x8560, 0x85D0, + 0x8670, 0x8770, 0x8900, 0x8B20, 0x8E20, 0x90C0, 0x9330, 0x94C0, 0x94E0, 0x92B0, 0x91E0, 0x90D0, 0x8FF0, 0x8E10, 0x8BD0, 0x8A20, + 0x8890, 0x8750, 0x8680, 0x85D0, 0x8590, 0x8550, 0x8530, 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84F0, 0x84E0, 0x8510, 0x84E0, 0x84F0, + 0x8520, 0x8520, 0x8540, 0x8570, 0x85B0, 0x8610, 0x86C0, 0x8780, 0x8870, 0x8930, 0x8990, 0x8970, 0x8890, 0x87B0, 0x8720, 0x86E0, + 0x86D0, 0x8720, 0x87F0, 0x8940, 0x8BB0, 0x8F70, 0x9520, 0x9BA0, 0xA230, 0xA950, 0xB130, 0xB840, 0xBF40, 0xC630, 0xCDC0, 0xD540, + 0xDDC0, 0xE690, 0xF000, 0xFB50, 0x0670, 0x1290, 0x1F50, 0x2C30, 0x3980, 0x4700, 0x5460, 0x6200, 0x6F70, 0x7A70, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7FA0, 0x7F10, 0x7F20, 0x7F30, + 0x7EF0, 0x7F50, 0x7F20, 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F00, + 0x7F10, 0x7F00, 0x7EE0, 0x7ED0, 0x7EB0, 0x7F20, 0x7F40, 0x7E80, 0x7EF0, 0x7F00, 0x7F00, 0x7F30, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, + 0x7EF0, 0x7E80, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7EB0, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7F10, 0x7F00, 0x7F20, + 0x7EF0, 0x7F50, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7F00, 0x7F00, 0x7B90, + 0x62B0, 0x59F0, 0x5C90, 0x64D0, 0x6C30, 0x6EF0, 0x6CC0, 0x6580, 0x5E20, 0x5B70, 0x5FB0, 0x6BB0, 0x7A70, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7E90, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F30, 0x7F10, 0x7F00, 0x7F20, + 0x7EF0, 0x7F80, 0x7F00, 0x7EF0, 0x7F30, 0x7F20, 0x7F80, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, + 0x7F60, 0x7F00, 0x7E10, 0x7D10, 0x7BB0, 0x7B50, 0x7B10, 0x79B0, 0x77A0, 0x71F0, 0x6530, 0x5240, 0x36A0, 0x14D0, 0xED70, 0xC8C0, + 0xA790, 0x8D80, 0x85F0, 0x8510, 0x84F0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84E0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84D0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8510, 0x8550, 0x85F0, 0x8720, 0x89C0, 0x8FA0, 0x9730, 0x9F70, + 0xA670, 0xACF0, 0xB380, 0xB9C0, 0xC0B0, 0xC710, 0xCE90, 0xE950, 0xF110, 0xF940, 0x01A0, 0x0B00, 0x13C0, 0x1CD0, 0x2630, 0x2EE0, + 0x38E0, 0x4190, 0x48B0, 0x4ED0, 0x52B0, 0x5570, 0x5720, 0x56F0, 0x5710, 0x55E0, 0x54E0, 0x5200, 0x4F00, 0x4C00, 0x4740, 0x41F0, + 0x3B30, 0x33C0, 0x2BB0, 0x22D0, 0x1A90, 0x10C0, 0x0750, 0xFE00, 0xF460, 0xEA50, 0xDF90, 0xD410, 0xC7F0, 0xBB80, 0xADC0, 0xA0A0, + 0x9390, 0x89F0, 0x8620, 0x8530, 0x84F0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84A0, 0x84B0, + 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x8500, 0x84E0, 0x84F0, 0x84E0, 0x8510, 0x8520, 0x8530, 0x8540, 0x8540, 0x8550, 0x8550, 0x8570, + 0x8580, 0x85B0, 0x85E0, 0x8630, 0x8670, 0x8700, 0x8780, 0x8860, 0x89B0, 0x8BB0, 0x8EF0, 0x9320, 0x9900, 0x9F60, 0xA590, 0xAC70, + 0xB2C0, 0xB830, 0xBDA0, 0xC210, 0xC5D0, 0xC950, 0xCD50, 0xD0F0, 0xD490, 0xD780, 0xD9C0, 0xDAC0, 0xDBF0, 0xDC30, 0xDC60, 0xDBB0, + 0xD9F0, 0xD7E0, 0xD560, 0xD1F0, 0xCDA0, 0xC7E0, 0xC1A0, 0xBA50, 0xB280, 0xA9A0, 0xA070, 0x97F0, 0x8FB0, 0x8A00, 0x86F0, 0x85C0, + 0x8550, 0x8510, 0x8500, 0x84E0, 0x84D0, 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, + 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x8500, 0x8520, 0x8530, 0x8540, 0x8560, 0x8580, + 0x85B0, 0x85F0, 0x8630, 0x8670, 0x86D0, 0x8700, 0x8720, 0x8710, 0x8780, 0x87A0, 0x87D0, 0x8790, 0x8770, 0x8730, 0x8720, 0x86B0, + 0x8680, 0x8670, 0x8660, 0x8640, 0x8630, 0x8620, 0x8620, 0x8600, 0x8610, 0x8620, 0x8630, 0x8620, 0x8660, 0x8630, 0x8660, 0x8690, + 0x86E0, 0x8740, 0x87A0, 0x87F0, 0x8840, 0x8850, 0x8880, 0x88C0, 0x8970, 0x8A80, 0x8BA0, 0x8C50, 0x8C90, 0x8C10, 0x8B10, 0x8990, + 0x8880, 0x87A0, 0x86E0, 0x8650, 0x85D0, 0x8590, 0x8560, 0x8540, 0x8530, 0x8530, 0x8530, 0x8530, 0x8530, 0x8540, 0x8560, 0x85A0, + 0x85D0, 0x85F0, 0x85F0, 0x85E0, 0x85D0, 0x85D0, 0x85D0, 0x85F0, 0x8610, 0x8610, 0x8600, 0x85F0, 0x85C0, 0x8590, 0x8560, 0x8530, + 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84E0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, + 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8510, 0x8520, 0x8530, + 0x8530, 0x8540, 0x8550, 0x8550, 0x8550, 0x8560, 0x8580, 0x85C0, 0x8600, 0x8640, 0x8670, 0x86B0, 0x86D0, 0x8730, 0x87D0, 0x88C0, + 0x89F0, 0x8B40, 0x8CE0, 0x8E30, 0x9010, 0x9190, 0x9350, 0x9420, 0x9550, 0x96B0, 0x9850, 0x9A40, 0x9BD0, 0x9D30, 0x9E40, 0x9E50, + 0x9D70, 0x9D10, 0x9CF0, 0x9DE0, 0x9F80, 0xA0F0, 0xA270, 0xA2D0, 0xA310, 0xA330, 0xA3D0, 0xA4A0, 0xA4E0, 0xA4C0, 0xA3A0, 0xA2D0, + 0xA260, 0xA250, 0xA320, 0xA460, 0xA4E0, 0xA480, 0xA3E0, 0xA310, 0xA2B0, 0xA210, 0xA250, 0xA290, 0xA180, 0xA0B0, 0xA000, 0x9F90, + 0xA040, 0xA130, 0xA220, 0xA2C0, 0xA2E0, 0xA260, 0xA220, 0xA240, 0xA340, 0xA3A0, 0xA330, 0xA2C0, 0xA1D0, 0xA110, 0xA110, 0xA0A0, + 0x9FD0, 0x9EC0, 0x9DB0, 0x9C40, 0x9AC0, 0x9900, 0x97C0, 0x9740, 0x97B0, 0x9850, 0x98F0, 0x9960, 0x9A30, 0x9B60, 0x9D70, 0x9F40, + 0xA120, 0xA3D0, 0xA650, 0xAAB0, 0xB070, 0xB650, 0xBC50, 0xC1F0, 0xD5D0, 0xDB30, 0xE040, 0xE450, 0xE7E0, 0xEA00, 0xEC30, 0xEDD0, + 0xEEB0, 0xEFA0, 0xEF70, 0xEF20, 0xEE50, 0xED40, 0xEBC0, 0xE8F0, 0xE550, 0xE090, 0xDB20, 0xD480, 0xCDE0, 0xC6B0, 0xBF70, 0xB700, + 0xAD50, 0xA270, 0x9690, 0x8BE0, 0x86B0, 0x8550, 0x8500, 0x84D0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, + 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x8500, 0x8560, 0x8660, + 0x8870, 0x8B90, 0x8DF0, 0x8EF0, 0x8E00, 0x8C40, 0x8A70, 0x88C0, 0x8780, 0x8670, 0x85D0, 0x8570, 0x8540, 0x8520, 0x8500, 0x84F0, + 0x84E0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8480, 0x8480, 0x8490, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x8500, + 0x8540, 0x85E0, 0x8790, 0x8D30, 0x96C0, 0xA0B0, 0xAA10, 0xB380, 0xBC30, 0xC440, 0xC9C0, 0xCEB0, 0xD3E0, 0xD950, 0xDFF0, 0xE7C0, + 0xF080, 0xF880, 0xFFC0, 0x0460, 0x0680, 0x06C0, 0x0490, 0x0230, 0xFE70, 0xF9E0, 0xF5A0, 0xF0D0, 0xEDC0, 0xEA90, 0xE890, 0xE830, + 0xE8A0, 0xE9D0, 0xEBF0, 0xEDE0, 0xF0F0, 0xF3D0, 0xF720, 0xFAE0, 0xFE90, 0x02D0, 0x06B0, 0x0AA0, 0x0EA0, 0x1280, 0x1620, 0x17B0, + 0x1830, 0x1730, 0x14E0, 0x11C0, 0x0C90, 0x07C0, 0x0210, 0xFB90, 0xF630, 0xF140, 0xECE0, 0xE950, 0xE520, 0xE180, 0xDDE0, 0xD9B0, + 0xD6B0, 0xD2D0, 0xD000, 0xCD00, 0xCA80, 0xC890, 0xC750, 0xC720, 0xC6F0, 0xC710, 0xC790, 0xC840, 0xCA50, 0xCC70, 0xCFA0, 0xD3E0, + 0xD820, 0xDF00, 0xE5F0, 0xEDF0, 0xF600, 0xFD70, 0x03E0, 0x0840, 0x0B90, 0x15A0, 0x1850, 0x1B70, 0x1EB0, 0x2140, 0x2350, 0x2520, + 0x26C0, 0x2750, 0x2890, 0x2930, 0x2A40, 0x2C10, 0x2D30, 0x2F20, 0x30D0, 0x3160, 0x3220, 0x3240, 0x31D0, 0x3230, 0x3320, 0x35E0, + 0x37F0, 0x3960, 0x3A80, 0x3AD0, 0x3BB0, 0x3C20, 0x3CE0, 0x3D90, 0x3E30, 0x3F70, 0x4050, 0x4110, 0x4170, 0x4170, 0x4180, 0x3FF0, + 0x3EA0, 0x3CC0, 0x3A90, 0x3900, 0x3780, 0x3590, 0x3330, 0x30A0, 0x2E20, 0x2AF0, 0x27D0, 0x24E0, 0x20D0, 0x1CC0, 0x17E0, 0x1240, + 0x0D90, 0x09D0, 0x06E0, 0x04C0, 0x0240, 0x0170, 0x00E0, 0x02C0, 0x06D0, 0x0CA0, 0x1460, 0x1C10, 0x2230, 0x2590, 0x24A0, 0x21B0, + 0x1C00, 0x1400, 0x0B90, 0x02F0, 0xFCF0, 0xF990, 0xF9B0, 0xFDE0, 0x0460, 0x0EA0, 0x1A30, 0x26B0, 0x3320, 0x4070, 0x4DF0, 0x5B30, + 0x6870, 0x7350, 0x7BF0, 0x7F00, 0x7F00, 0x7F90, 0x7EF0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, + 0x7ED0, 0x7E90, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7EF0, 0x7F50, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7F10, 0x7F10, 0x7EE0, + 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F50, 0x7F20, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, 0x7ED0, 0x7F00, 0x7F50, + 0x7F20, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F00, 0x7EF0, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F40, 0x7F10, 0x7F10, + 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, + 0x7F50, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7ED0, 0x7F00, 0x7EF0, 0x7F50, 0x7ED0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F30, + 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7ED0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, + 0x7F00, 0x7F20, 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, + 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F30, + 0x7F20, 0x7E90, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7E60, 0x7D90, 0x7C10, 0x7AE0, 0x7800, 0x75B0, 0x7260, 0x6E00, 0x6A50, + 0x6600, 0x61E0, 0x5E40, 0x59D0, 0x55B0, 0x5240, 0x4ED0, 0x4BF0, 0x48A0, 0x4570, 0x4290, 0x4130, 0x4060, 0x3ED0, 0x3E90, 0x3EE0, + 0x3F70, 0x4260, 0x4520, 0x4830, 0x4BE0, 0x4F20, 0x5240, 0x55B0, 0x59E0, 0x5E20, 0x6120, 0x6410, 0x66C0, 0x6850, 0x69D0, 0x6A90, + 0x6B40, 0x6B40, 0x6B10, 0x6A70, 0x69E0, 0x6850, 0x6710, 0x6620, 0x64E0, 0x6390, 0x61D0, 0x5FF0, 0x5D80, 0x5B50, 0x5860, 0x5560, + 0x51D0, 0x4D60, 0x48A0, 0x4400, 0x3E70, 0x37F0, 0x30B0, 0x27B0, 0x1E70, 0x1420, 0x0A60, 0x00D0, 0xF710, 0xEEA0, 0xE630, 0xDD50, + 0xD400, 0xCB40, 0xC260, 0xB980, 0xB0B0, 0xA8B0, 0xA120, 0x9A50, 0x93C0, 0x8D90, 0x89F0, 0x87D0, 0x86A0, 0x85E0, 0x8580, 0x8540, + 0x8520, 0x84F0, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8510, 0x8520, 0x8520, 0x8560, 0x8540, 0x8550, 0x8570, 0x8580, 0x8590, + 0x85A0, 0x85B0, 0x85D0, 0x85F0, 0x8600, 0x8620, 0x8620, 0x8620, 0x8630, 0x8640, 0x8640, 0x8650, 0x8660, 0x8680, 0x86A0, 0x86A0, + 0x86C0, 0x86C0, 0x86D0, 0x86F0, 0x8700, 0x8730, 0x8770, 0x8790, 0x87F0, 0x8880, 0x8940, 0x89B0, 0x8A60, 0x8B70, 0x8C90, 0x8E40, + 0x8FB0, 0x9170, 0x93F0, 0x9680, 0x9930, 0x9C70, 0xA030, 0xA3B0, 0xA780, 0xAB70, 0xAF50, 0xB2B0, 0xB6E0, 0xBAF0, 0xBEC0, 0xC2F0, + 0xC650, 0xC9F0, 0xCD60, 0xD0E0, 0xD3B0, 0xD660, 0xD8C0, 0xDAC0, 0xDCE0, 0xDE70, 0xE000, 0xE130, 0xE1E0, 0xE1B0, 0xE080, 0xDE60, + 0xDC70, 0xDA00, 0xD810, 0xD620, 0xD470, 0xD2E0, 0xD090, 0xCE40, 0xCBC0, 0xC990, 0xC800, 0xC6D0, 0xC6B0, 0xC700, 0xC850, 0xCAA0, + 0xCCA0, 0xCF90, 0xD220, 0xD510, 0xD840, 0xDB60, 0xDF00, 0xE340, 0xE7B0, 0xEC30, 0xF0E0, 0xF4B0, 0xF840, 0xFC30, 0x0050, 0x03F0, + 0x06B0, 0x0930, 0x0BC0, 0x0EF0, 0x1280, 0x1570, 0x18C0, 0x1BE0, 0x1DF0, 0x2120, 0x2300, 0x2530, 0x27F0, 0x2A70, 0x2E20, 0x3050, + 0x33A0, 0x35C0, 0x3870, 0x3AF0, 0x3C80, 0x3F00, 0x4090, 0x4230, 0x44A0, 0x4690, 0x49B0, 0x4D00, 0x4FE0, 0x5390, 0x56A0, 0x59C0, + 0x5C90, 0x5E90, 0x61A0, 0x6500, 0x6840, 0x6BB0, 0x6F20, 0x7340, 0x7680, 0x79B0, 0x7C60, 0x7E50, 0x7F10, 0x7F20, 0x7F60, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F50, 0x7EF0, 0x7F00, 0x7F40, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, + 0x7EF0, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, 0x7EE0, + 0x7ED0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7ED0, 0x7F00, 0x7F20, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, + 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F50, 0x7F10, 0x7F20, + 0x7F00, 0x7EF0, 0x7F50, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F00, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F50, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, + 0x7F20, 0x7F10, 0x7EB0, 0x7F10, 0x7EF0, 0x7460, 0x63F0, 0x4FC0, 0x3C70, 0x2950, 0x1710, 0x06A0, 0xF600, 0xE5D0, 0xD510, 0xC3C0, + 0xB160, 0xA000, 0x8F40, 0x86F0, 0x8520, 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x84A0, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8460, 0x84C0, 0x84F0, 0x8500, 0x8540, 0x85B0, 0x8700, 0x8A40, + 0x90B0, 0x97F0, 0x9F90, 0xA5A0, 0xAB80, 0xAF30, 0xB2C0, 0xB420, 0xB5B0, 0xB600, 0xB580, 0xB7C0, 0xB990, 0xBB40, 0xBCC0, 0xBE80, + 0xC100, 0xC410, 0xC7E0, 0xCB60, 0xCE90, 0xD1D0, 0xD410, 0xD710, 0xDA40, 0xDDB0, 0xE1A0, 0xE4D0, 0xE830, 0xEAC0, 0xED70, 0xF090, + 0xF330, 0xF6C0, 0xF9C0, 0xFB50, 0xFD40, 0xFDE0, 0xFED0, 0xFFD0, 0x00D0, 0x01C0, 0x0250, 0x0280, 0x01C0, 0x00F0, 0x01C0, 0x02C0, + 0x04E0, 0x0690, 0x0830, 0x09B0, 0x0AF0, 0x0D10, 0x1020, 0x1360, 0x16F0, 0x1A00, 0x1C80, 0x1F80, 0x22D0, 0x2770, 0x2B60, 0x3000, + 0x33D0, 0x36A0, 0x3960, 0x3AD0, 0x3B50, 0x3BA0, 0x3A90, 0x3A10, 0x38E0, 0x3760, 0x3710, 0x3710, 0x38F0, 0x3990, 0x3990, 0x3A20, + 0x39A0, 0x38B0, 0x3750, 0x3560, 0x3390, 0x30B0, 0x2D50, 0x2920, 0x2440, 0x1EB0, 0x1820, 0x1160, 0x0A30, 0x0260, 0xFAA0, 0xF2C0, + 0xEBB0, 0xE490, 0xDC00, 0xD1D0, 0xC630, 0xB920, 0xA8D0, 0x95B0, 0x8830, 0x8520, 0x84D0, 0x84A0, 0x8480, 0x8470, 0x8470, 0x8450, + 0x8440, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, + 0x83F0, 0x8400, 0x8440, 0x8440, 0x8430, 0x8440, 0x8460, 0x8450, 0x8460, 0x8470, 0x8480, 0x8480, 0x8490, 0x84D0, 0x84C0, 0x84B0, + 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8540, 0x8610, 0x8890, 0x91B0, 0x9E60, 0xA910, 0xB1B0, 0xB760, 0xBC40, 0xC060, 0xC400, 0xC7C0, + 0xCBD0, 0xD010, 0xD560, 0xDA20, 0xDF60, 0xE580, 0xEAE0, 0xEFD0, 0xF430, 0xF8B0, 0xFDE0, 0x0370, 0x0960, 0x0F00, 0x1440, 0x19B0, + 0x1F00, 0x2620, 0x2DD0, 0x35F0, 0x3E80, 0x4640, 0x4E90, 0x55B0, 0x5BF0, 0x62D0, 0x68B0, 0x6F00, 0x7440, 0x78B0, 0x7BA0, 0x7CE0, + 0x7D90, 0x7DB0, 0x7D70, 0x7CE0, 0x7B50, 0x7980, 0x76F0, 0x73D0, 0x71B0, 0x6E40, 0x6B60, 0x6680, 0x6030, 0x5960, 0x5180, 0x49D0, + 0x4320, 0x3C10, 0x3610, 0x2EA0, 0x26A0, 0x1DC0, 0x13D0, 0x0A00, 0xFE40, 0xF3F0, 0xE9E0, 0xE040, 0xD8A0, 0xD290, 0xCDF0, 0xCAA0, + 0xC870, 0xC6B0, 0xC520, 0xC3E0, 0xC290, 0xC2B0, 0xC350, 0xC3A0, 0xC420, 0xC530, 0xC600, 0xC800, 0xCB30, 0xCF70, 0xD500, 0xDA90, + 0xE050, 0xE640, 0xECC0, 0xF4F0, 0xFC60, 0x04F0, 0x0D90, 0x1630, 0x1F40, 0x2780, 0x3090, 0x39B0, 0x4350, 0x4C50, 0x5470, 0x5CE0, + 0x6480, 0x6B80, 0x7360, 0x7A80, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F50, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F00, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, + 0x7EF0, 0x7ED0, 0x7F10, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7DD0, 0x7080, 0x6040, 0x4E90, 0x3C70, 0x2B20, 0x1D10, 0x1450, 0x1270, 0x1700, 0x2120, + 0x2FA0, 0x3F80, 0x4F20, 0x5DD0, 0x6A90, 0x74A0, 0x7B60, 0x7E90, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7E60, 0x6A60, 0x5640, 0x4150, 0x2AE0, 0x16F0, 0x0280, 0xED80, 0xD8F0, 0xC560, 0xB460, 0xA5A0, 0x9B00, 0x92D0, + 0x8E00, 0x8A70, 0x8800, 0x8660, 0x8570, 0x8510, 0x84E0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, + 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84A0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84D0, 0x84D0, + 0x84E0, 0x8480, 0x84F0, 0x8500, 0x8530, 0x8520, 0x8530, 0x8560, 0x8520, 0x85D0, 0x8630, 0x86C0, 0x8790, 0x8870, 0x89B0, 0x8B30, + 0x8D70, 0x8F50, 0x9210, 0x94D0, 0x97D0, 0x9A90, 0x9E30, 0xA2C0, 0xA770, 0xABF0, 0xB160, 0xB5F0, 0xBAD0, 0xBF60, 0xC370, 0xC670, + 0xC8D0, 0xCB80, 0xCC90, 0xCDB0, 0xCDD0, 0xCD40, 0xCD70, 0xCC60, 0xCBA0, 0xCA90, 0xC8A0, 0xC770, 0xC690, 0xC4C0, 0xC2D0, 0xC030, + 0xBEF0, 0xBDB0, 0xBCE0, 0xBCC0, 0xBC50, 0xBC90, 0xBC30, 0xBC20, 0xBC40, 0xBB20, 0xBAA0, 0xB8A0, 0xB730, 0xB570, 0xB3E0, 0xB1D0, + 0xAFE0, 0xAE70, 0xABF0, 0xA940, 0xA730, 0xA580, 0xA440, 0xA2D0, 0xA230, 0xA220, 0xA250, 0xA3B0, 0xA560, 0xA7D0, 0xAB70, 0xAEF0, + 0xB320, 0xB760, 0xBC10, 0xC270, 0xCA20, 0xD1B0, 0xD9D0, 0xE1E0, 0xEA20, 0xF190, 0xF8B0, 0x00A0, 0x06F0, 0x0D00, 0x1120, 0x1370, + 0x1510, 0x14B0, 0x1420, 0x1280, 0x0EF0, 0x0B20, 0x0500, 0xFE90, 0xF730, 0xEF00, 0xE740, 0xDEA0, 0xD5B0, 0xCD60, 0xC3C0, 0xBA00, + 0xB120, 0xA880, 0xA010, 0x9880, 0x9240, 0x8D10, 0x85C0, 0x8560, 0x8530, 0x8560, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8510, + 0x8520, 0x8530, 0x8550, 0x8570, 0x85B0, 0x8610, 0x86B0, 0x87C0, 0x8910, 0x8AF0, 0x8DE0, 0x9200, 0x95A0, 0x9990, 0x9C50, 0x9E60, + 0xA110, 0xA310, 0xA4E0, 0xA6C0, 0xA8C0, 0xAAC0, 0xACC0, 0xAEC0, 0xB0A0, 0xB1B0, 0xB370, 0xB460, 0xB590, 0xB750, 0xB840, 0xBA60, + 0xBB50, 0xBC70, 0xBD40, 0xBD60, 0xBDD0, 0xBCC0, 0xBB00, 0xB9B0, 0xB830, 0xB6A0, 0xB480, 0xB150, 0xADF0, 0xA9F0, 0xA5E0, 0xA110, + 0x9D70, 0x99E0, 0x95D0, 0x9260, 0x8F30, 0x8C80, 0x8A70, 0x88B0, 0x8780, 0x86C0, 0x8640, 0x85F0, 0x85A0, 0x8570, 0x8530, 0x8510, + 0x8510, 0x8500, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, + 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, + 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8510, 0x8520, 0x8530, 0x8540, + 0x8550, 0x8570, 0x8590, 0x85D0, 0x8610, 0x8680, 0x86F0, 0x8790, 0x8850, 0x8950, 0x8A60, 0x8BC0, 0x8DD0, 0x9080, 0x9340, 0x95A0, + 0x97D0, 0x9A60, 0x9CB0, 0x9F20, 0xA200, 0xA4A0, 0xA7C0, 0xAA00, 0xAC40, 0xAE70, 0xB070, 0xB2C0, 0xB580, 0xB840, 0xBB30, 0xBC60, + 0xBDA0, 0xBF20, 0xC0B0, 0xC250, 0xC370, 0xC4B0, 0xC550, 0xC5C0, 0xC5C0, 0xC4F0, 0xC4E0, 0xC450, 0xC380, 0xC200, 0xC070, 0xBE60, + 0xBBF0, 0xBA20, 0xB8E0, 0xB690, 0xB3A0, 0xB080, 0xADA0, 0xAB00, 0xA770, 0xA3C0, 0xA090, 0x9CE0, 0x98F0, 0x94F0, 0x91E0, 0x8EB0, + 0x8C30, 0x8A00, 0x8840, 0x8700, 0x8630, 0x85B0, 0x8580, 0x8550, 0x8530, 0x8530, 0x8500, 0x8510, 0x8500, 0x8500, 0x8500, 0x8500, + 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8510, 0x8510, 0x8520, 0x8520, 0x8530, 0x8550, 0x8570, 0x8580, 0x85C0, 0x8610, 0x8650, + 0x86A0, 0x86F0, 0x8750, 0x8770, 0x87F0, 0x8820, 0x87E0, 0x8760, 0x86E0, 0x8670, 0x8610, 0x85C0, 0x8580, 0x8560, 0x8530, 0x8520, + 0x8500, 0x8500, 0x8510, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8520, 0x8580, + 0x86C0, 0x8D60, 0x9D40, 0xAE70, 0xC1B0, 0xD710, 0xEE00, 0x06C0, 0x20E0, 0x3B20, 0x5790, 0x6FA0, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, + 0x7EE0, 0x7F60, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7EA0, 0x7EC0, 0x7EC0, + 0x7F10, 0x7F20, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7930, 0x6C80, + 0x5F20, 0x4F40, 0x3ED0, 0x2EB0, 0x1E70, 0x1060, 0x02F0, 0xF860, 0xF120, 0xEBF0, 0xEAB0, 0xEA60, 0xEA50, 0xEA10, 0xE7F0, 0xE340, + 0xDB80, 0xD290, 0xC800, 0xBE60, 0xB4D0, 0xAB60, 0xA0E0, 0x9680, 0x8D60, 0x8820, 0x8630, 0x8590, 0x8560, 0x8570, 0x85E0, 0x8730, + 0x8CC0, 0x9A90, 0xA8C0, 0xB550, 0xC060, 0xC9F0, 0xD310, 0xDC00, 0xE660, 0xF0E0, 0xFB50, 0x0670, 0x0F00, 0x1710, 0x1E30, 0x23C0, + 0x29E0, 0x2E50, 0x3310, 0x3770, 0x3C80, 0x42E0, 0x4780, 0x4BD0, 0x4FA0, 0x5340, 0x5690, 0x5960, 0x5C80, 0x6050, 0x63F0, 0x67A0, + 0x6B20, 0x6D50, 0x6F90, 0x7160, 0x72D0, 0x7510, 0x76F0, 0x78A0, 0x7A00, 0x7B50, 0x7C90, 0x7D30, 0x7E00, 0x7E30, 0x7EA0, 0x7EC0, + 0x7E90, 0x7E90, 0x7E60, 0x7E40, 0x7E70, 0x7EA0, 0x7ED0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F10, 0x7F30, 0x7F30, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, + 0x7EF0, 0x7F30, 0x7F20, 0x7F10, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F10, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F70, 0x7F30, 0x7F00, 0x7F00, 0x7F10, 0x7F30, + 0x7F20, 0x7F00, 0x7F10, 0x7EF0, 0x7F00, 0x7EE0, 0x7EC0, 0x7EC0, 0x7EF0, 0x7F50, 0x7F00, 0x7EC0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, + 0x7ED0, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7EB0, 0x7F30, 0x7F00, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, 0x7F00, 0x7EC0, + 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7F50, 0x7F00, 0x7F00, 0x7F50, 0x7F10, 0x7F60, + 0x7F20, 0x7F10, 0x7EF0, 0x7EF0, 0x7F90, 0x7F10, 0x7F00, 0x7EE0, 0x7EE0, 0x7F70, 0x7730, 0x6AA0, 0x5F60, 0x5280, 0x4660, 0x3B50, + 0x30D0, 0x2850, 0x2130, 0x1B90, 0x1790, 0x13D0, 0x1140, 0x0EF0, 0x0DD0, 0x0E60, 0x0F20, 0x1230, 0x1620, 0x1AA0, 0x1FC0, 0x2530, + 0x2AC0, 0x3070, 0x3550, 0x3A50, 0x3EE0, 0x4380, 0x4810, 0x4CF0, 0x53C0, 0x59D0, 0x6010, 0x66B0, 0x6CF0, 0x73D0, 0x79D0, 0x7E30, + 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, + 0x7E90, 0x7EF0, 0x7EE0, 0x7F30, 0x7EB0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7EE0, 0x7EF0, 0x7F10, 0x7EF0, 0x7F60, + 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F00, 0x7EE0, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7F00, 0x7300, 0x46D0, 0x2030, + 0xFC80, 0xE380, 0xD1B0, 0xC5B0, 0xBF00, 0xB9A0, 0xB4C0, 0xAF40, 0xA8B0, 0xA1D0, 0x9A40, 0x92B0, 0x8BB0, 0x8760, 0x85A0, 0x8510, + 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8410, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, + 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, + 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8530, 0x8560, 0x85B0, 0x8630, 0x86E0, 0x87B0, 0x88F0, 0x89F0, 0x8AB0, 0x8B90, 0x8C10, 0x8DC0, + 0x9020, 0x9350, 0x9820, 0x9E50, 0xA5B0, 0xADC0, 0xB5C0, 0xBD80, 0xC3D0, 0xCA60, 0xD020, 0xD5F0, 0xDBF0, 0xE130, 0xE680, 0xEB40, + 0xEF70, 0xF300, 0xF580, 0xF910, 0xFBE0, 0xFE90, 0x0170, 0x0250, 0x0260, 0x0010, 0xFD90, 0xFA20, 0xF5C0, 0xF090, 0xEA20, 0xE370, + 0xDC90, 0xD670, 0xCFE0, 0xC950, 0xC290, 0xBCD0, 0xB650, 0xAFC0, 0xAA30, 0xA500, 0xA0D0, 0x9C90, 0x9A10, 0x9810, 0x95F0, 0x9450, + 0x9270, 0x9140, 0x8F50, 0x8D60, 0x8BD0, 0x8A20, 0x8930, 0x8910, 0x8950, 0x8AA0, 0x8CF0, 0x90E0, 0x95A0, 0x9A30, 0x9E90, 0xA300, + 0xA7A0, 0xAB70, 0xAF60, 0xB2E0, 0xB4A0, 0xB650, 0xB7A0, 0xB8E0, 0xBAD0, 0xBD00, 0xBFD0, 0xC380, 0xC750, 0xCD20, 0xD2E0, 0xD8F0, + 0xDEF0, 0xE460, 0xE900, 0xECD0, 0xEFD0, 0xF240, 0xF420, 0xF610, 0xF8A0, 0xFA70, 0xFBE0, 0xFCF0, 0xFE60, 0xFFF0, 0x0170, 0x0310, + 0x04C0, 0x06E0, 0x0990, 0x0B00, 0x0DE0, 0x0F30, 0x1160, 0x13C0, 0x15B0, 0x18B0, 0x1B60, 0x1E70, 0x2140, 0x2380, 0x2620, 0x2800, + 0x2900, 0x2A20, 0x2B60, 0x2E00, 0x3090, 0x32E0, 0x34C0, 0x3580, 0x3660, 0x3670, 0x3710, 0x38B0, 0x3A40, 0x3D70, 0x3FD0, 0x41D0, + 0x4400, 0x46D0, 0x4AB0, 0x4E70, 0x5160, 0x5410, 0x55D0, 0x5780, 0x5840, 0x5890, 0x5A20, 0x5BA0, 0x5D90, 0x5FB0, 0x61F0, 0x65C0, + 0x68F0, 0x6E30, 0x7460, 0x7A50, 0x7EB0, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EA0, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, + 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7D30, 0x6E40, 0x5DF0, 0x4B70, 0x3AC0, + 0x2A60, 0x1B80, 0x0EA0, 0x03E0, 0xFBA0, 0xF810, 0xF920, 0xFE60, 0x04C0, 0x09D0, 0x0C60, 0x0B40, 0x05F0, 0xFBD0, 0xED90, 0xDC80, + 0xC800, 0xB130, 0x9860, 0x87C0, 0x8500, 0x84D0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, + 0x8460, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8470, 0x8470, 0x84A0, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, + 0x8450, 0x8450, 0x8430, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x8560, 0x88B0, + 0x9A10, 0xADA0, 0xBDF0, 0xCC40, 0xD8C0, 0xE430, 0xEF00, 0xF970, 0x0310, 0x0B30, 0x1200, 0x1660, 0x17F0, 0x1870, 0x17A0, 0x1670, + 0x1510, 0x1380, 0x1180, 0x0E10, 0x0980, 0x03E0, 0xFDA0, 0xF7B0, 0xF180, 0xEBA0, 0xE580, 0xDF40, 0xD970, 0xD3C0, 0xCF00, 0xCB40, + 0xC800, 0xC510, 0xC2E0, 0xC170, 0xBFD0, 0xBEF0, 0xBF80, 0xC030, 0xC1B0, 0xC450, 0xC6C0, 0xC9B0, 0xCE00, 0xD360, 0xD940, 0xDF30, + 0xE650, 0xEEE0, 0xF850, 0x0250, 0x0D70, 0x18C0, 0x2230, 0x2C60, 0x3560, 0x3E10, 0x4610, 0x4D90, 0x5520, 0x5C80, 0x6380, 0x6A90, + 0x71F0, 0x7880, 0x7D60, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EB0, 0x7F20, + 0x7EF0, 0x7EF0, 0x7EF0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F00, 0x7EE0, 0x7EC0, 0x7EF0, 0x7EB0, 0x7F40, 0x7F10, 0x7EC0, 0x7F40, 0x7EF0, + 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F00, + 0x7F00, 0x7F10, 0x7F50, 0x7EB0, 0x7E70, 0x7EF0, 0x7F00, 0x7F20, 0x7ED0, 0x7EB0, 0x7F20, 0x7F00, 0x7F40, 0x7ED0, 0x7EA0, 0x7F10, + 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, + 0x7F20, 0x7F40, 0x7F00, 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F90, 0x7F10, 0x7F00, + 0x7F00, 0x7ED0, 0x7F30, 0x7F00, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EE0, 0x7F00, 0x7F30, 0x7F20, 0x7EC0, 0x7C90, + 0x7650, 0x6EE0, 0x6920, 0x6410, 0x61B0, 0x60C0, 0x6050, 0x6210, 0x6480, 0x6800, 0x6A50, 0x6C30, 0x6DB0, 0x6DE0, 0x6BD0, 0x68B0, + 0x63A0, 0x5E00, 0x5750, 0x5010, 0x47C0, 0x3E40, 0x3470, 0x28C0, 0x1DC0, 0x1270, 0x0670, 0xFAA0, 0xEED0, 0xE3D0, 0xDA30, 0xD270, + 0xCC10, 0xC7A0, 0xC540, 0xC390, 0xC1F0, 0xC070, 0xBFC0, 0xC020, 0xC140, 0xC300, 0xC560, 0xC800, 0xCAF0, 0xCEE0, 0xD3B0, 0xD9C0, + 0xE050, 0xE660, 0xEDB0, 0xF300, 0xF820, 0xFCA0, 0x0090, 0x0590, 0x0880, 0x09F0, 0x0A50, 0x0900, 0x07A0, 0x0590, 0x0310, 0xFF20, + 0xFA70, 0xF440, 0xED20, 0xE5E0, 0xDDE0, 0xD5D0, 0xCE40, 0xC660, 0xBD80, 0xB380, 0xA7E0, 0x9B80, 0x8FA0, 0x8810, 0x85A0, 0x8510, + 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x8500, + 0x8580, 0x87C0, 0x92F0, 0xA430, 0xB5A0, 0xC5F0, 0xD6B0, 0xE400, 0xEF00, 0xF590, 0xF830, 0xF5E0, 0xEF50, 0xE5B0, 0xD9C0, 0xCB70, + 0xBFB0, 0xB590, 0xAFB0, 0xAD40, 0xAF10, 0xB3B0, 0xB930, 0xBE70, 0xC370, 0xC6B0, 0xC890, 0xC910, 0xC9B0, 0xC960, 0xC8D0, 0xC950, + 0xC9F0, 0xCBA0, 0xCB50, 0xC8B0, 0xC300, 0xB870, 0xAB30, 0x9A80, 0x8BD0, 0x8630, 0x8510, 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, + 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8470, + 0x8490, 0x8480, 0x8480, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8470, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, + 0x8460, 0x8460, 0x84A0, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x8530, 0x85C0, 0x87C0, 0x8C90, 0x9270, + 0x9750, 0x9BE0, 0xA060, 0xA4F0, 0xA830, 0xA8A0, 0xA350, 0x9560, 0x87A0, 0x8510, 0x84D0, 0x8480, 0x8460, 0x8480, 0x8440, 0x8430, + 0x8430, 0x8450, 0x8420, 0x8410, 0x8420, 0x8400, 0x83F0, 0x83F0, 0x83D0, 0x83D0, 0x83D0, 0x83F0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83F0, 0x83C0, 0x83D0, 0x83D0, 0x83F0, 0x83E0, 0x8400, 0x8400, 0x8420, 0x8430, 0x8440, 0x8410, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8470, 0x84A0, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84A0, 0x84A0, 0x84A0, + 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x8520, 0x8620, 0x8C10, 0x9DB0, 0xB020, 0xBEF0, 0xCC10, + 0xD700, 0xE0A0, 0xEA10, 0xF470, 0x0070, 0x0D20, 0x1AD0, 0x2790, 0x31E0, 0x3810, 0x39D0, 0x36A0, 0x2E30, 0x1FE0, 0x0CB0, 0xF400, + 0xDB90, 0xC530, 0xB1D0, 0xA370, 0x9970, 0x9280, 0x8DB0, 0x8AE0, 0x88A0, 0x8780, 0x86C0, 0x8630, 0x85E0, 0x85C0, 0x85D0, 0x85E0, + 0x85F0, 0x8610, 0x8640, 0x8690, 0x8760, 0x8930, 0x8DE0, 0x9600, 0xA080, 0xAB00, 0xB5D0, 0xBE20, 0xC4C0, 0xC9E0, 0xCE10, 0xD1E0, + 0xD5E0, 0xDAA0, 0xE0F0, 0xE840, 0xEF50, 0xF680, 0xFC60, 0x0160, 0x04C0, 0x0600, 0x03A0, 0xFE90, 0xF750, 0xED60, 0xE220, 0xD5D0, + 0xC890, 0xBB00, 0xACE0, 0x9C40, 0x8CF0, 0x8610, 0x84E0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, + 0x8420, 0x8430, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8460, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x84F0, 0x8520, 0x85A0, 0x86F0, 0x8B10, 0x9640, 0xA3A0, 0xB1D0, + 0xBFD0, 0xCDB0, 0xDBB0, 0xE8E0, 0xF6E0, 0x0240, 0x0B90, 0x13E0, 0x1A40, 0x1FF0, 0x2420, 0x2880, 0x2C40, 0x2F10, 0x3110, 0x3260, + 0x33A0, 0x3590, 0x3930, 0x3F30, 0x4900, 0x5650, 0x6770, 0x7810, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F00, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x66D0, 0x4E00, 0x36C0, 0x21C0, 0x1030, 0x00E0, 0xF090, 0xDED0, 0xC7D0, 0xAB10, 0x8C00, 0x84F0, + 0x84A0, 0x8480, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84F0, 0x84E0, 0x8520, 0x85F0, + 0x8990, 0x96D0, 0xA570, 0xB2B0, 0xBEA0, 0xCA80, 0xD410, 0xDC70, 0xE500, 0xEE10, 0xF790, 0x01B0, 0x0B50, 0x14D0, 0x1D60, 0x2500, + 0x2B10, 0x3050, 0x3690, 0x3BA0, 0x41C0, 0x4840, 0x4E30, 0x5620, 0x5C90, 0x6300, 0x6820, 0x6BC0, 0x6ED0, 0x7070, 0x72A0, 0x74F0, + 0x7770, 0x7AA0, 0x7D00, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F00, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7EB0, 0x7EE0, + 0x7F10, 0x7EA0, 0x7EA0, 0x7ED0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, + 0x7F00, 0x7F10, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F50, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, + 0x7F70, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F80, 0x7EF0, 0x7EB0, 0x7F00, 0x7EF0, 0x7F50, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F40, + 0x7EE0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7E70, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F00, + 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F50, 0x7F00, 0x7F40, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, + 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F20, + 0x7F10, 0x7E90, 0x7EB0, 0x7ED0, 0x7F10, 0x7F00, 0x7E80, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F00, 0x7F20, 0x7F10, 0x7F10, + 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7EE0, + 0x7F50, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7EB0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7EB0, 0x7F10, 0x7F20, 0x7F40, + 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7ED0, 0x7EB0, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, + 0x7F00, 0x7F40, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F60, 0x7E90, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F10, + 0x7F20, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7EE0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, + 0x7EE0, 0x7F50, 0x7F00, 0x7EE0, 0x7ED0, 0x7EB0, 0x7F30, 0x7EF0, 0x7E90, 0x7ED0, 0x7F00, 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, + 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, + 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7EF0, 0x7F20, 0x7ED0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, + 0x7EF0, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F00, 0x7F00, + 0x7EF0, 0x7F10, 0x7F80, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, + 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EC0, 0x7ED0, 0x7F00, 0x7F20, 0x7F10, 0x7E90, 0x7EE0, 0x7EE0, + 0x7F10, 0x7F10, 0x7E90, 0x7E60, 0x7EF0, 0x7F10, 0x7F20, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7EF0, + 0x7F00, 0x7EE0, 0x7F40, 0x7EF0, 0x7F20, 0x7F40, 0x7EC0, 0x7F10, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, + 0x7F00, 0x7F30, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, + 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7E90, 0x7EE0, 0x7EE0, 0x7F10, + 0x7F10, 0x7E70, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7E90, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, + 0x7EC0, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7F10, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7A60, + 0x7140, 0x67E0, 0x5F90, 0x57B0, 0x4FF0, 0x47C0, 0x4070, 0x3830, 0x3160, 0x29E0, 0x21E0, 0x1A40, 0x1190, 0x0890, 0xFE70, 0xF3D0, + 0xEA50, 0xE040, 0xD6C0, 0xCD30, 0xC470, 0xBC40, 0xB410, 0xACF0, 0xA6E0, 0xA110, 0x9D60, 0x99F0, 0x9830, 0x9720, 0x96D0, 0x97E0, + 0x9960, 0x9BC0, 0x9ED0, 0xA200, 0xA520, 0xA8C0, 0xAC90, 0xB100, 0xB500, 0xB950, 0xBD30, 0xC080, 0xC550, 0xC900, 0xCBD0, 0xCE10, + 0xD090, 0xD240, 0xD3F0, 0xD5D0, 0xD750, 0xD8C0, 0xD9F0, 0xDAD0, 0xDBC0, 0xDC40, 0xDD00, 0xDDD0, 0xDF10, 0xE080, 0xE210, 0xE380, + 0xE5B0, 0xE760, 0xE8C0, 0xEAF0, 0xED60, 0xF140, 0xF540, 0xF990, 0xFDC0, 0x0110, 0x0480, 0x0820, 0x0B40, 0x0E30, 0x1090, 0x12A0, + 0x15C0, 0x1800, 0x1990, 0x1BA0, 0x1D80, 0x1E90, 0x1F50, 0x2000, 0x20F0, 0x2180, 0x2240, 0x2370, 0x23A0, 0x23B0, 0x2400, 0x24C0, + 0x24D0, 0x2470, 0x24C0, 0x2490, 0x2430, 0x2490, 0x2340, 0x21E0, 0x1FD0, 0x1CD0, 0x19E0, 0x1650, 0x1290, 0x0EE0, 0x0980, 0x0310, + 0xFBF0, 0xF3C0, 0xEAC0, 0xE0E0, 0xD820, 0xD050, 0xC900, 0xC2A0, 0xBCA0, 0xB6E0, 0xB110, 0xABB0, 0xA700, 0xA250, 0x9E40, 0x9950, + 0x94E0, 0x90C0, 0x8D70, 0x8AE0, 0x88B0, 0x8790, 0x8680, 0x85E0, 0x8590, 0x8540, 0x8520, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84D0, + 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, + 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8460, 0x8460, 0x8460, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8450, 0x8460, + 0x8450, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8470, 0x8430, 0x8430, 0x8430, 0x8470, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8460, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, + 0x8400, 0x8400, 0x8400, 0x83F0, 0x8400, 0x83F0, 0x83E0, 0x83E0, 0x8400, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x8410, 0x83C0, 0x83C0, + 0x83C0, 0x83A0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, + 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x84F0, 0x8520, 0x85A0, 0x86E0, + 0x8A40, 0x93B0, 0x9F50, 0xA8D0, 0xB1D0, 0xBA40, 0xC200, 0xC8F0, 0xD020, 0xD5A0, 0xD980, 0xDD20, 0xDF70, 0xE190, 0xE240, 0xE120, + 0xDE30, 0xD7A0, 0xD050, 0xC480, 0xB4B0, 0xA1F0, 0x8D30, 0x8580, 0x84D0, 0x84A0, 0x8480, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8460, 0x8460, 0x8480, 0x8490, 0x84C0, 0x8530, 0x89C0, + 0xA990, 0xC7D0, 0xE3D0, 0xFDF0, 0x12E0, 0x2440, 0x3190, 0x3D00, 0x4470, 0x48F0, 0x4BF0, 0x4D30, 0x4DF0, 0x4E10, 0x4DD0, 0x4EC0, + 0x4F40, 0x5150, 0x5490, 0x5760, 0x5C00, 0x60A0, 0x65F0, 0x6BA0, 0x7180, 0x7880, 0x7DA0, 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7F00, + 0x7F30, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F70, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, + 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F30, 0x7F20, 0x7E90, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, + 0x7E90, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, + 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F80, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EF0, + 0x7EA0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7F40, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F70, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, + 0x7F10, 0x7F00, 0x7F00, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, + 0x7EC0, 0x7ED0, 0x7EF0, 0x7F00, 0x7EF0, 0x7E90, 0x7EB0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7340, + 0x5A80, 0x4030, 0x2540, 0x0B50, 0xF2D0, 0xDC30, 0xC6C0, 0xB1A0, 0xA050, 0x91F0, 0x8990, 0x86B0, 0x85D0, 0x85A0, 0x85C0, 0x8650, + 0x88E0, 0x91F0, 0xA270, 0xB5A0, 0xCB70, 0xE250, 0xF9B0, 0x1150, 0x26A0, 0x3BB0, 0x4C10, 0x5960, 0x63D0, 0x6AD0, 0x6FF0, 0x7340, + 0x73D0, 0x7390, 0x71C0, 0x6DD0, 0x69B0, 0x6400, 0x5DF0, 0x5680, 0x4DB0, 0x4520, 0x3C00, 0x3350, 0x2BA0, 0x2460, 0x1ED0, 0x1900, + 0x1420, 0x0E70, 0xF610, 0xEF50, 0xE8A0, 0xE400, 0xE090, 0xDFB0, 0xE2E0, 0xE820, 0xEF40, 0xF720, 0xFD40, 0x0190, 0x0380, 0x0390, + 0x02F0, 0x0240, 0x02D0, 0x0450, 0x06F0, 0x0B40, 0x11C0, 0x19D0, 0x2160, 0x29E0, 0x3140, 0x3830, 0x3FE0, 0x4820, 0x4F90, 0x5770, + 0x60B0, 0x6990, 0x7170, 0x7840, 0x7D40, 0x7EB0, 0x7F00, 0x7F00, 0x7F40, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F00, + 0x7F00, 0x7EF0, 0x7ED0, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F30, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F50, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7ED0, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7EF0, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F20, + 0x7EC0, 0x7EF0, 0x65D0, 0x4360, 0x1E80, 0xF5A0, 0xCFE0, 0xA960, 0x8A20, 0x84F0, 0x84B0, 0x8490, 0x8480, 0x8490, 0x8460, 0x8460, + 0x8470, 0x8460, 0x8450, 0x8460, 0x8490, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x8500, 0x85F0, 0x8E80, 0xA650, 0xBBF0, 0xCF30, + 0xE1B0, 0xF1B0, 0xFFB0, 0x0CE0, 0x1A00, 0x25B0, 0x3120, 0x3B80, 0x4450, 0x4CB0, 0x52C0, 0x5800, 0x5B40, 0x5DB0, 0x5F30, 0x5FE0, + 0x6090, 0x6110, 0x60F0, 0x6130, 0x6120, 0x61C0, 0x60F0, 0x6050, 0x6030, 0x5F70, 0x5FD0, 0x5EB0, 0x5CE0, 0x5A90, 0x5710, 0x5360, + 0x4EA0, 0x4950, 0x4350, 0x3CE0, 0x36C0, 0x3050, 0x2A30, 0x2440, 0x1CE0, 0x1650, 0x0F30, 0x0780, 0x00F0, 0xF9A0, 0xF420, 0xEEA0, + 0xEA10, 0xE6B0, 0xE2A0, 0xDF60, 0xDB30, 0xD670, 0xD200, 0xCD80, 0xC9A0, 0xC670, 0xC320, 0xC030, 0xBC80, 0xB960, 0xB6D0, 0xB380, + 0xB170, 0xAF00, 0xAC00, 0xA950, 0xA580, 0xA280, 0x9FE0, 0x9DC0, 0x9B10, 0x98A0, 0x9670, 0x9450, 0x9240, 0x90E0, 0x8F90, 0x8E60, + 0x8D20, 0x8BF0, 0x8BA0, 0x8B10, 0x8B30, 0x8B50, 0x8B50, 0x8BB0, 0x8BB0, 0x8B90, 0x8BB0, 0x8C10, 0x8D20, 0x8EA0, 0x8FD0, 0x9050, + 0x90A0, 0x91C0, 0x9270, 0x9470, 0x9630, 0x97A0, 0x9980, 0x9AF0, 0x9D00, 0x9FB0, 0xA210, 0xA510, 0xA880, 0xABC0, 0xAE40, 0xB160, + 0xB580, 0xB9C0, 0xBE70, 0xC2B0, 0xC670, 0xCB20, 0xCFB0, 0xD410, 0xD8F0, 0xDD80, 0xE230, 0xE690, 0xEA90, 0xEF20, 0xF3D0, 0xF830, + 0xFBE0, 0xFF60, 0x0350, 0x0770, 0x0B20, 0x0E70, 0x11F0, 0x15B0, 0x18E0, 0x1C30, 0x1EF0, 0x2170, 0x24C0, 0x2790, 0x2C50, 0x3100, + 0x3610, 0x3A70, 0x3D60, 0x4150, 0x4510, 0x4900, 0x4E20, 0x5380, 0x58D0, 0x5D70, 0x60A0, 0x6C80, 0x6F70, 0x71F0, 0x7360, 0x7550, + 0x7690, 0x7730, 0x7840, 0x7880, 0x7890, 0x78A0, 0x77B0, 0x7800, 0x7740, 0x7750, 0x7710, 0x75F0, 0x7520, 0x73C0, 0x7300, 0x7240, + 0x70C0, 0x6F30, 0x6D20, 0x6B80, 0x69E0, 0x67D0, 0x66F0, 0x6520, 0x6350, 0x6130, 0x5F60, 0x5D80, 0x5B80, 0x59B0, 0x5840, 0x5740, + 0x56D0, 0x5560, 0x53F0, 0x5310, 0x52B0, 0x5300, 0x5260, 0x51D0, 0x50F0, 0x4F70, 0x4DF0, 0x4D00, 0x4B70, 0x4B10, 0x4A10, 0x49B0, + 0x4960, 0x47E0, 0x46F0, 0x4540, 0x4490, 0x43A0, 0x4180, 0x4010, 0x3D90, 0x3B20, 0x3800, 0x3570, 0x32F0, 0x2FB0, 0x2C30, 0x2820, + 0x23C0, 0x1FF0, 0x1BC0, 0x1780, 0x1390, 0x0EA0, 0x0AA0, 0x0690, 0x0350, 0x0020, 0xFD40, 0xFB90, 0xF9E0, 0xF860, 0xF770, 0xF730, + 0xF7F0, 0xF940, 0xFB30, 0xFE90, 0x01E0, 0x0620, 0x0AF0, 0x10C0, 0x1680, 0x1B10, 0x2100, 0x26E0, 0x2BF0, 0x31F0, 0x3730, 0x3E00, + 0x43F0, 0x49B0, 0x4FA0, 0x5400, 0x5810, 0x5BB0, 0x5F60, 0x6380, 0x6680, 0x6960, 0x6B80, 0x6CD0, 0x6F10, 0x6FA0, 0x70C0, 0x7190, + 0x7230, 0x72C0, 0x7280, 0x7380, 0x7420, 0x7500, 0x76F0, 0x7890, 0x7930, 0x7940, 0x78D0, 0x7870, 0x7800, 0x7610, 0x7270, 0x6C60, + 0x65A0, 0x5D90, 0x5690, 0x4F60, 0x4770, 0x40A0, 0x38E0, 0x3070, 0x27E0, 0x2060, 0x1B70, 0x1910, 0x19F0, 0x1D60, 0x21D0, 0x2630, + 0x28B0, 0x2970, 0x2950, 0x2790, 0x25E0, 0x2320, 0x20B0, 0x1F60, 0x1D20, 0x1AD0, 0x1690, 0x10F0, 0x0960, 0xFF80, 0xF410, 0xE570, + 0xD570, 0xC510, 0xB380, 0xA140, 0x8F50, 0x86D0, 0x8510, 0x84D0, 0x84B0, 0x8490, 0x84B0, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, + 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8470, 0x8430, 0x8430, 0x8430, 0x8410, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8430, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8410, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8410, 0x8450, 0x8450, 0x8460, + 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x8500, + 0x8530, 0x8590, 0x8640, 0x8890, 0x8C90, 0x9340, 0x9AC0, 0xA190, 0xA8C0, 0xAFA0, 0xB5C0, 0xBCA0, 0xC2B0, 0xC870, 0xCDA0, 0xD1E0, + 0xD5C0, 0xD9A0, 0xDDE0, 0xE230, 0xE6B0, 0xEAA0, 0xED70, 0xF010, 0xF1F0, 0xF3D0, 0xF520, 0xF6A0, 0xF780, 0xF830, 0xF8A0, 0xF8F0, + 0xF960, 0xFA60, 0xF990, 0xF7F0, 0xF760, 0xF6F0, 0xF6C0, 0xF7F0, 0xFA30, 0xFBF0, 0xFEA0, 0x0030, 0x01C0, 0x0320, 0x03D0, 0x03E0, + 0x0300, 0x0240, 0x00D0, 0xFF70, 0xFEA0, 0xFDC0, 0xFCD0, 0xFBA0, 0xFA90, 0xFAA0, 0xFB60, 0xFBE0, 0xFCF0, 0xFDD0, 0xFEB0, 0xFEE0, + 0xFF80, 0xFF70, 0xFF10, 0xFF40, 0xFFD0, 0x01D0, 0x05B0, 0x0BE0, 0x1360, 0x1C10, 0x24A0, 0x2B70, 0x3050, 0x3400, 0x37B0, 0x3AD0, + 0x3E90, 0x4380, 0x48C0, 0x4E90, 0x53B0, 0x5760, 0x5B10, 0x5F50, 0x62B0, 0x6620, 0x69F0, 0x6E70, 0x7270, 0x75C0, 0x7870, 0x7AB0, + 0x7CE0, 0x7E60, 0x7F10, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7BE0, 0x7320, 0x6A60, 0x5FF0, 0x53F0, 0x44C0, 0x3470, 0x2150, 0x0B50, 0xF260, 0xD6C0, 0xB8F0, 0x99E0, 0x86E0, + 0x84E0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, + 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8540, 0x8580, + 0x85E0, 0x8660, 0x8750, 0x8820, 0x8990, 0x8B10, 0x8C40, 0x8CC0, 0x8D20, 0x8CD0, 0x8B70, 0x8A00, 0x8850, 0x86E0, 0x85E0, 0x8540, + 0x8500, 0x84D0, 0x84D0, 0x84A0, 0x8490, 0x8480, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, + 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8480, 0x8430, 0x8430, 0x8440, 0x8430, 0x8440, + 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8480, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, + 0x8490, 0x8490, 0x84B0, 0x84B0, 0x84C0, 0x84E0, 0x8510, 0x8570, 0x8690, 0x8A20, 0x9430, 0x9F80, 0xAA10, 0xB350, 0xBCA0, 0xC500, + 0xCC40, 0xD430, 0xDC00, 0xE300, 0xEB20, 0xF220, 0xFA30, 0x01D0, 0x0930, 0x11C0, 0x1A00, 0x21B0, 0x29C0, 0x3270, 0x3BF0, 0x4480, + 0x4C80, 0x5440, 0x5B10, 0x6210, 0x67B0, 0x6CE0, 0x7270, 0x76A0, 0x7AE0, 0x7E40, 0x7F70, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F60, + 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F00, 0x7F20, 0x7ED0, + 0x7EB0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7E90, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, + 0x7F40, 0x7ED0, 0x7F10, 0x7F40, 0x7F00, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7F00, 0x7F10, 0x7F10, + 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F00, 0x7F60, 0x7EE0, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, + 0x7F70, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7C90, 0x5530, 0x33E0, 0x16D0, + 0xFE10, 0xE650, 0xCDA0, 0xB100, 0x8E60, 0x8510, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84E0, + 0x8510, 0x8580, 0x8660, 0x8850, 0x8D90, 0x97C0, 0xA3F0, 0xAF10, 0xB760, 0xBB10, 0xB740, 0xAE30, 0xA000, 0x8FA0, 0x8700, 0x8520, + 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, + 0x84A0, 0x84B0, 0x84C0, 0x84F0, 0x8510, 0x8550, 0x85F0, 0x8760, 0x8B70, 0x9400, 0x9F80, 0xAB40, 0xB780, 0xC370, 0xCF90, 0xDD00, + 0xEB40, 0xFB50, 0x0CD0, 0x1DF0, 0x2D50, 0x3A80, 0x4600, 0x4F70, 0x5800, 0x60C0, 0x68D0, 0x70B0, 0x7880, 0x7DA0, 0x7F20, 0x7F20, + 0x7F50, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7F00, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EF0, 0x7F30, + 0x7F00, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, 0x7E90, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E80, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, + 0x7E90, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7F10, + 0x7F30, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F70, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F20, 0x7F50, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, + 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F60, 0x7F00, 0x7F40, 0x7F10, 0x7F20, + 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, + 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, + 0x7EA0, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F00, + 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F50, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F70, + 0x7EE0, 0x7ED0, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7340, + 0x56F0, 0x3D50, 0x2850, 0x1980, 0x0FE0, 0x0AF0, 0x0A60, 0x0C10, 0x0FC0, 0x14F0, 0x1B80, 0x2360, 0x2C50, 0x35F0, 0x3FF0, 0x4A40, + 0x5500, 0x5DA0, 0x65A0, 0x6B30, 0x70B0, 0x75B0, 0x79D0, 0x7C90, 0x7E80, 0x7F10, 0x7F30, 0x7F00, 0x7E40, 0x7BB0, 0x77B0, 0x7300, + 0x6EA0, 0x6AC0, 0x6710, 0x62B0, 0x5D00, 0x5510, 0x4A90, 0x3C70, 0x2B20, 0x1760, 0x02F0, 0xECA0, 0xD880, 0xC530, 0xB3F0, 0xA430, + 0x95C0, 0x8B80, 0x8710, 0x8590, 0x8520, 0x84F0, 0x84E0, 0x8460, 0x84D0, 0x84D0, 0x84D0, 0x84F0, 0x8520, 0x85C0, 0x87F0, 0x9090, + 0x9D60, 0xA950, 0xB470, 0xBF80, 0xCA00, 0xD3B0, 0xDC90, 0xE300, 0xE860, 0xEC90, 0xF000, 0xF0F0, 0xF040, 0xEDF0, 0xE930, 0xE180, + 0xD8F0, 0xD020, 0xC780, 0xBFF0, 0xB980, 0xB450, 0xB060, 0xAE50, 0xAE20, 0xAF90, 0xB230, 0xB510, 0xB8F0, 0xBD70, 0xC350, 0xC940, + 0xE1A0, 0xE850, 0xEEB0, 0xF530, 0xFC00, 0x0240, 0x0830, 0x0E00, 0x12E0, 0x1710, 0x1B20, 0x1FA0, 0x23E0, 0x2730, 0x29F0, 0x2CA0, + 0x2EE0, 0x3110, 0x3270, 0x3370, 0x3570, 0x3620, 0x3740, 0x3930, 0x3BD0, 0x3F70, 0x43A0, 0x48B0, 0x4E20, 0x53C0, 0x5910, 0x5EB0, + 0x6570, 0x6B70, 0x7140, 0x76D0, 0x7AF0, 0x7DA0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7E70, 0x7D30, 0x7A30, 0x7620, 0x7110, 0x6AD0, 0x6300, + 0x5A20, 0x50D0, 0x4730, 0x3DE0, 0x3500, 0x2D60, 0x2680, 0x20B0, 0x1C60, 0x18D0, 0x1590, 0x12A0, 0x1070, 0x0F50, 0x1020, 0x11A0, + 0x1400, 0x1710, 0x1B30, 0x2000, 0x2670, 0x2DB0, 0x3570, 0x3C20, 0x4340, 0x49C0, 0x5170, 0x58E0, 0x5F50, 0x6610, 0x6C20, 0x7240, + 0x7740, 0x7AD0, 0x7DB0, 0x7E50, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F50, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7D80, 0x7A40, 0x7710, 0x7330, 0x6F40, 0x6BD0, 0x6730, 0x6330, 0x5F00, 0x5AE0, 0x5770, 0x5440, + 0x5200, 0x5090, 0x4F30, 0x4EC0, 0x4D40, 0x4CB0, 0x4BB0, 0x4A50, 0x4A10, 0x49A0, 0x49E0, 0x4990, 0x48C0, 0x49E0, 0x4AC0, 0x4CC0, + 0x4E40, 0x4ED0, 0x4FD0, 0x5000, 0x5120, 0x5150, 0x5290, 0x5590, 0x5800, 0x5A10, 0x5B90, 0x5C80, 0x5DE0, 0x5F40, 0x6080, 0x62A0, + 0x63C0, 0x64F0, 0x66A0, 0x6840, 0x69C0, 0x6AD0, 0x6CB0, 0x6DF0, 0x6E60, 0x6E90, 0x6E70, 0x6F80, 0x70F0, 0x72B0, 0x7420, 0x7520, + 0x7650, 0x7650, 0x7670, 0x76C0, 0x7730, 0x7860, 0x7940, 0x79D0, 0x7AF0, 0x7B70, 0x7CC0, 0x7DD0, 0x7E80, 0x7EA0, 0x7E90, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7ED0, 0x7F20, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F20, + 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, + 0x7ED0, 0x7EE0, 0x7F80, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7E70, 0x7ED0, 0x7EB0, 0x7F10, 0x7F00, 0x7E90, 0x7EF0, + 0x7F20, 0x7F20, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, + 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7EF0, 0x7F10, + 0x7EE0, 0x7EF0, 0x7F90, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, 0x7EF0, 0x7F00, 0x7F40, 0x7ED0, 0x7EB0, 0x7F10, + 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, 0x7ED0, 0x7EC0, 0x7EF0, 0x7F00, 0x7F20, 0x7EE0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7EF0, 0x7E90, + 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F70, + 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7ED0, 0x7F70, 0x7F20, 0x7ED0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7EF0, + 0x7EB0, 0x7EC0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7A60, 0x72C0, 0x6BA0, 0x65E0, 0x6050, 0x5C90, 0x5920, + 0x5740, 0x5580, 0x53B0, 0x52F0, 0x5130, 0x51B0, 0x51E0, 0x5210, 0x5310, 0x5400, 0x5440, 0x5490, 0x5410, 0x53E0, 0x5360, 0x5270, + 0x5130, 0x4E00, 0x4970, 0x42C0, 0x3A90, 0x3160, 0x25B0, 0x1990, 0x0BE0, 0xFD60, 0xED90, 0xDCF0, 0xCB60, 0xB800, 0xA2C0, 0x8D00, + 0x85B0, 0x84E0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, + 0x8410, 0x8420, 0x8410, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8480, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84C0, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84E0, + 0x84F0, 0x84F0, 0x8510, 0x8560, 0x8560, 0x85D0, 0x85F0, 0x8670, 0x8750, 0x88F0, 0x8B90, 0x8EC0, 0x91B0, 0x94F0, 0x9890, 0x9CA0, + 0xA170, 0xA6D0, 0xAC20, 0xAFF0, 0xB450, 0xB880, 0xBD00, 0xC1F0, 0xC740, 0xCD30, 0xD300, 0xD8D0, 0xDD70, 0xE1E0, 0xE700, 0xEAC0, + 0xEE00, 0xF0D0, 0xF270, 0xF3F0, 0xF500, 0xF6D0, 0xF840, 0xF920, 0xF8F0, 0xF830, 0xF6C0, 0xF5D0, 0xF490, 0xF390, 0xF140, 0xEE40, + 0xEAD0, 0xE710, 0xE400, 0xE140, 0xDEB0, 0xDCB0, 0xDA00, 0xD7F0, 0xD660, 0xD4C0, 0xD310, 0xD210, 0xD0B0, 0xCFE0, 0xCDB0, 0xCC70, + 0xCB00, 0xCB40, 0xCC20, 0xCD30, 0xCF20, 0xD010, 0xD170, 0xD390, 0xD660, 0xD950, 0xDBE0, 0xDE60, 0xE0C0, 0xE350, 0xE660, 0xE940, + 0xEC50, 0xEFC0, 0xF2E0, 0xF5E0, 0xF7B0, 0xF920, 0xF9A0, 0xF910, 0xF8F0, 0xF7D0, 0xF600, 0xF3C0, 0xF0C0, 0xEEC0, 0xEC60, 0xEA90, + 0xE930, 0xE7B0, 0xE710, 0xE5F0, 0xE560, 0xE570, 0xE5F0, 0xE7B0, 0xE9D0, 0xEB80, 0xEE40, 0xF110, 0xF430, 0xF770, 0xFB00, 0xFD90, + 0xFFF0, 0x0230, 0x0540, 0x08D0, 0x0CC0, 0x1140, 0x1580, 0x19D0, 0x1E60, 0x2350, 0x2910, 0x30E0, 0x38E0, 0x4180, 0x4B10, 0x5590, + 0x6020, 0x6BC0, 0x76D0, 0x7E90, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7B70, 0x74B0, 0x6D30, + 0x6560, 0x5CF0, 0x5490, 0x4C60, 0x44C0, 0x3E30, 0x3880, 0x3330, 0x2E70, 0x2AD0, 0x26F0, 0x2440, 0x2200, 0x2070, 0x2010, 0x2100, + 0x2250, 0x24D0, 0x28F0, 0x2E30, 0x3390, 0x3940, 0x3E90, 0x4370, 0x45E0, 0x46C0, 0x4540, 0x4240, 0x3D90, 0x3830, 0x32E0, 0x2DD0, + 0x28A0, 0x2440, 0x2000, 0x1C60, 0x1920, 0x15E0, 0x1320, 0x1080, 0x0DF0, 0x0AE0, 0x0830, 0x0530, 0x02F0, 0x0080, 0xFDF0, 0xFA50, + 0xF690, 0xF230, 0xEDE0, 0xE950, 0xE550, 0xE120, 0xDD80, 0xD9F0, 0xD7A0, 0xD5D0, 0xD480, 0xD350, 0xD260, 0xD1A0, 0xD0D0, 0xD030, + 0xCFA0, 0xCF20, 0xCDD0, 0xCC80, 0xCA40, 0xC750, 0xC450, 0xC000, 0xBBC0, 0xB6F0, 0xB250, 0xAD00, 0xA800, 0xA280, 0x9D70, 0x98B0, + 0x94F0, 0x91E0, 0x8FC0, 0x8E00, 0x8CC0, 0x8BF0, 0x8BF0, 0x8C10, 0x8C90, 0x8DF0, 0x8EB0, 0x8F90, 0x9040, 0x90F0, 0x90E0, 0x90D0, + 0x8FC0, 0x8E60, 0x8D50, 0x8C00, 0x8A80, 0x8940, 0x8820, 0x8720, 0x8640, 0x85A0, 0x8540, 0x8540, 0x84F0, 0x84E0, 0x84D0, 0x84B0, + 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8430, 0x8430, 0x8430, 0x8420, 0x8430, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8440, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, + 0x8500, 0x8540, 0x85B0, 0x8670, 0x8750, 0x8800, 0x88A0, 0x89F0, 0x8C00, 0x9010, 0x9400, 0x96E0, 0x9880, 0x9810, 0x95F0, 0x91A0, + 0x8C20, 0x87F0, 0x8600, 0x8530, 0x84F0, 0x8500, 0x84F0, 0x84B0, 0x84B0, 0x84D0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x84A0, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8490, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, + 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, + 0x84F0, 0x8500, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84E0, 0x84C0, 0x84D0, 0x84B0, 0x84A0, 0x84A0, + 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x84C0, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84E0, 0x8500, 0x8510, 0x8530, 0x8570, 0x85C0, 0x8670, 0x8760, + 0x88A0, 0x8A90, 0x8D00, 0x8FC0, 0x92D0, 0x95D0, 0x9980, 0x9CD0, 0x9FF0, 0xA2E0, 0xA620, 0xA960, 0xAC70, 0xAF40, 0xB1D0, 0xB3B0, + 0xB5B0, 0xB7A0, 0xB970, 0xBC30, 0xBEB0, 0xC1A0, 0xC430, 0xC6B0, 0xC8C0, 0xCA30, 0xCBD0, 0xCD70, 0xCE40, 0xCF00, 0xCFD0, 0xD130, + 0xD270, 0xD330, 0xD460, 0xD540, 0xD640, 0xD750, 0xD730, 0xD820, 0xD780, 0xD7F0, 0xD820, 0xD8A0, 0xD8F0, 0xD860, 0xD760, 0xD670, + 0xD510, 0xD430, 0xD2C0, 0xD150, 0xCFE0, 0xCD70, 0xCB70, 0xC910, 0xC680, 0xC430, 0xC1C0, 0xC010, 0xBEC0, 0xBD10, 0xBBF0, 0xBB30, + 0xBB10, 0xB9F0, 0xB930, 0xB8A0, 0xB8E0, 0xB9E0, 0xBAC0, 0xBC20, 0xBDF0, 0xBE80, 0xBF40, 0xBF30, 0xBF30, 0xBFB0, 0xC010, 0xC180, + 0xC170, 0xC130, 0xBFB0, 0xBDD0, 0xBBE0, 0xB8F0, 0xB610, 0xB3B0, 0xB110, 0xAE20, 0xAAF0, 0xA8D0, 0xA730, 0xA560, 0xA3D0, 0xA2E0, + 0xA270, 0xA2C0, 0xA2B0, 0xA380, 0xA4C0, 0xA620, 0xA780, 0xA940, 0xABB0, 0xAD00, 0xAF10, 0xB1C0, 0xB460, 0xB710, 0xBA50, 0xBDB0, + 0xC160, 0xC5B0, 0xC970, 0xCE60, 0xD2E0, 0xD7B0, 0xDCA0, 0xE160, 0xE640, 0xEAD0, 0xF070, 0xF5D0, 0xFB30, 0x0060, 0x0520, 0x09C0, + 0x0E80, 0x1390, 0x18E0, 0x1DE0, 0x2340, 0x2800, 0x2D30, 0x3270, 0x3800, 0x3E10, 0x4350, 0x47F0, 0x4D80, 0x5190, 0x5630, 0x59A0, + 0x5D40, 0x6150, 0x6500, 0x6800, 0x6AC0, 0x6CB0, 0x6FA0, 0x7220, 0x7540, 0x7790, 0x79E0, 0x7C20, 0x7DF0, 0x7ED0, 0x7F20, 0x7F40, + 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F70, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, + 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7F20, 0x7F00, 0x7F50, 0x7ED0, 0x7EA0, 0x7F10, 0x7F10, 0x7F30, 0x7EC0, 0x7EC0, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F30, 0x7F20, 0x7F10, + 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, + 0x7EE0, 0x7F60, 0x7F10, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EF0, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, + 0x7F20, 0x7F20, 0x7580, 0x65B0, 0x5630, 0x4680, 0x3910, 0x2D30, 0x2230, 0x18B0, 0x10B0, 0x0A00, 0x0470, 0xFFC0, 0xFBB0, 0xF860, + 0xF550, 0xF250, 0xEFA0, 0xECB0, 0xEA20, 0xE6D0, 0xE380, 0xE050, 0xDD30, 0xDAB0, 0xD940, 0xD810, 0xD820, 0xD840, 0xD890, 0xD950, + 0xD970, 0xD840, 0xD6A0, 0xD370, 0xCF40, 0xCB10, 0xC630, 0xC160, 0xBCB0, 0xB9E0, 0xB8A0, 0xBA30, 0xBEF0, 0xC620, 0xCF90, 0xDAB0, + 0xE660, 0xF390, 0x0200, 0x0FB0, 0x1D80, 0x2B40, 0x38B0, 0x4730, 0x5670, 0x6620, 0x7660, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x6EA0, 0x3E70, 0x0940, 0xD030, 0x95D0, 0x84E0, 0x8490, 0x8470, 0x8450, 0x8440, + 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x83E0, + 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8490, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84F0, 0x8500, + 0x8500, 0x8510, 0x8510, 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84F0, 0x8500, 0x8530, 0x8570, 0x85F0, + 0x86F0, 0x8870, 0x8B30, 0x8DF0, 0x9050, 0x91F0, 0x9200, 0x90D0, 0x8E90, 0x8BD0, 0x8930, 0x8760, 0x8660, 0x85B0, 0x8570, 0x8530, + 0x8510, 0x84F0, 0x84E0, 0x84C0, 0x84F0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84D0, 0x84F0, + 0x8570, 0x8780, 0x9360, 0xA3A0, 0xB000, 0xB7C0, 0xB9F0, 0xB630, 0xAD40, 0xA080, 0x93D0, 0x8A70, 0x8690, 0x8560, 0x8500, 0x84E0, + 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, + 0x84C0, 0x84B0, 0x8480, 0x8480, 0x84A0, 0x8460, 0x8460, 0x8410, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8440, + 0x8410, 0x8400, 0x8400, 0x83A0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x83C0, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8470, 0x8490, 0x84A0, 0x84C0, 0x84E0, 0x8510, 0x8660, 0x8F50, 0xA5B0, 0xBB30, 0xD020, 0xE410, 0xF770, 0x0710, 0x14E0, + 0x2140, 0x2BC0, 0x3350, 0x3940, 0x3D00, 0x3F90, 0x41A0, 0x42E0, 0x4450, 0x44B0, 0x44E0, 0x4470, 0x4480, 0x4650, 0x4900, 0x4C50, + 0x4FA0, 0x5240, 0x55D0, 0x5930, 0x5CB0, 0x5FE0, 0x61D0, 0x62B0, 0x60F0, 0x5C40, 0x5540, 0x4A90, 0x3D20, 0x2C20, 0x17F0, 0x0280, + 0xEC60, 0xD680, 0xC5B0, 0xB8D0, 0xB220, 0xAE90, 0xAE60, 0xAE50, 0xAB20, 0xA3D0, 0x95D0, 0x8900, 0x8530, 0x84D0, 0x84B0, 0x84A0, + 0x8490, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84E0, 0x8530, 0x87C0, 0x9CA0, 0xB6E0, 0xCCA0, 0xDF40, 0xF040, + 0x0040, 0x10B0, 0x21F0, 0x3340, 0x4560, 0x5910, 0x69B0, 0x7860, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, + 0x7ED0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F50, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F70, + 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7EA0, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, + 0x7ED0, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7F10, + 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, + 0x7EE0, 0x7E90, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7F00, 0x7E90, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, + 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F10, 0x7EF0, 0x7F10, + 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7EB0, 0x7EB0, 0x7F50, + 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7EB0, 0x7700, 0x70C0, 0x6B80, 0x68B0, 0x6760, 0x6740, 0x6980, + 0x6D20, 0x7260, 0x7810, 0x7D60, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, + 0x7F60, 0x7F10, 0x7EF0, 0x7F10, 0x7F10, 0x7F40, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F50, + 0x7C30, 0x7670, 0x7160, 0x6C50, 0x66F0, 0x62C0, 0x5E90, 0x5CA0, 0x5A70, 0x58E0, 0x58D0, 0x5930, 0x5AB0, 0x5BE0, 0x5CF0, 0x5EE0, + 0x6000, 0x6250, 0x6390, 0x6360, 0x6300, 0x6200, 0x5FF0, 0x5D20, 0x5940, 0x55B0, 0x5030, 0x49C0, 0x42C0, 0x3AE0, 0x3330, 0x2B60, + 0x23A0, 0x1C90, 0x1490, 0x0D70, 0x06E0, 0x00D0, 0xFB10, 0xF4E0, 0xEF00, 0xE7F0, 0xE110, 0xDA80, 0xD480, 0xCF70, 0xCAD0, 0xC5F0, + 0xC220, 0xBD70, 0xB860, 0xB3A0, 0xAEB0, 0xAA10, 0xA4E0, 0x9FC0, 0x9B00, 0x9630, 0x9290, 0x8F10, 0x8C50, 0x8A50, 0x88F0, 0x8820, + 0x8770, 0x8700, 0x86D0, 0x86C0, 0x86D0, 0x86F0, 0x8730, 0x8790, 0x8840, 0x8990, 0x8BA0, 0x8F10, 0x9480, 0x9A30, 0x9F90, 0xA680, + 0xAD50, 0xB560, 0xBCF0, 0xC590, 0xCD70, 0xD570, 0xDE90, 0xE790, 0xF0C0, 0xFAC0, 0x04B0, 0x0F70, 0x19E0, 0x24C0, 0x2EF0, 0x39F0, + 0x44C0, 0x4ED0, 0x59B0, 0x6360, 0x6C40, 0x7510, 0x7B80, 0x7F00, 0x7F10, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, + 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, + 0x7F10, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7B70, 0x6A40, 0x5870, 0x4380, 0x3080, 0x1EC0, + 0x0E50, 0x0090, 0xF4D0, 0xEBE0, 0xE6A0, 0xE450, 0xE4F0, 0xE7A0, 0xEBF0, 0xF0C0, 0xF4D0, 0xF7D0, 0xF9E0, 0xFAB0, 0xFC40, 0xFD50, + 0xFFB0, 0x01A0, 0x0380, 0x0410, 0x0480, 0x03B0, 0x02A0, 0x0200, 0x01A0, 0x0300, 0x0480, 0x0730, 0x0B20, 0x0FE0, 0x1520, 0x1A00, + 0x1E10, 0x21D0, 0x2500, 0x2950, 0x2D80, 0x3270, 0x36E0, 0x3BC0, 0x4010, 0x44D0, 0x49F0, 0x4E40, 0x52C0, 0x56D0, 0x5AB0, 0x5E20, + 0x6120, 0x6410, 0x6730, 0x69C0, 0x6BD0, 0x6D30, 0x6E40, 0x6E60, 0x6E90, 0x6E90, 0x6E00, 0x6D20, 0x6B90, 0x6A00, 0x67B0, 0x65E0, + 0x63C0, 0x61B0, 0x5F30, 0x5CC0, 0x59A0, 0x55C0, 0x51A0, 0x4DB0, 0x4A10, 0x4660, 0x4340, 0x4040, 0x3D10, 0x3A60, 0x3710, 0x3490, + 0x31E0, 0x2F30, 0x2CC0, 0x2B10, 0x29D0, 0x2920, 0x2860, 0x2730, 0x2610, 0x2520, 0x2440, 0x2410, 0x24F0, 0x25A0, 0x26C0, 0x2770, + 0x2800, 0x2870, 0x28D0, 0x2960, 0x29C0, 0x2AC0, 0x2A50, 0x29B0, 0x2890, 0x2730, 0x2510, 0x2360, 0x21A0, 0x1FD0, 0x1DD0, 0x1C00, + 0x19A0, 0x1760, 0x1420, 0x10F0, 0x0D10, 0x08B0, 0x03C0, 0xFF00, 0xF8F0, 0xF2D0, 0xECC0, 0xE6A0, 0xE110, 0xDC00, 0xD7D0, 0xD420, + 0xD0C0, 0xCE30, 0xCC30, 0xCA00, 0xC7D0, 0xC5B0, 0xC460, 0xC330, 0xC240, 0xC210, 0xC190, 0xC130, 0xC100, 0xC160, 0xC240, 0xC360, + 0xC550, 0xC760, 0xC9B0, 0xCCC0, 0xD000, 0xD430, 0xD980, 0xDDD0, 0xE210, 0xE600, 0xE980, 0xEC90, 0xEF30, 0xF2E0, 0xF550, 0xF8E0, + 0xFB90, 0xFF70, 0x0450, 0x0900, 0x0EB0, 0x1480, 0x1A60, 0x2140, 0x2880, 0x2ED0, 0x3560, 0x3B20, 0x4200, 0x4990, 0x5070, 0x5820, + 0x5ED0, 0x65F0, 0x6BA0, 0x70F0, 0x7680, 0x7A80, 0x7E40, 0x7EF0, 0x7F70, 0x7F00, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, + 0x7EF0, 0x7F00, 0x7F20, 0x7F20, 0x7EC0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7E90, 0x7ED0, 0x7F10, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F40, 0x7F40, + 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7ED0, + 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7EF0, 0x7EE0, 0x7DC0, 0x79B0, 0x7430, 0x6E20, + 0x6700, 0x5E50, 0x5540, 0x4C40, 0x43F0, 0x3CB0, 0x35E0, 0x3160, 0x2D00, 0x2A80, 0x2820, 0x26F0, 0x2750, 0x27C0, 0x2940, 0x2A80, + 0x2AF0, 0x2C10, 0x2C40, 0x2CD0, 0x2E20, 0x2EE0, 0x3090, 0x3280, 0x34E0, 0x36E0, 0x3940, 0x3C90, 0x3EA0, 0x4040, 0x3E50, 0x3BD0, + 0x3900, 0x3610, 0x3390, 0x3020, 0x2C40, 0x2A10, 0x26E0, 0x2330, 0x1FF0, 0x1C40, 0x1950, 0x1630, 0x13A0, 0x11F0, 0x1030, 0x0F10, + 0x0DC0, 0x0BF0, 0x0A10, 0x07B0, 0x0530, 0x0240, 0xFE50, 0xF920, 0xF280, 0xEAB0, 0xE2E0, 0xDAD0, 0xD3C0, 0xCCE0, 0xC670, 0xBFA0, + 0xB840, 0xB0D0, 0xA7E0, 0xA000, 0x9790, 0x8F90, 0x8520, 0x84F0, 0x84E0, 0x84C0, 0x84C0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x84B0, 0x8490, 0x8490, 0x8490, 0x8490, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, + 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84F0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, + 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, + 0x8470, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83D0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x8360, 0x83B0, 0x83A0, 0x83A0, 0x8360, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8380, + 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8370, 0x8380, 0x83A0, 0x8370, 0x8370, 0x8370, 0x8380, 0x8380, 0x8390, + 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, + 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83D0, 0x8360, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, + 0x83E0, 0x83E0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x84A0, 0x84D0, + 0x84E0, 0x8530, 0x8610, 0x87A0, 0x89A0, 0x8A70, 0x8A00, 0x8900, 0x8770, 0x8660, 0x8590, 0x84E0, 0x8500, 0x84E0, 0x84E0, 0x84D0, + 0x8500, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x8510, 0x8580, 0x8900, 0xA060, 0xBBC0, 0xD580, 0xEB70, 0xFB20, 0x0860, + 0x1400, 0x2100, 0x3210, 0x4300, 0x5360, 0x6140, 0x69D0, 0x6E30, 0x6D00, 0x6780, 0x5DD0, 0x4F20, 0x3EC0, 0x2B80, 0x15D0, 0xFFE0, + 0xEA00, 0xD620, 0xC240, 0xAD20, 0x93C0, 0x8690, 0x84F0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x84C0, 0x8490, + 0x84A0, 0x84B0, 0x84D0, 0x8500, 0x8600, 0x8DC0, 0xAAA0, 0xC790, 0xE670, 0x06B0, 0x27B0, 0x4900, 0x6820, 0x7ED0, 0x7F30, 0x7F30, + 0x7F50, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F00, 0x7F40, 0x7ED0, 0x73F0, 0x6920, 0x5CF0, 0x5190, 0x46A0, 0x3CE0, 0x3450, 0x2D90, 0x2840, 0x24E0, 0x2290, + 0x2260, 0x2340, 0x2490, 0x2660, 0x2860, 0x2A10, 0x2B50, 0x2CD0, 0x2DA0, 0x2E50, 0x2E40, 0x2E50, 0x2D40, 0x2C60, 0x2BD0, 0x2C00, + 0x2C60, 0x2DE0, 0x2F30, 0x3030, 0x30C0, 0x3090, 0x3020, 0x2FE0, 0x30E0, 0x32A0, 0x3510, 0x39A0, 0x3FE0, 0x46D0, 0x4F60, 0x57A0, + 0x6040, 0x68C0, 0x7090, 0x7740, 0x7D40, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7E40, 0x7530, 0x6C70, 0x62F0, 0x5990, 0x4F40, 0x4640, 0x3E80, 0x3630, + 0x2F20, 0x2840, 0x2300, 0x1DA0, 0x18C0, 0x1590, 0x1290, 0x0FF0, 0x0F10, 0x0F10, 0x1160, 0x1560, 0x1A60, 0x2130, 0x2A10, 0x3550, + 0x4360, 0x5340, 0x6530, 0x7860, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7EF0, 0x7F30, 0x7EF0, 0x7EA0, 0x7F20, 0x7EF0, + 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F10, 0x7F40, 0x7ED0, 0x7E90, 0x7F20, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F20, 0x7F20, + 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F40, 0x7EF0, 0x7F30, 0x7F30, 0x7F00, 0x7F80, 0x7F10, 0x7F00, 0x7F00, + 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7F00, 0x7EF0, 0x7F50, 0x7F00, 0x7E70, 0x7EC0, 0x7ED0, + 0x7F20, 0x7F20, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E90, 0x7E60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, + 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F40, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, + 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F50, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7EE0, + 0x7F50, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7E70, 0x7F10, 0x7EF0, 0x7EF0, 0x7EF0, 0x7E80, 0x7F10, 0x7F00, 0x7F20, + 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, + 0x7EF0, 0x7F60, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F80, 0x7F20, 0x7F00, 0x7ED0, 0x7ED0, 0x7F30, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, + 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7E90, 0x7EB0, 0x7EF0, 0x7EE0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, + 0x7EC0, 0x7EF0, 0x7F10, 0x7E90, 0x7ED0, 0x7F00, 0x7F00, 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F40, + 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7F10, + 0x7F30, 0x7F00, 0x7F80, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F70, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7ED0, 0x7EB0, + 0x7EE0, 0x7F60, 0x7F00, 0x7E90, 0x7EB0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, + 0x7F10, 0x7F00, 0x7EE0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F80, 0x7F10, 0x7F20, + 0x7EF0, 0x7EF0, 0x7F50, 0x7F00, 0x7F00, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F60, 0x7EE0, 0x7E90, 0x7F10, 0x7F00, 0x7EF0, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, + 0x7ED0, 0x7D10, 0x7AA0, 0x79C0, 0x78C0, 0x77B0, 0x7860, 0x7900, 0x7A50, 0x7BD0, 0x7D60, 0x7EC0, 0x7F10, 0x7F80, 0x7F00, 0x7F00, + 0x7EF0, 0x7F10, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F80, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7ED0, 0x7EF0, + 0x7F00, 0x7F40, 0x7F10, 0x7E90, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E70, 0x7ED0, 0x7F10, 0x7F20, 0x7F40, 0x7EA0, 0x7ED0, 0x7F10, + 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7480, 0x4BE0, 0x28C0, 0x0B60, 0xF590, 0xE570, 0xD9E0, 0xD300, 0xD000, + 0xD120, 0xD710, 0xE290, 0xF480, 0x0D80, 0x2C80, 0x4F90, 0x71B0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, + 0x7F00, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EC0, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x71A0, 0x34A0, 0xF7D0, + 0xBB00, 0x88A0, 0x84B0, 0x8480, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, + 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8430, + 0x8430, 0x8430, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8500, + 0x8580, 0x8690, 0x8950, 0x8FD0, 0x98C0, 0xA070, 0xA7D0, 0xAF10, 0xB710, 0xBFE0, 0xC6D0, 0xCD40, 0xD390, 0xD900, 0xDDC0, 0xE290, + 0xE7F0, 0xECD0, 0xF1B0, 0xF570, 0xF970, 0xFC60, 0xFF10, 0x01D0, 0x0410, 0x05F0, 0x0780, 0x0890, 0x0920, 0x0A40, 0x0A50, 0x0A10, + 0x0970, 0x0850, 0x06F0, 0x04B0, 0x0280, 0x0080, 0xFE30, 0xFB40, 0xF900, 0xF5B0, 0xF2B0, 0xEFF0, 0xEE10, 0xED10, 0xEC60, 0xEBE0, + 0xEC50, 0xED30, 0xEE80, 0xF020, 0xF230, 0xF4A0, 0xF780, 0xFA90, 0xFDF0, 0x0220, 0x0620, 0x0A10, 0x0D90, 0x11E0, 0x16E0, 0x1D70, + 0x2500, 0x2EC0, 0x3970, 0x44F0, 0x5060, 0x5B40, 0x6550, 0x6F10, 0x7730, 0x7CE0, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7E00, 0x7550, 0x6A60, 0x5CF0, 0x4D10, 0x3B00, 0x2620, 0x0CA0, 0xF2B0, 0xD690, 0xBA90, 0x9FA0, 0x8AF0, + 0x8590, 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x8500, 0x8570, 0x87A0, 0x9AA0, 0xB2C0, 0xCB10, 0xE070, + 0xF170, 0xFB60, 0xFD30, 0xF5F0, 0xE5F0, 0xCDA0, 0xB200, 0x9550, 0x86B0, 0x8500, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8490, + 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8490, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, + 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8520, 0x8550, 0x8590, 0x85E0, 0x8620, 0x86D0, 0x8770, 0x8870, 0x8A90, 0x8D80, + 0x9150, 0x95B0, 0x99E0, 0x9E50, 0xA410, 0xAA80, 0xB280, 0xBB00, 0xC3E0, 0xCD50, 0xD610, 0xDFA0, 0xE8E0, 0xF3A0, 0xFDA0, 0x0650, + 0x0FB0, 0x17E0, 0x2040, 0x2810, 0x2F80, 0x3760, 0x3E10, 0x4490, 0x49B0, 0x4E70, 0x5400, 0x5880, 0x5D80, 0x61E0, 0x6680, 0x6AB0, + 0x6E80, 0x7260, 0x7600, 0x7970, 0x7CA0, 0x7EC0, 0x7F40, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7EF0, + 0x7F40, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7F30, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F50, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F30, + 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, + 0x7F00, 0x7F10, 0x7EF0, 0x7F00, 0x7F20, 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F80, 0x4240, 0xED50, 0x9040, 0x84A0, + 0x8470, 0x8450, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8460, 0x8460, 0x8450, 0x8460, 0x8490, 0x8480, 0x84C0, + 0x84B0, 0x84D0, 0x8500, 0x85F0, 0x8A50, 0x97D0, 0xA3A0, 0xACF0, 0xB460, 0xBA50, 0xBED0, 0xC180, 0xC1F0, 0xC0B0, 0xBEB0, 0xBD40, + 0xBC60, 0xBD90, 0xC0D0, 0xC5E0, 0xCCD0, 0xD500, 0xDE60, 0xE8C0, 0xF470, 0x0200, 0x1060, 0x2180, 0x30E0, 0x3E90, 0x4AD0, 0x53A0, + 0x58E0, 0x5AE0, 0x5B90, 0x5D70, 0x60E0, 0x66C0, 0x6EF0, 0x77D0, 0x7EA0, 0x7F10, 0x7F50, 0x7EB0, 0x7E70, 0x7F10, 0x7F00, 0x7F60, + 0x7ED0, 0x7EB0, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7EA0, 0x7F10, 0x7F10, 0x7F20, 0x7E70, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, + 0x7F80, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F00, 0x7EF0, 0x7ED0, 0x7F60, 0x7F10, 0x7ED0, 0x7EF0, 0x7F20, 0x7F40, + 0x7F10, 0x7F90, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EC0, 0x7EC0, + 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, + 0x7F20, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7390, 0x6630, 0x5CA0, 0x5480, 0x4F00, 0x4BA0, 0x48C0, 0x4690, + 0x4470, 0x41B0, 0x3E70, 0x3A50, 0x36E0, 0x3370, 0x30C0, 0x2E90, 0x2DB0, 0x2EC0, 0x3080, 0x3330, 0x3760, 0x3B50, 0x4030, 0x4530, + 0x4A60, 0x4F40, 0x52D0, 0x54A0, 0x5460, 0x51F0, 0x4F70, 0x4B80, 0x4800, 0x4490, 0x4120, 0x3EE0, 0x3CF0, 0x3CF0, 0x3DB0, 0x3F90, + 0x4360, 0x46C0, 0x4BD0, 0x50F0, 0x55A0, 0x5B20, 0x6040, 0x6520, 0x6A30, 0x6DE0, 0x7240, 0x7580, 0x78B0, 0x7BA0, 0x7D70, 0x7EF0, + 0x7F10, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F30, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, + 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7F10, 0x7F00, 0x7EF0, 0x7F90, + 0x7F00, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F30, 0x7F00, + 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7EC0, 0x7F30, 0x7F00, 0x7F00, 0x7F00, 0x7F00, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7F50, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, + 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7E70, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, + 0x7EC0, 0x7EF0, 0x7F00, 0x7F00, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F20, 0x7F20, 0x7F20, 0x7F00, + 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F00, 0x7EF0, 0x7F30, + 0x74C0, 0x4FC0, 0x29C0, 0x0160, 0xD6F0, 0xABE0, 0x88C0, 0x84E0, 0x84A0, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, + 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8410, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8410, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84C0, 0x84E0, + 0x8500, 0x8540, 0x8670, 0x8930, 0x8FA0, 0x9770, 0x9EE0, 0xA590, 0xABE0, 0xB280, 0xBAE0, 0xC380, 0xCC90, 0xD410, 0xDB20, 0xE040, + 0xE350, 0xE480, 0xE420, 0xE240, 0xDF30, 0xD9B0, 0xD340, 0xCCE0, 0xC7A0, 0xC3B0, 0xC240, 0xC320, 0xC4A0, 0xC5B0, 0xC530, 0xC230, + 0xBBF0, 0xB1A0, 0xA570, 0x98D0, 0x8DB0, 0x87C0, 0x85B0, 0x8510, 0x84E0, 0x84C0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8440, 0x8440, + 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83F0, 0x83D0, 0x83D0, 0x8410, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83B0, + 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x8400, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, + 0x8410, 0x8430, 0x8430, 0x8430, 0x8470, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8470, 0x8460, 0x8460, + 0x8460, 0x8450, 0x8460, 0x8460, 0x8470, 0x8450, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, + 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8540, + 0x85C0, 0x8710, 0x8BC0, 0x9860, 0xA810, 0xB7C0, 0xC690, 0xD3F0, 0xDF90, 0xE900, 0xEF90, 0xF430, 0xF620, 0xF7B0, 0xF7D0, 0xF920, + 0xFAE0, 0xFD90, 0x02B0, 0x08C0, 0x10C0, 0x1910, 0x2020, 0x26E0, 0x2CC0, 0x31B0, 0x3760, 0x3BA0, 0x4110, 0x4610, 0x4A70, 0x4E90, + 0x50D0, 0x52E0, 0x5340, 0x5390, 0x53B0, 0x53E0, 0x54C0, 0x5510, 0x55D0, 0x5650, 0x56A0, 0x57E0, 0x58E0, 0x5990, 0x5A90, 0x5A70, + 0x5B70, 0x5B10, 0x5A70, 0x5920, 0x5660, 0x5310, 0x4EE0, 0x4AE0, 0x4780, 0x4450, 0x4340, 0x42C0, 0x4330, 0x4530, 0x46E0, 0x49C0, + 0x4C90, 0x4F30, 0x5300, 0x5600, 0x5910, 0x5C00, 0x5EE0, 0x6250, 0x64B0, 0x65A0, 0x64C0, 0x6250, 0x5EE0, 0x59C0, 0x5390, 0x4D50, + 0x46A0, 0x3FA0, 0x3870, 0x3230, 0x2D60, 0x29B0, 0x28B0, 0x2960, 0x2B50, 0x2EA0, 0x3160, 0x3470, 0x34B0, 0x32B0, 0x2F20, 0x2980, + 0x2540, 0x23F0, 0x26E0, 0x2FC0, 0x3C90, 0x4D10, 0x5E40, 0x6EF0, 0x7C50, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, + 0x7F00, 0x7F00, 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F50, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, + 0x7F10, 0x7F10, 0x7F30, 0x7EC0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7F30, 0x7EF0, 0x7EA0, 0x7F20, 0x7F10, 0x7F10, 0x7EE0, 0x7EC0, 0x7F10, + 0x7ED0, 0x7F00, 0x7EF0, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7E90, 0x7F10, 0x7F20, 0x7F40, 0x7ED0, 0x7EA0, + 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7EE0, 0x7F00, 0x7F20, 0x7F00, 0x7F50, + 0x7F20, 0x7F40, 0x7EF0, 0x7F10, 0x7F70, 0x7EF0, 0x7F00, 0x7F10, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, 0x7F20, + 0x7F00, 0x7EF0, 0x7EB0, 0x7F30, 0x7EF0, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7ED0, 0x7F00, 0x7F00, 0x7EF0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, + 0x7EF0, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F50, 0x7EE0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F30, 0x7EE0, 0x7EC0, + 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F30, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, + 0x7EE0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7E70, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, 0x7EC0, + 0x7ED0, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7EB0, 0x7F20, + 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F60, 0x7F00, + 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F50, 0x7F10, 0x7CB0, + 0x6470, 0x4910, 0x2E70, 0x1310, 0xF660, 0xD8B0, 0xB990, 0x9A30, 0x8740, 0x84F0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, + 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8480, 0x8480, 0x8450, 0x8460, 0x8420, 0x8470, 0x8470, 0x84B0, 0x8480, 0x8490, + 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8550, 0x8640, 0x8940, 0x92D0, 0x9F10, 0xAA90, 0xB690, 0xC230, 0xCDF0, 0xD980, 0xE380, + 0xEC50, 0xF590, 0xFE70, 0x0720, 0x0F50, 0x18B0, 0x2040, 0x2810, 0x2F80, 0x34E0, 0x3A20, 0x3ED0, 0x4270, 0x46E0, 0x4B40, 0x4EF0, + 0x5300, 0x55B0, 0x5840, 0x5A00, 0x5BB0, 0x5E00, 0x5F50, 0x6060, 0x6160, 0x62F0, 0x6450, 0x6560, 0x66A0, 0x6780, 0x6790, 0x6750, + 0x66E0, 0x6690, 0x6710, 0x67B0, 0x68C0, 0x69C0, 0x6AD0, 0x6C00, 0x6DA0, 0x7020, 0x7240, 0x7510, 0x7810, 0x7AA0, 0x7D20, 0x7EB0, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F10, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7EF0, 0x7E90, 0x7D10, 0x7B60, 0x79A0, 0x7850, 0x7630, 0x73B0, 0x7260, 0x7150, 0x6F70, 0x6E30, 0x6CA0, 0x6BE0, + 0x6B90, 0x6AA0, 0x6B00, 0x69D0, 0x68C0, 0x6810, 0x6790, 0x67A0, 0x6820, 0x69D0, 0x6B80, 0x6D00, 0x6E00, 0x6E10, 0x6F10, 0x6F80, + 0x7020, 0x7050, 0x7000, 0x6FA0, 0x6EA0, 0x6C90, 0x6BE0, 0x6A40, 0x6910, 0x6830, 0x66A0, 0x6560, 0x6480, 0x6450, 0x64A0, 0x6540, + 0x6730, 0x68A0, 0x6A20, 0x6BE0, 0x6D90, 0x7090, 0x72A0, 0x7480, 0x7720, 0x7880, 0x7A90, 0x7BB0, 0x7CF0, 0x7DE0, 0x7E90, 0x7EF0, + 0x7EE0, 0x7F40, 0x7E80, 0x7E20, 0x7D20, 0x7C20, 0x7A90, 0x7950, 0x7700, 0x7560, 0x7290, 0x6FF0, 0x6D20, 0x6910, 0x65B0, 0x61B0, + 0x5D60, 0x5950, 0x54B0, 0x5060, 0x4B90, 0x45B0, 0x3FE0, 0x3900, 0x32D0, 0x2BB0, 0x2480, 0x1EA0, 0x1730, 0x1020, 0x0940, 0x0240, + 0xFC30, 0xF5D0, 0xEF20, 0xE830, 0xE0B0, 0xD7E0, 0xD040, 0xC930, 0xC2C0, 0xBC40, 0xB5B0, 0xAED0, 0xA8A0, 0xA260, 0x9B80, 0x9660, + 0x91C0, 0x8DE0, 0x8B40, 0x8990, 0x88C0, 0x8850, 0x8830, 0x8850, 0x88C0, 0x8920, 0x8960, 0x89D0, 0x8AE0, 0x8C70, 0x8FA0, 0x9430, + 0x9880, 0x9CE0, 0xA060, 0xA3F0, 0xA730, 0xAA60, 0xAE20, 0xB0C0, 0xB3B0, 0xB820, 0xBB60, 0xBF50, 0xC300, 0xC6C0, 0xCAA0, 0xCD50, + 0xD060, 0xD370, 0xD6F0, 0xDA20, 0xDCC0, 0xDFB0, 0xE300, 0xE5A0, 0xE8F0, 0xEAD0, 0xEDB0, 0xEFC0, 0xF1B0, 0xF430, 0xF5A0, 0xF770, + 0xF870, 0xF960, 0xFB40, 0xFD00, 0xFEE0, 0x00A0, 0x01F0, 0x0350, 0x04F0, 0x05C0, 0x0720, 0x0870, 0x0A60, 0x0B30, 0x0C20, 0x0DD0, + 0x0EB0, 0x1060, 0x1110, 0x1250, 0x1250, 0x1170, 0x1010, 0x0EB0, 0x0E60, 0x0CF0, 0x0B10, 0x08A0, 0x0500, 0x0100, 0xFC30, 0xF670, + 0xF160, 0xEBD0, 0xE630, 0xDFB0, 0xD8B0, 0xD210, 0xCB50, 0xC530, 0xBF00, 0xB8F0, 0xB3E0, 0xAE70, 0xAA10, 0xA700, 0xA530, 0xA4B0, + 0xA480, 0xA530, 0xAE10, 0xB150, 0xB4C0, 0xB8E0, 0xBCA0, 0xC0B0, 0xC4E0, 0xC860, 0xCC30, 0xCF40, 0xD210, 0xD360, 0xD410, 0xD450, + 0xD4A0, 0xD580, 0xD730, 0xD8A0, 0xD890, 0xD760, 0xD430, 0xCE40, 0xC6A0, 0xBCE0, 0xB270, 0xA6D0, 0x9A40, 0x8EC0, 0x87E0, 0x8580, + 0x84F0, 0x84C0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8440, 0x8430, 0x8430, 0x8420, + 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8410, 0x8430, 0x8420, 0x8410, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, + 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8420, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8460, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84E0, 0x84C0, 0x84B0, 0x84B0, 0x84D0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, + 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, + 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x8480, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8530, 0x8550, 0x8580, 0x8600, 0x86E0, + 0x8870, 0x8BD0, 0x91C0, 0x9860, 0x9FB0, 0xA6F0, 0xAE90, 0xB6A0, 0xBDF0, 0xC5B0, 0xCDB0, 0xD520, 0xDC90, 0xE4E0, 0xECC0, 0xF410, + 0xFAF0, 0x00F0, 0x0700, 0x0C70, 0x1250, 0x1920, 0x1FF0, 0x2660, 0x2C10, 0x3280, 0x38F0, 0x3F70, 0x4620, 0x4BD0, 0x5130, 0x5670, + 0x5B40, 0x6090, 0x6600, 0x6B00, 0x6FF0, 0x72F0, 0x7710, 0x79E0, 0x7CF0, 0x7ED0, 0x7F20, 0x7F40, 0x7F10, 0x7F50, 0x7F00, 0x7F20, + 0x7EF0, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F70, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F10, + 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F40, 0x7F30, 0x5F70, 0x3700, 0x11C0, 0xF510, 0xDC00, 0xC420, 0xAB50, 0x9200, 0x8630, 0x84E0, 0x84B0, 0x8490, 0x8490, + 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, + 0x8440, 0x8430, 0x8440, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8440, 0x8400, 0x8400, 0x8410, 0x8410, 0x8400, + 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8480, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8440, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, + 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x8640, 0x90E0, 0xA7F0, 0xBEE0, 0xD580, 0xEA70, 0xFD30, 0x0CA0, 0x1A50, 0x2530, 0x2EF0, 0x3760, + 0x3D50, 0x4210, 0x4480, 0x42C0, 0x3ED0, 0x3690, 0x2C30, 0x1DD0, 0x0EE0, 0x0030, 0xF160, 0xE2D0, 0xD430, 0xC3F0, 0xB180, 0x99A0, + 0x8660, 0x84C0, 0x8480, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x8530, 0x8690, 0x8DC0, 0x9EC0, + 0xAE70, 0xBE00, 0xCC20, 0xD9C0, 0xE930, 0xF6E0, 0x0390, 0x1030, 0x1B70, 0x26D0, 0x3200, 0x3DE0, 0x49A0, 0x5490, 0x5ED0, 0x6800, + 0x70E0, 0x7880, 0x7DD0, 0x7F10, 0x7F00, 0x7F50, 0x7F00, 0x7F00, 0x7F20, 0x7EF0, 0x7F80, 0x7F20, 0x7F40, 0x7F10, 0x7EF0, 0x7F80, + 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F50, 0x7F10, 0x7EE0, 0x7F00, 0x7F00, 0x7F60, 0x7F00, 0x7ED0, 0x7ED0, 0x7EB0, 0x7EF0, 0x7EF0, + 0x7EB0, 0x7ED0, 0x7EF0, 0x7F30, 0x7F20, 0x7E90, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7E70, 0x7D20, 0x7B60, 0x78F0, 0x7730, 0x7500, + 0x7340, 0x7210, 0x7090, 0x6FC0, 0x6F10, 0x6E30, 0x6DE0, 0x6C40, 0x6B40, 0x6990, 0x68A0, 0x6800, 0x6750, 0x6820, 0x6AA0, 0x6E60, + 0x7390, 0x79F0, 0x7EA0, 0x7EE0, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7ED0, 0x7F00, 0x7EE0, 0x7F70, 0x7ED0, + 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7E90, 0x7F00, 0x7EE0, 0x7DC0, 0x7230, 0x64A0, + 0x54E0, 0x45B0, 0x35C0, 0x26C0, 0x1700, 0x0590, 0xF3B0, 0xDFF0, 0xCC00, 0xB5E0, 0xA2B0, 0x9110, 0x87D0, 0x8580, 0x8500, 0x84E0, + 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8540, 0x8590, 0x8630, 0x8790, 0x8A90, 0x9050, 0x9790, + 0x9E90, 0xA570, 0xAC60, 0xB330, 0xBA70, 0xC170, 0xC870, 0xCF00, 0xD540, 0xDA90, 0xDFA0, 0xE470, 0xE8F0, 0xED60, 0xF240, 0xF690, + 0xFA50, 0xFD90, 0x0040, 0x0210, 0x02F0, 0x0290, 0x0050, 0xFD00, 0xF9E0, 0xF630, 0xF2F0, 0xF100, 0xF090, 0xF2B0, 0xF6F0, 0xFE20, + 0x0620, 0x0E90, 0x17D0, 0x1FB0, 0x2520, 0x2970, 0x2B40, 0x2B20, 0x28F0, 0x2410, 0x1EC0, 0x18C0, 0x1410, 0x1150, 0x1040, 0x1160, + 0x12D0, 0x14E0, 0x1500, 0x13D0, 0x11D0, 0x0E30, 0x09E0, 0x0440, 0xFED0, 0xF960, 0xF350, 0xEDC0, 0xE630, 0xDB70, 0xCCC0, 0xB8D0, + 0xA170, 0x8BA0, 0x8560, 0x84D0, 0x84B0, 0x84A0, 0x84A0, 0x8470, 0x8470, 0x8460, 0x8470, 0x8470, 0x8420, 0x8470, 0x8470, 0x8470, + 0x8480, 0x8490, 0x84A0, 0x84E0, 0x85C0, 0x9BC0, 0xBD20, 0xDBE0, 0xF830, 0x1220, 0x2C40, 0x4440, 0x5B90, 0x6F80, 0x7DE0, 0x7EF0, + 0x7F00, 0x7F30, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7EE0, 0x7EF0, 0x7F50, 0x7F00, 0x7F20, 0x7F10, 0x4A50, + 0x01E0, 0xBD80, 0x8700, 0x8490, 0x8460, 0x8440, 0x8420, 0x83F0, 0x83E0, 0x83D0, 0x83C0, 0x83B0, 0x83A0, 0x8390, 0x8390, 0x8380, + 0x8380, 0x8370, 0x8370, 0x8370, 0x8360, 0x8360, 0x8360, 0x8320, 0x8370, 0x8360, 0x8370, 0x8390, 0x8370, 0x8370, 0x8310, 0x8380, + 0x8380, 0x8380, 0x8390, 0x8390, 0x8390, 0x8350, 0x83A0, 0x8390, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8400, 0x8420, 0x8420, + 0x8420, 0x8400, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x84F0, 0x8520, 0x8580, 0x86D0, 0x8FF0, 0xA1F0, 0xB4E0, 0xCB10, + 0xE2A0, 0xFB90, 0x1550, 0x2F30, 0x47A0, 0x5EF0, 0x7560, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F40, 0x7F20, 0x7F10, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F00, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F30, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F90, 0x7F30, + 0x7F00, 0x7F00, 0x7EF0, 0x7F50, 0x7F20, 0x7F00, 0x7F00, 0x7EB0, 0x7F20, 0x7EE0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7F50, 0x7F00, 0x7F00, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EB0, 0x7EF0, 0x7EE0, 0x7F30, 0x7F30, 0x7EA0, 0x7F00, 0x7ED0, 0x7AB0, 0x70A0, 0x6840, 0x62D0, + 0x5E30, 0x5B20, 0x5960, 0x5880, 0x5840, 0x5830, 0x56D0, 0x5580, 0x51A0, 0x4D00, 0x4790, 0x4130, 0x3A60, 0x32C0, 0x2A70, 0x2200, + 0x1BA0, 0x1870, 0x18B0, 0x1BA0, 0x21F0, 0x2800, 0x2D90, 0x3130, 0x3330, 0x34F0, 0x3690, 0x38E0, 0x3AF0, 0x3E30, 0x4230, 0x4760, + 0x4DF0, 0x5700, 0x5FD0, 0x6890, 0x7120, 0x7970, 0x7E90, 0x7F30, 0x7F00, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, + 0x7EF0, 0x7EF0, 0x7F10, 0x7E70, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F30, 0x7EF0, + 0x7F00, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F90, 0x7F00, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7F30, 0x7F00, 0x7E70, 0x7ED0, 0x7ED0, 0x7F20, 0x7F40, 0x7E90, 0x7ED0, + 0x7EE0, 0x7F10, 0x7F10, 0x7E90, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F20, + 0x7EF0, 0x7F10, 0x7ED0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, + 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7F00, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F10, 0x7F40, 0x7ED0, 0x7EB0, 0x7F00, + 0x7F10, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7EF0, 0x7F20, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, + 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F80, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F10, 0x7F10, 0x7F00, 0x76A0, 0x66D0, 0x57E0, 0x4740, 0x3840, 0x29D0, 0x1C90, 0x0EB0, + 0x01F0, 0xF6A0, 0xEB90, 0xE090, 0xD660, 0xCC10, 0xC310, 0xB9F0, 0xB110, 0xA8F0, 0xA0B0, 0x98A0, 0x9250, 0x8DD0, 0x8B50, 0x8970, + 0x8850, 0x87F0, 0x87D0, 0x8800, 0x88A0, 0x89F0, 0x8CC0, 0x9160, 0x9740, 0x9D60, 0xA440, 0xAB90, 0xB370, 0xBB80, 0xC3B0, 0xCBE0, + 0xD350, 0xDB10, 0xE300, 0xEBE0, 0xF400, 0xFB80, 0x0350, 0x0B20, 0x11F0, 0x1860, 0x1E10, 0x23F0, 0x2A40, 0x2EF0, 0x33D0, 0x3870, + 0x3C60, 0x4150, 0x4630, 0x4A70, 0x4F20, 0x5320, 0x5740, 0x5A90, 0x5DB0, 0x6140, 0x6400, 0x67B0, 0x6AA0, 0x6DF0, 0x71D0, 0x7490, + 0x7830, 0x7B60, 0x7DD0, 0x7EF0, 0x7F00, 0x7F40, 0x7F00, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F00, 0x7F20, 0x7F20, 0x7EF0, 0x7F90, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F70, 0x7F20, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7ED0, 0x7EF0, 0x7F20, 0x7F20, 0x7EC0, + 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F30, + 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, + 0x7EF0, 0x7F00, 0x7F00, 0x7F70, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EA0, 0x7AC0, 0x7610, 0x6FA0, 0x6820, 0x5FD0, 0x5590, + 0x4A90, 0x3CD0, 0x2EB0, 0x2030, 0x1060, 0xFFC0, 0xEDD0, 0xDBA0, 0xC980, 0xB560, 0x9E60, 0x8B50, 0x8570, 0x84E0, 0x84B0, 0x8490, + 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x84A0, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, + 0x84D0, 0x8510, 0x85C0, 0x8940, 0x99C0, 0xAB80, 0xBE30, 0xCFE0, 0xE090, 0xF170, 0x0060, 0x0FC0, 0x1AF0, 0x2330, 0x2B10, 0x2F10, + 0x30E0, 0x3040, 0x2E10, 0x2AF0, 0x2640, 0x2190, 0x1CC0, 0x1730, 0x10C0, 0x0950, 0x0040, 0xF6E0, 0xED30, 0xE4D0, 0xDC20, 0xD3C0, + 0xCBB0, 0xC400, 0xBD00, 0xB590, 0xAFA0, 0xAB00, 0xA7A0, 0xA610, 0xA570, 0xA530, 0xA580, 0xA660, 0xA7A0, 0xAAD0, 0xB0F0, 0xBB10, + 0xCA10, 0xDEE0, 0xF8E0, 0x1650, 0x3490, 0x5400, 0x6D50, 0x7E30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, + 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F30, 0x7F00, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7EF0, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7DB0, 0x6EF0, + 0x6280, 0x57C0, 0x4E70, 0x4680, 0x3E40, 0x3640, 0x2EE0, 0x2A20, 0x2740, 0x26D0, 0x2810, 0x2B70, 0x2FC0, 0x33D0, 0x3650, 0x37E0, + 0x39A0, 0x3AD0, 0x3B90, 0x3D30, 0x4040, 0x43F0, 0x48D0, 0x5930, 0x5BE0, 0x5CF0, 0x5D90, 0x5D30, 0x5C40, 0x5AF0, 0x58D0, 0x5620, + 0x52C0, 0x4DC0, 0x47A0, 0x4130, 0x39F0, 0x31E0, 0x2980, 0x2040, 0x1690, 0x0CA0, 0x0260, 0xF6D0, 0xEBB0, 0xE010, 0xD400, 0xC800, + 0xBC00, 0xB130, 0xA620, 0x9C20, 0x91F0, 0x8BC0, 0x8840, 0x86A0, 0x85E0, 0x85D0, 0x8580, 0x8590, 0x85D0, 0x8660, 0x8780, 0x89B0, + 0x8D40, 0x9260, 0x9690, 0x9A90, 0x9DA0, 0x9F90, 0xA270, 0xA500, 0xA850, 0xACE0, 0xB1C0, 0xB760, 0xBC90, 0xC2E0, 0xC8B0, 0xCDB0, + 0xD1F0, 0xD550, 0xD900, 0xDCE0, 0xDF60, 0xE160, 0xE2C0, 0xE3B0, 0xE430, 0xE350, 0xE1A0, 0xDDE0, 0xD930, 0xD310, 0xCBE0, 0xC420, + 0xBCA0, 0xB3C0, 0xAB90, 0xA330, 0x9A50, 0x9040, 0x88D0, 0x8600, 0x8520, 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x84C0, 0x8480, + 0x8470, 0x8460, 0x8490, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8410, 0x8430, 0x8430, 0x8430, + 0x8450, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84F0, 0x84D0, 0x84F0, 0x8510, 0x8570, 0x8670, + 0x89B0, 0x9250, 0x9DE0, 0xA830, 0xB1F0, 0xBC00, 0xC610, 0xD060, 0xDB80, 0xE650, 0xF150, 0xFBC0, 0x05A0, 0x1000, 0x19D0, 0x24B0, + 0x2F60, 0x39C0, 0x43B0, 0x4D80, 0x58D0, 0x62D0, 0x6BB0, 0x7440, 0x7B40, 0x7ED0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EE0, + 0x7F50, 0x7F20, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F10, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F20, 0x7F20, + 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F10, 0x7F00, + 0x7EF0, 0x7F30, 0x7EF0, 0x7F20, 0x7ED0, 0x7BF0, 0x77F0, 0x73C0, 0x6F50, 0x6BB0, 0x6800, 0x6510, 0x61B0, 0x5EB0, 0x5C60, 0x5990, + 0x56A0, 0x5420, 0x5100, 0x4F30, 0x4D30, 0x4C40, 0x4BD0, 0x4B90, 0x4BC0, 0x4850, 0x4740, 0x45E0, 0x44D0, 0x4430, 0x4320, 0x4240, + 0x4150, 0x3FF0, 0x3F80, 0x3E10, 0x3D00, 0x3B70, 0x3940, 0x36F0, 0x3400, 0x3260, 0x3040, 0x2EF0, 0x2E00, 0x2D00, 0x2C30, 0x2A30, + 0x2740, 0x24E0, 0x2140, 0x1D90, 0x1A50, 0x1770, 0x1560, 0x12F0, 0x1090, 0x0E00, 0x0B60, 0x0840, 0x0480, 0x00B0, 0xFD80, 0xFB00, + 0xF870, 0xF580, 0xF250, 0xEF50, 0xEAA0, 0xE760, 0xE490, 0xE1B0, 0xDF30, 0xDC70, 0xDA30, 0xD6F0, 0xD3D0, 0xD0A0, 0xCC40, 0xC8A0, + 0xC5C0, 0xC2E0, 0xC0B0, 0xBEB0, 0xBCB0, 0xBA60, 0xB790, 0xB4F0, 0xB180, 0xAEB0, 0xAC10, 0xA870, 0xA620, 0xA420, 0xA270, 0x9FF0, + 0x9CE0, 0x9A10, 0x96E0, 0x9330, 0x9060, 0x8DD0, 0x8BB0, 0x89F0, 0x8890, 0x8760, 0x86A0, 0x8610, 0x85D0, 0x8590, 0x8570, 0x8550, + 0x8530, 0x8520, 0x8510, 0x8500, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x84C0, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8430, 0x8480, 0x8470, 0x8470, 0x8430, 0x8480, 0x8480, 0x8470, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x84B0, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84B0, 0x84B0, 0x84C0, 0x8510, 0x8500, + 0x8530, 0x85C0, 0x8750, 0x8D40, 0x9980, 0xA690, 0xB4A0, 0xC1C0, 0xCEE0, 0xDC90, 0xE9B0, 0xF720, 0x0590, 0x12D0, 0x1F30, 0x2A60, + 0x34D0, 0x3D90, 0x4460, 0x48C0, 0x4AD0, 0x4AB0, 0x4540, 0x3CD0, 0x2F10, 0x1D20, 0x07E0, 0xEDD0, 0xD030, 0xB0B0, 0x8E10, 0x8530, + 0x84C0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8440, 0x8450, 0x8450, + 0x8460, 0x8460, 0x8470, 0x8480, 0x84A0, 0x84C0, 0x8590, 0xA040, 0xD550, 0x0E70, 0x4100, 0x6BB0, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7E90, 0x4DE0, 0x11C0, 0xBDE0, 0x84B0, + 0x8440, 0x8410, 0x8410, 0x83C0, 0x83B0, 0x83A0, 0x8390, 0x83C0, 0x83A0, 0x83C0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x8380, 0x83B0, + 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x8430, 0x83F0, 0x83F0, 0x8400, 0x8400, + 0x8430, 0x8400, 0x8400, 0x83E0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, + 0x8490, 0x84B0, 0x8510, 0x88C0, 0xA830, 0xC6F0, 0xE3D0, 0xFDE0, 0x1810, 0x2EB0, 0x4380, 0x5800, 0x6C40, 0x7DB0, 0x7F20, 0x7F40, + 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F30, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7EF0, 0x7F20, 0x7F10, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, + 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7E90, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7ED0, 0x7EF0, + 0x7EE0, 0x7E80, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F00, + 0x7F00, 0x7F10, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7EF0, 0x7F00, 0x7F40, 0x7F00, + 0x7F10, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F90, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, + 0x7EA0, 0x7EF0, 0x7F00, 0x7F00, 0x7F10, 0x7E90, 0x7E70, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, + 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x6B50, 0x5A00, 0x4B00, 0x3FF0, 0x3770, 0x31A0, 0x2FB0, 0x3110, 0x3640, + 0x3E90, 0x49A0, 0x57D0, 0x66C0, 0x75F0, 0x7ED0, 0x7F00, 0x7F00, 0x7F10, 0x7F50, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F30, 0x7ED0, + 0x7EB0, 0x7F00, 0x7F20, 0x7F40, 0x7EF0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7F00, + 0x7F30, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F40, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F80, 0x7F00, 0x7F40, 0x7F20, 0x7F10, 0x7F70, + 0x7EE0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F70, 0x6E00, 0x54F0, 0x3DE0, 0x26A0, 0x0EF0, 0xF730, 0xDD70, 0xC1D0, 0xA950, 0x9450, 0x8960, + 0x8670, 0x85E0, 0x85E0, 0x8640, 0x8710, 0x8840, 0x8A10, 0x8D30, 0x95F0, 0xA610, 0xBC40, 0xD9A0, 0xFAB0, 0x1A60, 0x3630, 0x4160, + 0x3D20, 0x2A50, 0x0CB0, 0xECC0, 0xCF00, 0xB840, 0xA9E0, 0xA1F0, 0x9EF0, 0x9CE0, 0x9850, 0x8510, 0x84E0, 0x84D0, 0x84C0, 0x84A0, + 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8490, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, + 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8470, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x83E0, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8460, 0x8440, 0x8440, 0x8440, 0x8400, 0x8430, 0x8430, 0x8430, 0x83D0, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8420, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8440, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8410, 0x8420, 0x83C0, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x8410, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8450, + 0x8460, 0x8470, 0x8490, 0x84A0, 0x84D0, 0x8530, 0x86C0, 0x9120, 0xA2F0, 0xB150, 0xBBF0, 0xC300, 0xC5B0, 0xC3A0, 0xBC00, 0xAFC0, + 0x9F00, 0x8C10, 0x8590, 0x84E0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8450, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8410, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8460, + 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x8540, 0x8720, 0x92D0, 0xA470, 0xB540, 0xC4C0, 0xD330, + 0xE170, 0xECF0, 0xF770, 0x0120, 0x0A20, 0x1340, 0x1AF0, 0x2140, 0x2690, 0x2B30, 0x2EA0, 0x3280, 0x35F0, 0x38D0, 0x3B70, 0x3C40, + 0x3C60, 0x3B90, 0x38A0, 0x33D0, 0x2DB0, 0x26B0, 0x2060, 0x1A50, 0x1650, 0x1430, 0x13E0, 0x1560, 0x1750, 0x1870, 0x19C0, 0x1A80, + 0x1B50, 0x1C60, 0x1F00, 0x2300, 0x27E0, 0x2E20, 0x3590, 0x3E30, 0x4710, 0x5050, 0x5970, 0x6270, 0x6B30, 0x7420, 0x7C40, 0x7F10, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F20, + 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7EF0, + 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, + 0x7EF0, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F40, 0x7F50, + 0x7EF0, 0x7EF0, 0x7EB0, 0x7F60, 0x7F40, 0x7E90, 0x7EC0, 0x7F00, 0x7F10, 0x7F30, 0x7EA0, 0x7EE0, 0x7F00, 0x7F10, 0x7F00, 0x7EA0, + 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, + 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7ED0, 0x7EF0, 0x7F00, 0x7F10, 0x7F60, 0x7F00, + 0x7ED0, 0x7F00, 0x7EF0, 0x7F50, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7E90, + 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F80, + 0x7F10, 0x7EF0, 0x7F30, 0x7F20, 0x7F80, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F00, 0x7F40, 0x7F40, + 0x7F10, 0x7F10, 0x7EE0, 0x7F60, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7ED0, + 0x7F10, 0x7EF0, 0x7F60, 0x7ED0, 0x7EB0, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7EE0, 0x7F40, 0x7EF0, 0x7E90, 0x7F10, + 0x7EF0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, 0x7F10, + 0x7F00, 0x7F10, 0x7F10, 0x7F80, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7830, 0x6D70, 0x6360, 0x5810, 0x4C50, 0x4120, 0x35C0, + 0x2B60, 0x2230, 0x18A0, 0x1150, 0x0990, 0x02D0, 0xFCC0, 0xF790, 0xF490, 0xF310, 0xF310, 0xF510, 0xF910, 0x26A0, 0x36F0, 0x4800, + 0x57E0, 0x67E0, 0x7580, 0x7ED0, 0x7F10, 0x7E70, 0x7EC0, 0x7ED0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, + 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, + 0x7EF0, 0x7F30, 0x7F20, 0x7EF0, 0x7F50, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, + 0x7F00, 0x7F00, 0x7F10, 0x7F50, 0x7EB0, 0x7EF0, 0x7F00, 0x7EE0, 0x7F50, 0x7BB0, 0x7230, 0x6780, 0x5B90, 0x4E90, 0x4100, 0x3320, + 0x2550, 0x16F0, 0x0730, 0xF800, 0xE890, 0xD920, 0xCA50, 0xB970, 0xA960, 0x9970, 0x8BF0, 0x8660, 0x8520, 0x84E0, 0x84D0, 0x84B0, + 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x83F0, 0x8440, 0x8430, 0x8440, + 0x8430, 0x8430, 0x8440, 0x8420, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x84A0, 0x8450, 0x8450, 0x8450, + 0x8460, 0x8450, 0x8450, 0x8480, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8460, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8470, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, + 0x8450, 0x8470, 0x8470, 0x8480, 0x84C0, 0x8490, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8460, 0x8460, 0x8450, 0x8440, 0x8420, 0x8420, + 0x8410, 0x8400, 0x8400, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x8390, + 0x8390, 0x8390, 0x8390, 0x83B0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83C0, 0x8390, + 0x8390, 0x8350, 0x83A0, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83D0, 0x83A0, 0x83D0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, + 0x83E0, 0x83A0, 0x83B0, 0x8360, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8410, 0x8420, 0x8430, 0x8440, 0x8450, 0x8470, 0x8480, 0x8490, 0x8490, + 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8480, 0x8470, + 0x8460, 0x8450, 0x8440, 0x8430, 0x8470, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, + 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8470, 0x8490, 0x8560, 0xB1A0, 0xF1A0, 0x29D0, 0x58D0, 0x7A70, + 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F40, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F90, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F40, 0x7EB0, 0x7EB0, + 0x7EF0, 0x7F30, 0x7EE0, 0x7E90, 0x7EB0, 0x7F10, 0x7F20, 0x7EF0, 0x7E90, 0x7EB0, 0x7F20, 0x7F40, 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F30, 0x7F00, 0x7F30, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EC0, 0x7F40, 0x7EF0, 0x7F20, + 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7F50, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F10, + 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F30, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7EC0, 0x7EF0, + 0x7F00, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7EF0, 0x7F20, + 0x7F20, 0x7F00, 0x7F40, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7F00, 0x7F00, 0x7F00, + 0x7F10, 0x7F50, 0x7EE0, 0x7E70, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F40, 0x7EF0, 0x7EC0, 0x7F10, 0x7F10, + 0x7F20, 0x7F20, 0x7E90, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, + 0x7F30, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, 0x7F10, 0x7F00, 0x7EE0, + 0x7ED0, 0x7F60, 0x7F00, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EF0, + 0x7F00, 0x7EE0, 0x7E90, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, + 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F20, 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, + 0x7F10, 0x7ED0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, 0x7F10, 0x7EB0, 0x7F20, 0x7EE0, 0x7EF0, + 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7F80, 0x7EF0, 0x7F20, 0x7F10, + 0x7F00, 0x7F90, 0x7F10, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F40, 0x7F10, 0x7E90, 0x7EB0, 0x7ED0, + 0x7F10, 0x7F00, 0x7E70, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, + 0x7F20, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F00, + 0x7EF0, 0x7F50, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7D10, 0x7190, 0x65B0, 0x5960, 0x4B80, 0x3A50, + 0x26B0, 0x1160, 0xFA80, 0xE550, 0xD510, 0xCCA0, 0xCE00, 0xD850, 0xE920, 0xFDD0, 0x12B0, 0x2690, 0x37A0, 0x4600, 0x54B0, 0x61A0, + 0x6F10, 0x7B00, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F20, 0x7EF0, + 0x7F10, 0x7F90, 0x6F70, 0x54E0, 0x3800, 0x1850, 0xF6B0, 0xD480, 0xB160, 0x8E50, 0x8530, 0x84C0, 0x84B0, 0x8490, 0x8490, 0x8490, + 0x84A0, 0x8490, 0x84C0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84B0, 0x8470, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83D0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x83D0, 0x8420, 0x8420, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, + 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x8500, 0x84E0, 0x8510, + 0x8510, 0x8520, 0x8550, 0x8550, 0x8530, 0x8540, 0x8530, 0x85A0, 0x8610, 0x8700, 0x88F0, 0x8D80, 0x94C0, 0x9D80, 0xA630, 0xAEF0, + 0xB880, 0xC250, 0xCC70, 0xD6F0, 0xE130, 0xEBE0, 0xF510, 0xFFA0, 0x07A0, 0x0F50, 0x1710, 0x2060, 0x2A80, 0x35C0, 0x40B0, 0x4AB0, + 0x5520, 0x5D70, 0x6520, 0x6BE0, 0x71C0, 0x7600, 0x79D0, 0x7CB0, 0x7E70, 0x7F10, 0x7EF0, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, + 0x7F40, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7E10, 0x7CD0, 0x7BC0, 0x7AF0, 0x7AA0, + 0x7AA0, 0x7B20, 0x7BF0, 0x7C90, 0x7CE0, 0x7D40, 0x7DD0, 0x7E20, 0x7E40, 0x7E90, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, + 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7EE0, 0x7E00, 0x7CD0, 0x7B30, 0x7970, 0x7840, 0x77B0, 0x77B0, 0x77D0, 0x7770, 0x7750, 0x7780, 0x7770, 0x77C0, 0x7850, + 0x7890, 0x7830, 0x77A0, 0x7730, 0x7720, 0x7750, 0x7890, 0x7A30, 0x7B20, 0x7BD0, 0x7BF0, 0x7C10, 0x7C60, 0x7CC0, 0x7D10, 0x7D70, + 0x7D60, 0x7D20, 0x7CF0, 0x7D10, 0x7D60, 0x7D30, 0x7CB0, 0x7B60, 0x7A20, 0x78C0, 0x7790, 0x76E0, 0x7620, 0x75E0, 0x75E0, 0x75E0, + 0x7610, 0x7650, 0x7610, 0x7560, 0x7490, 0x72D0, 0x7030, 0x6DD0, 0x6C30, 0x6A90, 0x68B0, 0x6640, 0x6310, 0x5F10, 0x5A20, 0x5500, + 0x4EE0, 0x49E0, 0x4430, 0x3DF0, 0x3680, 0x2EC0, 0x26C0, 0x1F30, 0x1890, 0x11C0, 0x0B10, 0x0580, 0x00A0, 0xFC70, 0xFA50, 0xF980, + 0xFA10, 0xFC20, 0x0050, 0x0510, 0x0A80, 0x1060, 0x16C0, 0x1CA0, 0x20B0, 0x2320, 0x2460, 0x2310, 0x2000, 0x1AE0, 0x12D0, 0x0930, + 0xFD30, 0xEFC0, 0xE1F0, 0xD490, 0xC7D0, 0xBC90, 0xB200, 0xA7F0, 0x9E80, 0x9540, 0x8D50, 0x8830, 0x85F0, 0x8520, 0x84E0, 0x84D0, + 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, + 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, + 0x83D0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83C0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x8400, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, + 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8460, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, + 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8510, 0x8550, 0x85B0, 0x8660, 0x87A0, 0x8970, 0x8BA0, 0x8E60, 0x9190, 0x9440, 0x9730, + 0x9A80, 0x9D50, 0xA0A0, 0xA430, 0xA7F0, 0xAC10, 0xB110, 0xB4B0, 0xB9D0, 0xBE00, 0xC1E0, 0xC680, 0xCAE0, 0xCFB0, 0xD460, 0xD8B0, + 0xDCC0, 0xE060, 0xE4F0, 0xEA50, 0xF060, 0xF670, 0xFCD0, 0x0410, 0x0B00, 0x1190, 0x1880, 0x1F80, 0x2760, 0x2ED0, 0x35B0, 0x3CB0, + 0x4170, 0x4690, 0x4B00, 0x4F60, 0x6430, 0x69F0, 0x6FE0, 0x7610, 0x7BF0, 0x7ED0, 0x7F70, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7F50, + 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, 0x7F00, 0x7F40, 0x7F10, 0x7E90, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, + 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, + 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F70, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F50, + 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F60, 0x7ED0, 0x7F10, 0x7F00, 0x7F00, 0x7F50, 0x7F00, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F50, 0x7F00, + 0x7EA0, 0x7ED0, 0x7ED0, 0x7F20, 0x7F00, 0x7E90, 0x7ED0, 0x7EE0, 0x7F00, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7E90, + 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7EE0, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F50, + 0x7EF0, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F00, 0x7F00, 0x7F00, 0x7F50, 0x7EB0, + 0x7E70, 0x7EE0, 0x7EF0, 0x7F40, 0x7ED0, 0x7E90, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7EA0, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, + 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, + 0x7F00, 0x7F20, 0x7F10, 0x7EF0, 0x7F70, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, + 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, + 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F70, + 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7F20, 0x7F70, 0x7EF0, + 0x7EB0, 0x7EF0, 0x7EE0, 0x7F50, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7E90, + 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F00, 0x7F20, 0x7DE0, 0x6980, 0x5530, + 0x4040, 0x2930, 0x15E0, 0x0370, 0xF150, 0xE030, 0xCEE0, 0xBDC0, 0xABC0, 0x9800, 0x88C0, 0x8540, 0x84E0, 0x84B0, 0x84D0, 0x8480, + 0x8470, 0x8460, 0x8450, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8440, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8470, 0x8450, 0x8490, 0x8470, 0x8480, 0x84B0, 0x84E0, 0x8610, 0x9C90, 0xBD70, 0xDEE0, 0xFFF0, + 0x2040, 0x3F30, 0x5B20, 0x72A0, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x6AB0, 0x4970, + 0x26C0, 0x0890, 0xED60, 0xD580, 0xC1C0, 0xB1A0, 0xA530, 0x9C30, 0x95C0, 0x92D0, 0x92B0, 0x9600, 0x9D60, 0xA840, 0xB590, 0xC5C0, + 0xD6E0, 0xE880, 0xFA10, 0x0800, 0x12F0, 0x1B80, 0x21B0, 0x25A0, 0x2890, 0x2930, 0x27B0, 0x23B0, 0x1C60, 0x1290, 0x06B0, 0xF9F0, + 0xEBF0, 0xDBE0, 0xCA30, 0xB610, 0x9D50, 0x89D0, 0x8520, 0x84C0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, + 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8430, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8460, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84D0, 0x8520, 0x86A0, 0x8FE0, 0xA240, 0xB2D0, 0xC2D0, + 0xD250, 0xE1D0, 0xEF90, 0xFC80, 0x07E0, 0x11F0, 0x19B0, 0x1FD0, 0x2480, 0x2740, 0x29B0, 0x2B60, 0x2D50, 0x2F10, 0x3150, 0x33A0, + 0x3680, 0x3990, 0x3C00, 0x3DF0, 0x3F90, 0x4030, 0x3FE0, 0x3EC0, 0x3AF0, 0x35D0, 0x2EC0, 0x26A0, 0x1B70, 0x0EC0, 0xFFE0, 0xEE70, + 0xDC10, 0xC840, 0xB430, 0x9F70, 0x8DC0, 0x8630, 0x8510, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, + 0x8510, 0x8580, 0x86B0, 0x8A70, 0x92F0, 0x9D70, 0xA750, 0xB010, 0xB8C0, 0xC140, 0xC840, 0xCDC0, 0xD290, 0xD700, 0xDAF0, 0xDF10, + 0xE250, 0xE4C0, 0xE720, 0xE890, 0xE9D0, 0xEA70, 0xEAC0, 0xEA80, 0xE9D0, 0xE950, 0xE8E0, 0xE790, 0xE5F0, 0xE3A0, 0xE180, 0xDF10, + 0xDCD0, 0xDB80, 0xD9E0, 0xD8F0, 0xD7A0, 0xD650, 0xD520, 0xD330, 0xD110, 0xCFC0, 0xCD90, 0xCBB0, 0xC9E0, 0xC860, 0xC710, 0xC610, + 0xC530, 0xC3A0, 0xC250, 0xC160, 0xBFF0, 0xBF10, 0xBE20, 0xBD40, 0xBCD0, 0xBC10, 0xBC00, 0xBB70, 0xBB30, 0xBBD0, 0xBC00, 0xBD90, + 0xBF00, 0xC030, 0xC280, 0xC490, 0xC730, 0xC9A0, 0xCD60, 0xD220, 0xD8C0, 0xDEE0, 0xE4B0, 0xEA90, 0xF0A0, 0xF680, 0xFDD0, 0x0590, + 0x0DE0, 0x16D0, 0x1F10, 0x2720, 0x2F00, 0x3640, 0x3E90, 0x4620, 0x4D00, 0x5390, 0x5A80, 0x6090, 0x6630, 0x6C20, 0x71C0, 0x7680, + 0x7AB0, 0x7DA0, 0x7F50, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, + 0x7EE0, 0x7F20, 0x7F10, 0x7E90, 0x7EE0, 0x7ED0, 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F00, 0x7F20, + 0x7F10, 0x7F10, 0x7EC0, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F20, + 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7ED0, 0x7F00, 0x7ED0, 0x7F10, 0x7F60, 0x7EE0, 0x7EC0, 0x7F10, + 0x7F20, 0x7F40, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7EA0, 0x7EF0, 0x7D10, 0x7750, 0x7320, 0x6E20, 0x6960, 0x6510, + 0x5FF0, 0x5B70, 0x5660, 0x51D0, 0x4D50, 0x49E0, 0x4190, 0x40F0, 0x41B0, 0x42C0, 0x4500, 0x4730, 0x4950, 0x4BC0, 0x4EA0, 0x5280, + 0x5650, 0x5A90, 0x5E30, 0x6100, 0x63C0, 0x6640, 0x6810, 0x6AC0, 0x6CE0, 0x6ED0, 0x70B0, 0x7120, 0x71F0, 0x7380, 0x74B0, 0x75B0, + 0x76A0, 0x7790, 0x7780, 0x7740, 0x7650, 0x7500, 0x7380, 0x7140, 0x6D90, 0x6910, 0x6230, 0x5AA0, 0x5110, 0x46B0, 0x3B00, 0x2CF0, + 0x1E50, 0x0E50, 0xFE60, 0xEE60, 0xDF10, 0xCEE0, 0xC090, 0xB210, 0xA450, 0x97A0, 0x8CC0, 0x8790, 0x85B0, 0x8520, 0x84F0, 0x84D0, + 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x84B0, 0x8490, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8490, 0x84A0, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, + 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8530, 0x85B0, 0x8690, 0x8880, 0x8DD0, 0x94F0, 0x9D30, 0xA4D0, 0xACB0, + 0xB470, 0xBA50, 0xC140, 0xC700, 0xCE10, 0xD550, 0xDC30, 0xE380, 0xE950, 0xEDD0, 0xF260, 0xF6E0, 0xFAC0, 0xFF80, 0x03C0, 0x0880, + 0x0B80, 0x0F30, 0x1320, 0x17E0, 0x1D30, 0x22B0, 0x2990, 0x3030, 0x3670, 0x3D00, 0x4440, 0x4C10, 0x53B0, 0x5AE0, 0x6240, 0x6850, + 0x6E90, 0x74B0, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F80, 0x7F00, 0x7F00, 0x7F10, + 0x7F10, 0x7F80, 0x7F00, 0x7ED0, 0x7EF0, 0x7F00, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F20, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, + 0x7EF0, 0x7F10, 0x7EA0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, + 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F10, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x6F60, 0x5750, + 0x3B50, 0x2290, 0x0A60, 0xF3C0, 0xDF20, 0xCBD0, 0xBCF0, 0xB120, 0xA8C0, 0xA240, 0x9E20, 0x9C10, 0x99F0, 0x9800, 0x9630, 0x9490, + 0x9370, 0x9240, 0x91E0, 0x92C0, 0x94F0, 0x98F0, 0x9E00, 0xA340, 0xA980, 0xAEA0, 0xB420, 0xBA10, 0xC0B0, 0xC830, 0xD060, 0xD980, + 0xE230, 0xEAB0, 0xF2C0, 0xFA70, 0x0300, 0x0A00, 0x10F0, 0x1880, 0x1FE0, 0x2800, 0x2F50, 0x3610, 0x3D60, 0x4440, 0x4A10, 0x4E90, + 0x51F0, 0x5700, 0x5A50, 0x5F70, 0x6420, 0x6840, 0x6DB0, 0x7260, 0x77A0, 0x7D50, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F40, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7350, 0x64B0, 0x5360, 0x4020, 0x29E0, + 0x13E0, 0xFC60, 0xE380, 0xC950, 0xAED0, 0x9550, 0x8780, 0x8550, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8500, + 0x8500, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x84E0, 0x84E0, 0x84E0, 0x84F0, + 0x84F0, 0x8510, 0x8530, 0x8570, 0x85F0, 0x8690, 0x8790, 0x88C0, 0x8AA0, 0x8CF0, 0x90E0, 0x9500, 0x98B0, 0x9B80, 0x9D70, 0x9E60, + 0x9E70, 0x9D10, 0x9C20, 0x9AF0, 0x9930, 0x97A0, 0x9680, 0x9710, 0x9A60, 0xA080, 0xA810, 0xB0F0, 0xBA00, 0xC360, 0xCCC0, 0xD490, + 0xDAD0, 0xDF80, 0xE0F0, 0xDE50, 0xD6B0, 0xCAD0, 0xBBE0, 0xA9F0, 0x99F0, 0x8CB0, 0x86D0, 0x8580, 0x84F0, 0x84D0, 0x84C0, 0x84B0, + 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x84B0, 0x8490, 0x84C0, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, + 0x8500, 0x8510, 0x8550, 0x85F0, 0x8850, 0x90E0, 0x9E20, 0xABF0, 0xB9F0, 0xC880, 0xD7D0, 0xE6C0, 0xF4D0, 0x02A0, 0x0DA0, 0x16F0, + 0x1F90, 0x27B0, 0x2EE0, 0x34F0, 0x3970, 0x3BB0, 0x3B40, 0x3890, 0x3360, 0x2D00, 0x25A0, 0x1D50, 0x1500, 0x0CD0, 0x0560, 0xFE30, + 0xF880, 0xF570, 0xF3F0, 0xF3A0, 0xF520, 0xF780, 0xFB80, 0x0140, 0x0870, 0x1080, 0x1930, 0x2300, 0x2D80, 0x3850, 0x44D0, 0x5190, + 0x5D70, 0x6A30, 0x74B0, 0x7D60, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7ED0, 0x7F10, 0x7F30, + 0x7EE0, 0x7E90, 0x7EF0, 0x7EF0, 0x7C50, 0x6A00, 0x50C0, 0x31D0, 0x0EF0, 0xEBB0, 0xCC50, 0xB220, 0x9D00, 0x8F80, 0x8880, 0x8600, + 0x8530, 0x84F0, 0x84F0, 0x84F0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84F0, 0x84D0, 0x84E0, 0x8500, 0x8530, 0x85C0, + 0x8720, 0x8AE0, 0x9370, 0x9D90, 0xA810, 0xB2C0, 0xBE80, 0xCBB0, 0xD8F0, 0xE730, 0xF630, 0x0580, 0x1410, 0x2250, 0x3030, 0x3E10, + 0x4F30, 0x5EE0, 0x6DF0, 0x7AD0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7F00, 0x7F40, 0x7F10, 0x7E90, 0x7E90, 0x7F00, 0x7EF0, 0x7F10, + 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7220, 0x5A40, 0x3A00, 0x1510, 0xEC80, + 0xC3F0, 0x9D90, 0x8740, 0x84F0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8490, 0x8460, 0x8460, 0x8410, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8480, 0x8460, 0x8480, 0x8440, + 0x8460, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84D0, + 0x84B0, 0x84D0, 0x84E0, 0x8510, 0x8550, 0x8600, 0x8810, 0x8E50, 0x9A10, 0xA590, 0xB260, 0xBDB0, 0xC830, 0xD160, 0xD9B0, 0xE1F0, + 0xEA30, 0xF160, 0xF870, 0xFF30, 0x0540, 0x0AD0, 0x0F10, 0x1330, 0x1760, 0x1B60, 0x1F90, 0x2290, 0x25B0, 0x2790, 0x2930, 0x2B70, + 0x2D00, 0x2ED0, 0x3020, 0x3120, 0x3250, 0x3300, 0x3360, 0x33A0, 0x3310, 0x33B0, 0x3370, 0x33C0, 0x3410, 0x34B0, 0x3630, 0x3710, + 0x37C0, 0x3800, 0x37B0, 0x37B0, 0x3800, 0x37C0, 0x36F0, 0x3690, 0x31C0, 0x2F60, 0x2E60, 0x2C80, 0x2B00, 0x29F0, 0x2970, 0x2B80, + 0x2EC0, 0x3430, 0x3A50, 0x4210, 0x4BB0, 0x5460, 0x5BE0, 0x6210, 0x6680, 0x6AA0, 0x6D20, 0x6F10, 0x70B0, 0x7230, 0x73A0, 0x7440, + 0x73C0, 0x7230, 0x6F00, 0x6AE0, 0x64D0, 0x5EF0, 0x5850, 0x5150, 0x4A70, 0x43C0, 0x3CD0, 0x3730, 0x31D0, 0x2EC0, 0x2CC0, 0x2A70, + 0x28B0, 0x2700, 0x2690, 0x26D0, 0x27A0, 0x2A80, 0x2E40, 0x3310, 0x3880, 0x3C80, 0x4130, 0x44B0, 0x4720, 0x48D0, 0x4850, 0x4550, + 0x3EE0, 0x3490, 0x27E0, 0x1920, 0x0980, 0xF910, 0xE960, 0xDB80, 0xCF30, 0xC5D0, 0xBDE0, 0xB7F0, 0xB470, 0xB280, 0xB300, 0xB3B0, + 0xB4B0, 0xB5E0, 0xB640, 0xB470, 0xB1B0, 0xAD10, 0xA830, 0xA1D0, 0x9B60, 0x9470, 0x8EA0, 0x8AA0, 0x8810, 0x86E0, 0x8640, 0x85F0, + 0x85B0, 0x8570, 0x8560, 0x8540, 0x8530, 0x8520, 0x8510, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84E0, 0x8530, 0x84E0, 0x84E0, 0x84F0, + 0x8500, 0x8510, 0x8540, 0x8590, 0x8630, 0x8770, 0x89E0, 0x90E0, 0x99C0, 0xA390, 0xAE00, 0xB8E0, 0xC420, 0xCF50, 0xDAF0, 0xE760, + 0xF470, 0x00C0, 0x0BD0, 0x1730, 0x20B0, 0x2970, 0x3180, 0x37B0, 0x3E20, 0x43C0, 0x48B0, 0x4E20, 0x51E0, 0x5650, 0x5A10, 0x5C70, + 0x5EA0, 0x5F80, 0x60C0, 0x60E0, 0x6090, 0x6030, 0x5E60, 0x5D40, 0x5B50, 0x59B0, 0x5920, 0x5940, 0x5B90, 0x5EB0, 0x6260, 0x66F0, + 0x69F0, 0x6B60, 0x6960, 0x63F0, 0x5B00, 0x4F50, 0x4150, 0x3270, 0x23C0, 0x1710, 0x0BB0, 0x01F0, 0xF8C0, 0xEEA0, 0xE510, 0xDB00, + 0xD020, 0xC480, 0xB8E0, 0xAD40, 0xA110, 0x9580, 0x8C60, 0x8810, 0x86A0, 0x85E0, 0x8590, 0x8580, 0x8590, 0x8580, 0x85A0, 0x85F0, + 0x8680, 0x87D0, 0x8A80, 0x9020, 0x9850, 0xA280, 0xAC20, 0xB650, 0xC180, 0xCB80, 0xD550, 0xDD90, 0xE570, 0xEC70, 0xF210, 0xF790, + 0xFBE0, 0x0020, 0x02C0, 0x04C0, 0x0750, 0x0980, 0x0B70, 0x0CA0, 0x0CB0, 0x0D00, 0x0CE0, 0x0B70, 0x0930, 0x05B0, 0x0120, 0xF9D0, + 0xEFD0, 0xBD00, 0xAFC0, 0xA3C0, 0x9AB0, 0x9310, 0x8D50, 0x8980, 0x8740, 0x85F0, 0x8550, 0x8510, 0x84E0, 0x84D0, 0x84C0, 0x84B0, + 0x84D0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8490, 0x8490, 0x8450, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x84A0, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84C0, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, + 0x8500, 0x8500, 0x8520, 0x8550, 0x85B0, 0x8640, 0x8750, 0x8950, 0x8D10, 0x92C0, 0x9920, 0x9DE0, 0xA1C0, 0xA5E0, 0xA9D0, 0xAC90, + 0xAFB0, 0xB2D0, 0xB5F0, 0xB8B0, 0xBAC0, 0xBCD0, 0xBDE0, 0xBF30, 0xBFD0, 0xBF80, 0xBEE0, 0xBE30, 0xBD50, 0xBC30, 0xBAA0, 0xB940, + 0xB760, 0xB5B0, 0xB440, 0xB3D0, 0xB270, 0xB1D0, 0xB1C0, 0xB1B0, 0xB0D0, 0xB020, 0xAFC0, 0xAED0, 0xAE80, 0xAEE0, 0xAF00, 0xAEE0, + 0xAE10, 0xAC80, 0xAA70, 0xA890, 0xA780, 0xA720, 0xA6F0, 0xA630, 0xA620, 0xA6C0, 0xA740, 0xA7A0, 0xA7F0, 0xA7E0, 0xA820, 0xA870, + 0xA9D0, 0xABA0, 0xADF0, 0xB030, 0xB200, 0xB330, 0xB440, 0xB540, 0xB6B0, 0xB940, 0xBBC0, 0xBE30, 0xBFF0, 0xC100, 0xC210, 0xC310, + 0xC3F0, 0xC580, 0xC760, 0xC940, 0xCAC0, 0xCBC0, 0xCCF0, 0xCE80, 0xD000, 0xD250, 0xD450, 0xD760, 0xD9D0, 0xDBF0, 0xDEB0, 0xE160, + 0xE460, 0xE6F0, 0xE990, 0xEC60, 0xEFD0, 0xF380, 0xF760, 0xFAE0, 0xFDD0, 0x0030, 0x01C0, 0x02F0, 0x04B0, 0x0730, 0x0900, 0x0AD0, + 0x0C10, 0x0C90, 0x0C00, 0x0B40, 0x0950, 0x0850, 0x0710, 0x0600, 0x0560, 0x0580, 0x05D0, 0x06A0, 0x0750, 0x08D0, 0x0B00, 0x0E20, + 0x1330, 0x1960, 0x2100, 0x2A10, 0x3410, 0x3EA0, 0x49E0, 0x54F0, 0x6090, 0x6BE0, 0x76F0, 0x7E90, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F60, 0x7F40, 0x7F70, 0x7F20, 0x7EE0, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7E80, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7E90, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7EE0, 0x79E0, 0x7040, 0x6430, 0x5700, 0x4820, 0x3900, 0x2B30, 0x1E40, 0x1240, 0x0890, + 0xFF30, 0xF660, 0xEDA0, 0xE450, 0xDCA0, 0xD4A0, 0xCC80, 0xC3C0, 0xBB80, 0xB2F0, 0xAA00, 0xA110, 0x9800, 0x8FC0, 0x8A80, 0x8780, + 0x8630, 0x85A0, 0x8550, 0x8530, 0x8510, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84F0, 0x84D0, 0x84D0, + 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x8460, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, + 0x84F0, 0x8500, 0x8510, 0x8510, 0x8520, 0x8530, 0x8530, 0x8540, 0x8550, 0x8550, 0x8580, 0x8590, 0x85B0, 0x85C0, 0x85E0, 0x85F0, + 0x85D0, 0x85B0, 0x85D0, 0x8590, 0x85B0, 0x8580, 0x8580, 0x8580, 0x8560, 0x8550, 0x8540, 0x8530, 0x8530, 0x8530, 0x8540, 0x8540, + 0x8550, 0x8580, 0x85C0, 0x8650, 0x8780, 0x8A70, 0x91D0, 0x9C50, 0xA6E0, 0xB220, 0xBD60, 0xC8F0, 0xD440, 0xDE60, 0xE690, 0xEDF0, + 0xF480, 0xF880, 0xFBF0, 0xFD80, 0xFD70, 0xF890, 0xF180, 0xE6E0, 0xDA50, 0xCC40, 0xBE60, 0xB150, 0xA5F0, 0x9C00, 0x9300, 0x8CC0, + 0x88D0, 0x86F0, 0x8600, 0x8580, 0x8540, 0x8520, 0x8500, 0x8500, 0x8500, 0x8530, 0x8500, 0x8500, 0x8500, 0x84E0, 0x8510, 0x8510, + 0x8530, 0x8530, 0x8550, 0x8570, 0x85A0, 0x85F0, 0x86A0, 0x8810, 0x8AE0, 0x8F50, 0xA150, 0xA4A0, 0xA7A0, 0xA9C0, 0xAA50, 0xA920, + 0xA4E0, 0x9F10, 0x9740, 0x8DC0, 0x87E0, 0x8580, 0x84F0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8460, 0x8470, 0x8470, 0x8480, 0x84A0, 0x8480, 0x8490, + 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x84D0, 0x84E0, 0x84E0, 0x8500, 0x84F0, + 0x84F0, 0x8500, 0x84B0, 0x8500, 0x8500, 0x8510, 0x8520, 0x8530, 0x8550, 0x8570, 0x8590, 0x85B0, 0x85E0, 0x8630, 0x86B0, 0x8790, + 0x8920, 0x8B10, 0x8DE0, 0x9280, 0x9820, 0x9F60, 0xA640, 0xAD80, 0xB6B0, 0xC020, 0xCA30, 0xD4D0, 0xDFB0, 0xEB90, 0xF780, 0x02B0, + 0x0CD0, 0x1470, 0x1B60, 0x2080, 0x23B0, 0x2520, 0x2440, 0x2380, 0x2200, 0x2180, 0x2110, 0x2030, 0x2020, 0x1E90, 0x1CC0, 0x1B90, + 0x1BC0, 0x1E80, 0x21F0, 0x2680, 0x2BA0, 0x30E0, 0x3610, 0x3BB0, 0x41A0, 0x4890, 0x4EC0, 0x54C0, 0x59C0, 0x5EB0, 0x6440, 0x69C0, + 0x6F90, 0x7530, 0x79F0, 0x7D90, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F00, 0x7ED0, 0x7ED0, 0x76C0, 0x6A40, 0x5BD0, + 0x4A00, 0x34E0, 0x1EE0, 0x06C0, 0xECA0, 0xD490, 0xBDF0, 0xA9C0, 0x9840, 0x8C50, 0x87B0, 0x8650, 0x85E0, 0x85B0, 0x85B0, 0x8590, + 0x8560, 0x8530, 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x8500, 0x84E0, 0x84F0, 0x8500, 0x8520, 0x8550, 0x85E0, 0x8780, 0x8CD0, + 0x97E0, 0xA3C0, 0xAFD0, 0xBB80, 0xC570, 0xCD30, 0xD1C0, 0xD2B0, 0xD140, 0xCC80, 0xC580, 0xBCF0, 0xB3C0, 0xA980, 0x9F90, 0x9540, + 0x8D30, 0x88B0, 0x86D0, 0x8600, 0x85B0, 0x8580, 0x8580, 0x85B0, 0x85F0, 0x8670, 0x8780, 0x8890, 0x89D0, 0x8AC0, 0x8BA0, 0x8CC0, + 0x8DC0, 0x8E60, 0x8DA0, 0x8C00, 0x8A40, 0x88A0, 0x8780, 0x8690, 0x8600, 0x8590, 0x8550, 0x8520, 0x8510, 0x8500, 0x84F0, 0x84F0, + 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x8500, 0x8500, 0x8520, 0x8530, 0x8550, 0x8590, 0x85F0, 0x8690, 0x87E0, 0x8A60, + 0x8F70, 0x9680, 0x9E70, 0xA5E0, 0xADC0, 0xB580, 0xBD10, 0xC540, 0xCCA0, 0xD3E0, 0xDB50, 0xE310, 0xEAA0, 0xF1A0, 0xF7F0, 0xFDA0, + 0x0320, 0x08A0, 0x0ED0, 0x1510, 0x1AE0, 0x1FE0, 0x2550, 0x29D0, 0x2DE0, 0x31D0, 0x35B0, 0x3A40, 0x3DE0, 0x40D0, 0x4370, 0x4520, + 0x47C0, 0x4A50, 0x4C60, 0x4ED0, 0x50D0, 0x52E0, 0x54A0, 0x5660, 0x5890, 0x5A10, 0x5CA0, 0x5E10, 0x5E80, 0x5F00, 0x5F10, 0x5FD0, + 0x60B0, 0x6200, 0x64D0, 0x6670, 0x67C0, 0x68C0, 0x69B0, 0x6AB0, 0x6C00, 0x6D40, 0x6F50, 0x71B0, 0x7440, 0x7690, 0x78A0, 0x7AC0, + 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7EE0, 0x7E40, 0x7CD0, 0x7A90, 0x7760, 0x73D0, 0x7050, 0x6D40, 0x6A20, + 0x66D0, 0x6260, 0x5E70, 0x5910, 0x5290, 0x4AE0, 0x42C0, 0x3860, 0x2FE0, 0x2910, 0x2250, 0x1C00, 0x16A0, 0x1110, 0x0C90, 0x0960, + 0x0840, 0x0860, 0x0A00, 0x0C40, 0x1020, 0x1550, 0x1C50, 0x2490, 0x2DE0, 0x3830, 0x4090, 0x4880, 0x4FF0, 0x5730, 0x5E90, 0x6660, + 0x6E00, 0x7450, 0x7A30, 0x7D60, 0x7E50, 0x7E30, 0x7B30, 0x7460, 0x6890, 0x5940, 0x45B0, 0x2ED0, 0x1890, 0x02C0, 0xECD0, 0xD7A0, + 0xC3E0, 0xB180, 0xA070, 0x92E0, 0x8A30, 0x8740, 0x8640, 0x8600, 0x8620, 0x8690, 0x88B0, 0x8DC0, 0x95B0, 0x9E60, 0xA470, 0xA9B0, + 0xAD90, 0xB040, 0xB280, 0xB380, 0xB270, 0xAF50, 0xA990, 0xA1B0, 0x97C0, 0x8DB0, 0x8800, 0x85D0, 0x8520, 0x84F0, 0x84D0, 0x84C0, + 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84D0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84F0, 0x84E0, + 0x8530, 0x8550, 0x85F0, 0x8800, 0x8E90, 0x9980, 0xA420, 0xAEA0, 0xB720, 0xBDD0, 0xC2D0, 0xC740, 0xCAB0, 0xCDF0, 0xD010, 0xD2A0, + 0xD430, 0xD4E0, 0xD560, 0xD590, 0xD610, 0xD5C0, 0xD480, 0xD370, 0xD2B0, 0xD2D0, 0xD2D0, 0xD220, 0xD140, 0xCFF0, 0xCDD0, 0xCB90, + 0xC970, 0xC890, 0xC6C0, 0xC5C0, 0xC400, 0xC230, 0xC0E0, 0xBF00, 0xBD40, 0xBAE0, 0xB8F0, 0xB6C0, 0xB4D0, 0xB300, 0xB140, 0xAF80, + 0xAE10, 0xAC80, 0xAB10, 0xA9E0, 0xA920, 0xA8F0, 0xAA00, 0xABA0, 0xAE00, 0xB000, 0xB390, 0xB750, 0xBD00, 0xC2C0, 0xC970, 0xD0B0, + 0xD890, 0xE0F0, 0xE990, 0xF270, 0xFD00, 0x06C0, 0x1230, 0x1DC0, 0x2890, 0x3470, 0x3F70, 0x4B40, 0x55F0, 0x6050, 0x69F0, 0x7240, + 0x77F0, 0x7D00, 0x7EC0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F00, 0x7EE0, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, + 0x7F10, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, + 0x7EF0, 0x7F80, 0x7F10, 0x7EF0, 0x7F30, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, + 0x7F70, 0x7F20, 0x7EC0, 0x7EE0, 0x7ED0, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7C80, 0x7250, 0x68B0, 0x5D60, 0x5280, 0x46D0, 0x3C20, + 0x33A0, 0x2A60, 0x21D0, 0x1900, 0x1120, 0x0B20, 0x0650, 0x0440, 0x0480, 0x06D0, 0x0C70, 0x1320, 0x1B00, 0x21D0, 0x27A0, 0x2B70, + 0x2D30, 0x2E30, 0x2DE0, 0x2B80, 0x2850, 0x22D0, 0x1C70, 0x1590, 0x0F50, 0x0B20, 0x0A60, 0x0B90, 0x0E00, 0x10A0, 0x12E0, 0x1310, + 0x1170, 0x0E60, 0x09B0, 0x04E0, 0xFFC0, 0xFA90, 0xF6B0, 0xF360, 0xF140, 0xEFD0, 0xEF90, 0xF120, 0xF160, 0xF1D0, 0xF0D0, 0xEEE0, + 0xED70, 0xEB30, 0xE9B0, 0xE800, 0xE6F0, 0xE820, 0xE980, 0xEC40, 0xEFF0, 0xF350, 0xF800, 0xFC00, 0x00D0, 0x1EC0, 0x2810, 0x3080, + 0x3860, 0x40C0, 0x4900, 0x50E0, 0x5710, 0x5AB0, 0x5E80, 0x60E0, 0x62F0, 0x64D0, 0x6770, 0x6AD0, 0x6DD0, 0x7030, 0x7340, 0x75E0, + 0x7980, 0x7CB0, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F30, 0x7EF0, 0x7ED0, 0x7EE0, + 0x7F00, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7F20, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7EE0, + 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7EA0, 0x7BE0, 0x7790, 0x72D0, 0x6D00, 0x66E0, 0x6050, 0x5990, + 0x5310, 0x4C60, 0x4680, 0x4080, 0x3AA0, 0x34C0, 0x2F10, 0x2A70, 0x2730, 0x24A0, 0x2370, 0x2300, 0x22F0, 0x2400, 0x2550, 0x2700, + 0x2960, 0x2B90, 0x2F10, 0x3260, 0x3640, 0x3910, 0x3A90, 0x3C00, 0x3B80, 0x3AF0, 0x39B0, 0x37A0, 0x3630, 0x3400, 0x3140, 0x2E10, + 0x29F0, 0x2680, 0x2240, 0x1EE0, 0x1B80, 0x1890, 0x1710, 0x15A0, 0x15C0, 0x16D0, 0x1880, 0x1BF0, 0x2020, 0x25D0, 0x2D10, 0x33B0, + 0x3BC0, 0x42F0, 0x4B30, 0x5280, 0x5940, 0x5FD0, 0x6550, 0x6AC0, 0x6E10, 0x6FB0, 0x70F0, 0x7040, 0x6D90, 0x69B0, 0x6520, 0x6000, + 0x5890, 0x4FF0, 0x4740, 0x3DC0, 0x33D0, 0x28F0, 0x1DA0, 0x12E0, 0x0730, 0xFB00, 0xEF50, 0xE3D0, 0xD980, 0xCE50, 0xC490, 0xBB10, + 0xB2A0, 0xAB00, 0xA320, 0x9D70, 0x98B0, 0x9580, 0x9410, 0x9480, 0x9670, 0x9830, 0x9A50, 0x9BF0, 0x9DF0, 0xA000, 0xA2F0, 0xA620, + 0xA9A0, 0xAC90, 0xAF80, 0xB1A0, 0xB3E0, 0xB690, 0xB830, 0xB920, 0xBA10, 0xBA90, 0xBB60, 0xBC10, 0xBCA0, 0xBE70, 0xBFB0, 0xC0D0, + 0xC230, 0xC310, 0xC480, 0xC590, 0xC790, 0xC9E0, 0xCC30, 0xCE60, 0xCFC0, 0xD0E0, 0xD220, 0xD330, 0xD3C0, 0xD460, 0xD4F0, 0xD4E0, + 0xD4B0, 0xD4D0, 0xD450, 0xD480, 0xD440, 0xD3B0, 0xD3D0, 0xD460, 0xD480, 0xD510, 0xD580, 0xD680, 0xD6B0, 0xD690, 0xD560, 0xD420, + 0xD3D0, 0xD3C0, 0xD470, 0xD470, 0xD4C0, 0xD530, 0xD580, 0xD550, 0xD5D0, 0xD680, 0xD710, 0xD6F0, 0xD630, 0xD640, 0xD5D0, 0xD630, + 0xD6F0, 0xD700, 0xD740, 0xD700, 0xD750, 0xD710, 0xD7E0, 0xD960, 0xDA80, 0xDB20, 0xDB70, 0xDB00, 0xDB80, 0xDBE0, 0xDCA0, 0xDD40, + 0xDDF0, 0xDEF0, 0xDEA0, 0xDE70, 0xDDE0, 0xDDB0, 0xDDD0, 0xDD60, 0xDD40, 0xDCD0, 0xDC20, 0xDC90, 0xDCD0, 0xDCD0, 0xDCC0, 0xDD30, + 0xDDB0, 0xDE30, 0xE020, 0xE350, 0xE6D0, 0xEB00, 0xEE60, 0xF170, 0xF3A0, 0xF670, 0xFA90, 0xFF10, 0x03F0, 0x0940, 0x0D90, 0x11F0, + 0x13A0, 0x1540, 0x1610, 0x16A0, 0x1680, 0x16B0, 0x1670, 0x1560, 0x13C0, 0x11F0, 0x0F60, 0x0CC0, 0x0900, 0x0550, 0x0160, 0xFE40, + 0xFA90, 0xF720, 0xF2E0, 0xEE00, 0xE8D0, 0xE310, 0xDDA0, 0xD890, 0xD340, 0xCE20, 0xC960, 0xC460, 0xBEF0, 0xB9E0, 0xB5A0, 0xB1E0, + 0xAE90, 0xAB70, 0xA860, 0xA5B0, 0xA450, 0xA3F0, 0xA3A0, 0xA4A0, 0xA5B0, 0xA770, 0xA940, 0xAB40, 0xADB0, 0xB080, 0xB470, 0xB8F0, + 0xBE00, 0xC320, 0xC840, 0xCD90, 0xD410, 0xDA30, 0xDFB0, 0xE580, 0xEAD0, 0xF010, 0xF4C0, 0xF960, 0xFF40, 0x04D0, 0x0950, 0x0CE0, + 0x1050, 0x12F0, 0x1530, 0x17A0, 0x1AC0, 0x1DD0, 0x20B0, 0x2310, 0x24C0, 0x2650, 0x2770, 0x2820, 0x2810, 0x2780, 0x26B0, 0x2500, + 0x22F0, 0x20F0, 0x1EA0, 0x1AE0, 0x1710, 0x1280, 0x0E50, 0x0A00, 0x05B0, 0x01E0, 0xFEE0, 0xFC70, 0xFB30, 0xFA10, 0xF9A0, 0xFA70, + 0xFBD0, 0xFD90, 0x0060, 0x03A0, 0x0730, 0x0B30, 0x0F00, 0x12C0, 0x15D0, 0x17F0, 0x19E0, 0x1BE0, 0x1E40, 0x20F0, 0x23B0, 0x2760, + 0x2AE0, 0x2D80, 0x2FB0, 0x31D0, 0x3490, 0x3790, 0x3B60, 0x3EB0, 0x4240, 0x4540, 0x4890, 0x4D20, 0x52A0, 0x5A50, 0x6290, 0x6B30, + 0x7440, 0x7C10, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7EE0, 0x7100, 0x6210, 0x5390, 0x4560, + 0x3910, 0x2D70, 0x2000, 0x11A0, 0x0050, 0xED50, 0xD8B0, 0xC460, 0xAFD0, 0xA070, 0x9500, 0x8EC0, 0x8C30, 0x8C60, 0x9060, 0x9A40, + 0xA690, 0xB780, 0xC7C0, 0xD760, 0xE5F0, 0xF1C0, 0xFC40, 0x0380, 0x0890, 0x0BF0, 0x0E80, 0x1010, 0x1160, 0x12E0, 0x1580, 0x17A0, + 0x1A30, 0x1CC0, 0x1F90, 0x2300, 0x2660, 0x2AC0, 0x2FC0, 0x3610, 0x3CF0, 0x4360, 0x4A80, 0x5180, 0x5830, 0x5DE0, 0x61D0, 0x6590, + 0x6800, 0x69A0, 0x6AF0, 0x6BB0, 0x6BB0, 0x6A50, 0x6860, 0x6400, 0x5DC0, 0x5650, 0x4CC0, 0x43A0, 0x3B00, 0x3230, 0x2960, 0x2060, + 0x1680, 0x0D10, 0x0310, 0xFA40, 0xF1F0, 0xE9D0, 0xE330, 0xDD60, 0xDA50, 0xD920, 0xD9C0, 0xDC40, 0xDEF0, 0xE2B0, 0xE530, 0xE7C0, + 0xEAB0, 0xED60, 0xF050, 0xF2F0, 0xF550, 0xF7A0, 0xFA40, 0xFCD0, 0x0070, 0x0540, 0x0B10, 0x10D0, 0x1700, 0x1DC0, 0x2550, 0x2E50, + 0x3820, 0x4300, 0x4E60, 0x5840, 0x6290, 0x6C30, 0x7600, 0x7D40, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F00, + 0x7F50, 0x7F10, 0x7F00, 0x7EF0, 0x7EB0, 0x73E0, 0x6660, 0x56F0, 0x47B0, 0x37F0, 0x2940, 0x1C50, 0x1070, 0x0570, 0xFC50, 0xF480, + 0xEE10, 0xE920, 0xE570, 0xE2B0, 0xE1B0, 0xE1A0, 0xE210, 0xE2F0, 0xE460, 0xE5D0, 0xE790, 0xE950, 0xEB60, 0xECA0, 0xECA0, 0xECA0, + 0xEBD0, 0xEAD0, 0xE9A0, 0xE7F0, 0xE6D0, 0xE520, 0xE360, 0xE0F0, 0xDE80, 0xDBF0, 0xD9A0, 0xD710, 0xD500, 0xD3A0, 0xD360, 0xD390, + 0xD510, 0xD870, 0xDB90, 0xE090, 0xE5C0, 0xEB10, 0xF050, 0xF5A0, 0xFB90, 0x00E0, 0x0670, 0x0B30, 0x0F00, 0x1280, 0x1590, 0x1830, + 0x1A40, 0x1AF0, 0x1BD0, 0x1B50, 0x19D0, 0x1830, 0x1600, 0x1480, 0x1290, 0x11B0, 0x1160, 0x1220, 0x1450, 0x17B0, 0x1C00, 0x2210, + 0x28B0, 0x30B0, 0x3920, 0x4220, 0x4C90, 0x5800, 0x6280, 0x6C90, 0x74B0, 0x7BB0, 0x7EC0, 0x7F40, 0x7F30, 0x7F20, 0x7F10, 0x7F00, + 0x7F40, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7D80, 0x78E0, 0x74F0, 0x7080, 0x6C90, 0x67F0, 0x6380, 0x5FD0, 0x5B90, 0x56F0, + 0x5290, 0x4DF0, 0x49E0, 0x44D0, 0x3FF0, 0x3AA0, 0x3570, 0x30D0, 0x2CD0, 0x28F0, 0x2610, 0x22D0, 0x2000, 0x1C30, 0x1820, 0x0EC0, + 0x0D80, 0x0D10, 0x0C90, 0x0CB0, 0x0CE0, 0x0CD0, 0x0D10, 0x0D30, 0x0DB0, 0x0E00, 0x0EA0, 0x1000, 0x1060, 0x11C0, 0x11E0, 0x1090, + 0x0FB0, 0x0E00, 0x0C20, 0x0AD0, 0x0890, 0x05E0, 0x0300, 0xFFF0, 0xFBB0, 0xF660, 0xF1D0, 0xEC80, 0xE750, 0xE1E0, 0xDC90, 0xD6F0, + 0xD0E0, 0xCA70, 0xC330, 0xBC30, 0xB5E0, 0xAF90, 0xAA60, 0xA5D0, 0xA1E0, 0x9F30, 0x9CA0, 0x9B20, 0x9AA0, 0x9B50, 0x9D00, 0x9F30, + 0xA2F0, 0xA6C0, 0xAAC0, 0xAF10, 0xB4B0, 0xBA20, 0xC0D0, 0xC730, 0xCE20, 0xD430, 0xD930, 0xDF90, 0xE490, 0xEB00, 0xF090, 0xF570, + 0xFAE0, 0xFF90, 0x0480, 0x0990, 0x0EA0, 0x1400, 0x1900, 0x1D80, 0x2210, 0x2650, 0x2BD0, 0x3170, 0x37A0, 0x3D50, 0x4310, 0x49C0, + 0x50E0, 0x57D0, 0x5EF0, 0x6630, 0x6DE0, 0x74D0, 0x7B70, 0x7EE0, 0x7F30, 0x7F00, 0x7F00, 0x7F90, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, + 0x7F30, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7910, 0x6860, 0x54D0, 0x4210, 0x2F60, 0x1E00, 0x0D50, 0xFE30, + 0xF0B0, 0xE520, 0xDAB0, 0xD170, 0xCAC0, 0xC690, 0xC380, 0xC1F0, 0xC2A0, 0xC4F0, 0xC980, 0xCF70, 0xD810, 0xE1F0, 0xED70, 0xFAB0, + 0x07D0, 0x1530, 0x2230, 0x2DF0, 0x38F0, 0x41F0, 0x4840, 0x4D10, 0x5040, 0x52A0, 0x54D0, 0x5770, 0x59A0, 0x5AC0, 0x5A90, 0x56F0, + 0x4FF0, 0x4740, 0x3BB0, 0x3030, 0x2400, 0x1770, 0x0C50, 0x00A0, 0xF7C0, 0xEF40, 0xE750, 0xE070, 0xD900, 0xD140, 0xC980, 0xC1C0, + 0xB9E0, 0xB200, 0xAA90, 0xA370, 0x9BF0, 0x9530, 0x8EE0, 0x8A80, 0x87E0, 0x8650, 0x85E0, 0x8550, 0x8550, 0x8500, 0x84F0, 0x84F0, + 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84E0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84D0, 0x84F0, 0x8500, + 0x8510, 0x8530, 0x8540, 0x8580, 0x85E0, 0x8660, 0x8770, 0x8970, 0x8D10, 0x92C0, 0x9890, 0x9E80, 0xA4A0, 0xAB40, 0xB100, 0xB710, + 0xBD80, 0xC410, 0xCAA0, 0xD150, 0xD850, 0xDF50, 0xE5D0, 0xEB70, 0xF0B0, 0xF4E0, 0xF980, 0xFDE0, 0x02B0, 0x06E0, 0x0A40, 0x0E60, + 0x10A0, 0x1280, 0x1490, 0x1610, 0x1930, 0x1BA0, 0x1CD0, 0x1E50, 0x1EF0, 0x2090, 0x22B0, 0x2560, 0x2840, 0x2BB0, 0x2EF0, 0x3220, + 0x35F0, 0x3A70, 0x3F70, 0x4590, 0x4C50, 0x53B0, 0x5C20, 0x6410, 0x6CB0, 0x74F0, 0x7C70, 0x7F10, 0x7EA0, 0x7EC0, 0x7E80, 0x7F10, + 0x7F20, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7E30, 0x7150, 0x6500, + 0x5800, 0x4A90, 0x3CF0, 0x2EA0, 0x2190, 0x1370, 0x07A0, 0xFB10, 0xF250, 0xEB00, 0xE4D0, 0xDFB0, 0xDB50, 0xD6B0, 0xD220, 0xCC80, + 0xC5D0, 0xBFC0, 0xB990, 0xB390, 0xAD40, 0xA7C0, 0xA300, 0x9EC0, 0x9C60, 0x9AB0, 0x9B10, 0x9C60, 0x9DC0, 0x9F00, 0x9F30, 0x9F80, + 0x9FB0, 0x9F10, 0x9DD0, 0x9B60, 0x98F0, 0x9520, 0x9040, 0x8C20, 0x8910, 0x8720, 0x8630, 0x85A0, 0x8550, 0x8530, 0x8510, 0x8500, + 0x84F0, 0x8500, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, + 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8500, 0x8510, 0x8510, 0x8520, 0x8530, 0x8550, 0x8560, 0x8580, 0x85B0, 0x8610, + 0x86A0, 0x8790, 0x88D0, 0x8AC0, 0x8C30, 0x8D20, 0x8D40, 0x8C70, 0x8B30, 0x8980, 0x8810, 0x86E0, 0x8600, 0x8580, 0x8540, 0x8510, + 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84A0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8520, 0x8530, 0x8540, + 0x8550, 0x8570, 0x8590, 0x85B0, 0x85D0, 0x85E0, 0x85E0, 0x85E0, 0x85E0, 0x8600, 0x85E0, 0x85D0, 0x85C0, 0x85B0, 0x8590, 0x8570, + 0x8560, 0x8550, 0x8540, 0x8530, 0x8530, 0x8530, 0x8520, 0x8550, 0x8520, 0x8520, 0x8520, 0x8510, 0x8510, 0x8510, 0x8510, 0x8510, + 0x8520, 0x8520, 0x8520, 0x8530, 0x8530, 0x8550, 0x8560, 0x8580, 0x85B0, 0x85F0, 0x8640, 0x86C0, 0x8780, 0x88F0, 0x9320, 0x96C0, + 0x9A90, 0x9EB0, 0xA3C0, 0xA970, 0xAF20, 0xB4B0, 0xBA70, 0xBFB0, 0xC480, 0xC940, 0xCEC0, 0xD390, 0xD910, 0xDDE0, 0xE310, 0xE8F0, + 0xEE30, 0xF300, 0xF680, 0xF990, 0xFC50, 0xFF30, 0x0270, 0x0580, 0x08E0, 0x0BB0, 0x0EB0, 0x11F0, 0x13E0, 0x15F0, 0x1950, 0x1C30, + 0x1F30, 0x2190, 0x2490, 0x27F0, 0x2AE0, 0x2DD0, 0x3210, 0x3530, 0x3970, 0x3C50, 0x3FB0, 0x41F0, 0x4370, 0x4690, 0x4870, 0x4B70, + 0x4E00, 0x4FD0, 0x5280, 0x5410, 0x5610, 0x5780, 0x57C0, 0x5860, 0x5840, 0x5830, 0x58C0, 0x5890, 0x5860, 0x5780, 0x5660, 0x5550, + 0x53B0, 0x52C0, 0x51E0, 0x5140, 0x5130, 0x5090, 0x50E0, 0x5160, 0x51C0, 0x53D0, 0x56B0, 0x5B20, 0x5FC0, 0x6490, 0x6A30, 0x6FA0, + 0x75E0, 0x7B10, 0x7EF0, 0x7F00, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F60, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F10, 0x7E70, 0x7EC0, + 0x7ED0, 0x7F10, 0x7EE0, 0x7E90, 0x7F00, 0x7EA0, 0x75C0, 0x6D90, 0x64C0, 0x5C00, 0x5410, 0x4C50, 0x45E0, 0x4040, 0x3C80, 0x3AD0, + 0x3B90, 0x3EC0, 0x4380, 0x4840, 0x4C90, 0x5110, 0x5620, 0x59E0, 0x5C80, 0x5DB0, 0x5D20, 0x5BA0, 0x5840, 0x5330, 0x4C20, 0x44E0, + 0x3DF0, 0x37B0, 0x3320, 0x3240, 0x3510, 0x3C30, 0x4640, 0x5240, 0x5FB0, 0x6C20, 0x77C0, 0x7E80, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, + 0x7F00, 0x7F20, 0x7EE0, 0x7E90, 0x7E30, 0x7B20, 0x7990, 0x7AE0, 0x7D60, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7ED0, 0x7F50, 0x7F00, + 0x7F00, 0x7F10, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F00, + 0x7D50, 0x7400, 0x6860, 0x5AC0, 0x4C50, 0x4170, 0x39C0, 0x3670, 0x3690, 0x3820, 0x3A50, 0x3A70, 0x3760, 0x31C0, 0x2850, 0x1D90, + 0x1070, 0x0240, 0xF5D0, 0xE9C0, 0xE1D0, 0xDC90, 0xDAA0, 0xDBE0, 0xDE90, 0xE2F0, 0xE8A0, 0xEEA0, 0xF610, 0xFD10, 0x0460, 0x0A20, + 0x0E40, 0x01E0, 0xF810, 0xEB50, 0xDA00, 0xC400, 0xA930, 0x8C50, 0x8500, 0x84A0, 0x8480, 0x8460, 0x8450, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, 0x8460, 0x8470, 0x8450, + 0x8440, 0x8430, 0x8440, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, + 0x8470, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8450, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, + 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8530, 0x8550, 0x8580, 0x85B0, 0x85F0, 0x8630, 0x86C0, + 0x87B0, 0x8910, 0x8B50, 0x8DF0, 0x9090, 0x9290, 0x9580, 0x9870, 0x9B50, 0x9F70, 0xA2D0, 0xA650, 0xA9E0, 0xAC90, 0xB090, 0xB430, + 0xB860, 0xBC80, 0xBFA0, 0xC260, 0xC490, 0xC630, 0xC900, 0xCBC0, 0xCFD0, 0xD260, 0xD480, 0xD620, 0xD7C0, 0xDA20, 0xDBE0, 0xDDD0, + 0xDFF0, 0xE130, 0xE360, 0xE590, 0xE850, 0xEB60, 0xEE10, 0xF0A0, 0xF200, 0xF2F0, 0xF330, 0xF3A0, 0xF500, 0xF690, 0xF7F0, 0xF940, + 0xF9A0, 0xFA10, 0xFAA0, 0xFA70, 0xFA40, 0xFAB0, 0xFB90, 0xFB20, 0xFA70, 0xFB10, 0xFBC0, 0xFCE0, 0xFE90, 0xFF90, 0x00C0, 0x00C0, + 0x00B0, 0x00A0, 0x0060, 0x00F0, 0x00C0, 0x00D0, 0x0160, 0x0040, 0x0010, 0xFF80, 0xFE30, 0xFCD0, 0xFAA0, 0xF8A0, 0xF610, 0xF350, + 0xF0E0, 0xEED0, 0xED70, 0xEB80, 0xE9E0, 0xE850, 0xE710, 0xE550, 0xE350, 0xE0C0, 0xDF80, 0xDCE0, 0xDB40, 0xD980, 0xD860, 0xD7E0, + 0xD690, 0xD550, 0xD380, 0xD120, 0xCF40, 0xCDB0, 0xCC60, 0xCA90, 0xC8B0, 0xC6B0, 0xC420, 0xC280, 0xC0E0, 0xBEE0, 0xBE10, 0xBCC0, + 0xBB90, 0xB9B0, 0xB870, 0xB710, 0xB5B0, 0xB560, 0xB5A0, 0xB610, 0xB6C0, 0xB7D0, 0xB8F0, 0xBB00, 0xBDC0, 0xC1B0, 0xC580, 0xC9D0, + 0xCE80, 0xD310, 0xD890, 0xDDA0, 0xE270, 0xE850, 0xEE40, 0xF4A0, 0xFAF0, 0x00A0, 0x05C0, 0x0AB0, 0x0FD0, 0x14C0, 0x1960, 0x1D50, + 0x2170, 0x2570, 0x2890, 0x2B90, 0x2E40, 0x3060, 0x32D0, 0x3470, 0x35B0, 0x3860, 0x39B0, 0x3BA0, 0x3C80, 0x3C50, 0x3D10, 0x3C70, + 0x3C60, 0x3C80, 0x3BB0, 0x3C60, 0x3D00, 0x3DC0, 0x3DC0, 0x3CD0, 0x3C70, 0x3C00, 0x3C60, 0x3DD0, 0x4080, 0x4520, 0x4980, 0x5010, + 0x57E0, 0x5FA0, 0x6880, 0x7110, 0x7990, 0x7E70, 0x7F10, 0x7F30, 0x7F00, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F90, 0x7F10, + 0x7F20, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EB0, 0x7C90, 0x7A60, 0x7980, 0x7990, 0x7B00, 0x7D20, 0x7ED0, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7EF0, 0x7F50, 0x7730, 0x67E0, 0x5840, 0x4850, 0x3840, 0x2860, 0x1A90, 0x0DB0, 0x03A0, 0xFB90, 0xF610, 0xF2A0, + 0xF010, 0xEE00, 0xEC50, 0xEAD0, 0xE950, 0xE840, 0xE6F0, 0xE620, 0xE540, 0xE4D0, 0xE400, 0xE450, 0xE520, 0xE650, 0xE7B0, 0xE830, + 0xE920, 0xEA00, 0xEA90, 0xEB50, 0xECE0, 0xEF10, 0xF0C0, 0xF220, 0xF3A0, 0xF4E0, 0xF680, 0xF7E0, 0xF9D0, 0xFBD0, 0xFD00, 0xFE80, + 0x0000, 0x01F0, 0x03E0, 0x0590, 0x0690, 0x07E0, 0x08B0, 0x09A0, 0x0B10, 0x0C70, 0x0DD0, 0x0F60, 0x1050, 0x1110, 0x11C0, 0x1200, + 0x12B0, 0x12B0, 0x1340, 0x1370, 0x1390, 0x12C0, 0x11C0, 0x1110, 0x1020, 0x0F20, 0x0E20, 0x0C90, 0x0B00, 0x08C0, 0x07C0, 0x0720, + 0x06E0, 0x05C0, 0x04C0, 0x0320, 0x01B0, 0x0050, 0xFF80, 0xFF00, 0xFEB0, 0xFE50, 0xFD60, 0xFD00, 0xFC40, 0xFC40, 0xFBB0, 0xFB20, + 0xFA40, 0xF950, 0xF830, 0xF740, 0xF660, 0xF600, 0xF5D0, 0xF5C0, 0xF510, 0xF430, 0xF390, 0xF360, 0xF2C0, 0xF1C0, 0xF0D0, 0xEFE0, + 0xEEF0, 0xEE90, 0xEE90, 0xEE40, 0xEDA0, 0xED50, 0xEC30, 0xEAC0, 0xE900, 0xE5B0, 0xE2E0, 0xDFF0, 0xDCB0, 0xD880, 0xD4C0, 0xD1B0, + 0xCDF0, 0xCB10, 0xC760, 0xC420, 0xC0F0, 0xBD30, 0xBA70, 0xB740, 0xB5C0, 0xB340, 0xB160, 0xB030, 0xAF50, 0xAE30, 0xAD10, 0xABF0, + 0xAB10, 0xAA90, 0xA960, 0xA850, 0xA6E0, 0xA6C0, 0xA620, 0xA540, 0xA4B0, 0xA460, 0xA450, 0xA4D0, 0xA530, 0xA620, 0xA670, 0xA690, + 0xA6A0, 0xA740, 0xA7B0, 0xA7D0, 0xA8A0, 0xA920, 0xAA20, 0xAB70, 0xACE0, 0xAE30, 0xAF70, 0xB0C0, 0xB1B0, 0xB2D0, 0xB4C0, 0xB5A0, + 0xB690, 0xB880, 0xBA40, 0xBC70, 0xBE50, 0xBFB0, 0xC1F0, 0xC380, 0xC4E0, 0xC690, 0xC7E0, 0xC980, 0xCB20, 0xD360, 0xD530, 0xD610, + 0xD7E0, 0xD910, 0xDB10, 0xDC30, 0xDC60, 0xDD30, 0xDD90, 0xDE40, 0xDEF0, 0xDFB0, 0xE080, 0xE160, 0xE260, 0xE2C0, 0xE350, 0xE4A0, + 0xE560, 0xE670, 0xE750, 0xE7A0, 0xE8D0, 0xEA30, 0xEBC0, 0xED60, 0xEF50, 0xF170, 0xF320, 0xF440, 0xF5D0, 0xF760, 0xF9C0, 0xFC60, + 0xFF10, 0x0180, 0x0360, 0x0590, 0x06D0, 0x08C0, 0x0B10, 0x0D30, 0x0FE0, 0x11D0, 0x12D0, 0x1560, 0x16A0, 0x1840, 0x1A30, 0x1BB0, + 0x1D80, 0x1E80, 0x1FD0, 0x20E0, 0x2220, 0x2450, 0x2580, 0x26A0, 0x2740, 0x27B0, 0x28B0, 0x2940, 0x2A90, 0x2BB0, 0x2BE0, 0x2CA0, + 0x2D10, 0x2E70, 0x2FE0, 0x3160, 0x3370, 0x3470, 0x35C0, 0x3610, 0x36F0, 0x37C0, 0x3A40, 0x3C90, 0x3F50, 0x41A0, 0x4510, 0x4830, + 0x4AA0, 0x4D00, 0x4F40, 0x5180, 0x5350, 0x5630, 0x5870, 0x5B60, 0x5EC0, 0x6200, 0x6430, 0x66C0, 0x6850, 0x6A10, 0x6B40, 0x6C60, + 0x6E50, 0x6FB0, 0x71E0, 0x7360, 0x74B0, 0x7640, 0x76E0, 0x7810, 0x7980, 0x79E0, 0x79E0, 0x7940, 0x7930, 0x7940, 0x7990, 0x7A70, + 0x7A60, 0x7AA0, 0x7A40, 0x7930, 0x7900, 0x7840, 0x7830, 0x77E0, 0x7700, 0x7680, 0x7590, 0x7470, 0x7400, 0x7340, 0x7330, 0x7280, + 0x71A0, 0x7040, 0x6EC0, 0x6EA0, 0x6EC0, 0x6F90, 0x7060, 0x7100, 0x7240, 0x7310, 0x74B0, 0x7560, 0x75E0, 0x76D0, 0x7880, 0x7AC0, + 0x7C60, 0x7D90, 0x7E30, 0x7E60, 0x7EC0, 0x7ED0, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F10, 0x7E70, 0x7ED0, 0x7ED0, + 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F40, 0x7F30, 0x7F20, + 0x7F20, 0x7EF0, 0x7F50, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7E60, 0x7B10, 0x76B0, 0x7260, 0x6D50, 0x6850, 0x63D0, 0x6100, + 0x5F50, 0x5EB0, 0x5EF0, 0x5FD0, 0x6210, 0x6470, 0x6770, 0x6BD0, 0x7000, 0x7500, 0x79A0, 0x7CC0, 0x7EA0, 0x7EA0, 0x7F10, 0x7F10, + 0x7F20, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7F30, 0x7F00, 0x7EF0, + 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F00, 0x7EF0, + 0x7F00, 0x7F60, 0x7F10, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7ED0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7EB0, 0x7EF0, + 0x7EE0, 0x7EF0, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F00, + 0x7EF0, 0x7F10, 0x7F60, 0x7F20, 0x7F20, 0x7F20, 0x7F00, 0x7A40, 0x7190, 0x6860, 0x5F40, 0x55D0, 0x4C80, 0x4270, 0x3A90, 0x33B0, + 0x2CE0, 0x27C0, 0x22E0, 0x1DB0, 0x19B0, 0x15A0, 0x1190, 0x0F00, 0x0CD0, 0x0BF0, 0x0B70, 0x0BC0, 0x0C40, 0x0D30, 0x0F10, 0x1160, + 0x1440, 0x1810, 0x1B30, 0x2020, 0x24F0, 0x2990, 0x2F90, 0x3500, 0x3B70, 0x4120, 0x4700, 0x4E00, 0x5440, 0x5A10, 0x5F60, 0x63C0, + 0x6850, 0x6CC0, 0x7040, 0x7350, 0x7590, 0x77E0, 0x79C0, 0x7B90, 0x7CF0, 0x7E20, 0x7ED0, 0x7EB0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, + 0x7F00, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EA0, 0x7E60, 0x7E30, 0x7E10, 0x7E10, 0x7EA0, 0x7EE0, + 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7F10, 0x7F00, 0x7EF0, 0x7E90, 0x7E90, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, + 0x7F10, 0x7EE0, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F40, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, + 0x7EF0, 0x7650, 0x6980, 0x5C60, 0x4F40, 0x41B0, 0x3490, 0x28B0, 0x1C80, 0x1110, 0x06F0, 0xFE60, 0xF650, 0xEF10, 0xE880, 0xE280, + 0xDD10, 0xD850, 0xD310, 0xCFA0, 0xCD90, 0xCD20, 0xCEC0, 0xD200, 0xD6B0, 0xDC80, 0xE2A0, 0xEB30, 0xF260, 0xFAB0, 0x03C0, 0x0DF0, + 0x1900, 0x24E0, 0x3210, 0x3E40, 0x49F0, 0x5540, 0x6130, 0x6E00, 0x7A60, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7950, 0x5B30, + 0x3E20, 0x20E0, 0x03F0, 0xE6F0, 0xCA90, 0xAEC0, 0x9210, 0x8660, 0x84F0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, + 0x8450, 0x8440, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x8530, 0x85D0, 0x86C0, 0x8740, + 0x86B0, 0x85C0, 0x8530, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x8510, + 0x8520, 0x85C0, 0x87E0, 0x8FB0, 0x9930, 0xA070, 0xA4A0, 0xA630, 0xA440, 0x9F50, 0x9760, 0x8EC0, 0x8840, 0x85F0, 0x8540, 0x8500, + 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84D0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8430, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8440, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x84A0, 0x84E0, 0x8680, 0x9AA0, 0xAFB0, 0xBB90, 0xBF80, 0xBE00, 0xB9A0, + 0xB400, 0xADD0, 0xA6B0, 0x9F60, 0x9650, 0x8D30, 0x8760, 0x8550, 0x84E0, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8410, 0x8470, 0x8460, + 0x8450, 0x8440, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8410, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8420, 0x8460, 0x8460, 0x8460, 0x8470, 0x8450, 0x8450, 0x8420, 0x8440, + 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8420, 0x8430, 0x8430, + 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8470, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8500, 0x8550, 0x8650, + 0x8970, 0x92B0, 0x9E50, 0xA8B0, 0xB2C0, 0xBC10, 0xC5B0, 0xD070, 0xDA60, 0xE520, 0xF080, 0xFCE0, 0x0980, 0x1710, 0x25E0, 0x3560, + 0x45A0, 0x5380, 0x5ED0, 0x66A0, 0x6960, 0x66C0, 0x5C90, 0x4AB0, 0x3240, 0x1140, 0xEDB0, 0xC7D0, 0xA1F0, 0x87C0, 0x84E0, 0x84B0, + 0x8450, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x84A0, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x84A0, 0x84C0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8530, 0x8590, 0x8650, 0x8780, 0x8920, 0x8AB0, 0x8C90, 0x8E50, 0x90E0, + 0x9410, 0x9680, 0x98C0, 0x9A70, 0x9A80, 0x9930, 0x96E0, 0x9370, 0x8FC0, 0x8C30, 0x8990, 0x87A0, 0x8690, 0x8620, 0x8660, 0x8690, + 0x87F0, 0x8B10, 0x9190, 0x9890, 0x9D10, 0x9E40, 0x9750, 0x99A0, 0x9D40, 0xA1F0, 0xA730, 0xABE0, 0xAF90, 0xB2F0, 0xB520, 0xB870, + 0xBC80, 0xC2D0, 0xCAF0, 0xD4E0, 0xE1C0, 0xF000, 0xFE90, 0x0D70, 0x1A70, 0x2650, 0x2FC0, 0x3760, 0x3D90, 0x42E0, 0x47F0, 0x4CC0, + 0x50C0, 0x53B0, 0x5500, 0x54D0, 0x5210, 0x4E10, 0x4860, 0x40F0, 0x3950, 0x31A0, 0x2A30, 0x22E0, 0x1B30, 0x16A0, 0x1320, 0x1190, + 0x1210, 0x1400, 0x1840, 0x1CD0, 0x2210, 0x2960, 0x3010, 0x3770, 0x3F40, 0x4640, 0x4D90, 0x5400, 0x5970, 0x5E40, 0x62E0, 0x6820, + 0x6C80, 0x71C0, 0x7680, 0x7A60, 0x7DA0, 0x7ED0, 0x7F30, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, 0x7F20, 0x7F20, 0x7F10, 0x7F10, + 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7F10, 0x7EF0, 0x7F80, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F30, + 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, 0x7F40, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7EF0, 0x7F00, + 0x7EC0, 0x7F20, 0x7F00, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7F00, 0x7F20, 0x7F40, 0x7F00, + 0x7F30, 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F70, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7ED0, 0x7EB0, 0x7F60, + 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EE0, 0x7ED0, 0x7F20, 0x7F20, 0x7E90, 0x7ED0, 0x7F00, 0x7EE0, 0x7EF0, + 0x7EC0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, + 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F80, + 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7EF0, 0x7F40, 0x7F10, + 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7800, 0x6E70, 0x6520, 0x5B50, 0x52B0, 0x4880, + 0x3BF0, 0x2DB0, 0x1CA0, 0x0A40, 0xF510, 0xDD80, 0xC520, 0xAC00, 0x93D0, 0x86E0, 0x8510, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, + 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84E0, 0x84B0, 0x84B0, 0x84D0, 0x84C0, 0x84D0, 0x84F0, + 0x8500, 0x8550, 0x8640, 0x8BA0, 0xA1F0, 0xC010, 0xE500, 0x10B0, 0x4530, 0x7520, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x58A0, 0xDF50, 0x8790, 0x8490, 0x8470, 0x8460, 0x8470, 0x8470, 0x8480, 0x84A0, 0x84D0, + 0x8500, 0x8520, 0x8510, 0x84E0, 0x84B0, 0x8490, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x84A0, 0x84F0, + 0x9330, 0xD740, 0x10F0, 0x3AA0, 0x4CC0, 0x44B0, 0x2660, 0xF820, 0xC090, 0x8B90, 0x84C0, 0x8490, 0x8470, 0x8450, 0x8450, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8490, 0x84B0, 0x84E0, 0x8580, 0x8A60, + 0xA360, 0xBAC0, 0xD370, 0xECB0, 0x0570, 0x1C70, 0x2EC0, 0x3B10, 0x4190, 0x4260, 0x4040, 0x3CF0, 0x3A80, 0x3A60, 0x3D40, 0x4250, + 0x4AB0, 0x54A0, 0x60A0, 0x6AE0, 0x7270, 0x7650, 0x75B0, 0x6FE0, 0x6420, 0x53F0, 0x4130, 0x2EA0, 0x1FF0, 0x1530, 0x0DB0, 0x0920, + 0x05D0, 0x0400, 0x04B0, 0x07B0, 0x0EC0, 0x1830, 0x23E0, 0x2FA0, 0x3AF0, 0x44B0, 0x4D60, 0x5500, 0x5C00, 0x6150, 0x6330, 0x60A0, + 0x57C0, 0x4890, 0x3480, 0x1EB0, 0x0A30, 0xFA40, 0xF070, 0xEDB0, 0xF030, 0xF630, 0xFDB0, 0x05A0, 0x0CB0, 0x12B0, 0x15E0, 0x1660, + 0x1330, 0x0D00, 0x0470, 0xFAE0, 0xF050, 0xE5D0, 0xDAC0, 0xCF20, 0xC170, 0xB400, 0xA700, 0x9A90, 0x8FD0, 0x8980, 0x86B0, 0x85B0, + 0x8540, 0x8510, 0x8500, 0x8500, 0x8500, 0x8510, 0x8530, 0x8560, 0x85F0, 0x8710, 0x89F0, 0x8EC0, 0x9230, 0x93E0, 0x9380, 0x9190, + 0x8ED0, 0x8C20, 0x8A20, 0x8860, 0x8760, 0x86C0, 0x8660, 0x8640, 0x8650, 0x8690, 0x8700, 0x87C0, 0x8920, 0x8C40, 0x9220, 0x9B50, + 0xA600, 0xB330, 0xC140, 0xD000, 0xE030, 0xF200, 0x0460, 0x1750, 0x2AD0, 0x3EE0, 0x5270, 0x6550, 0x75D0, 0x7F20, 0x7ED0, 0x7EB0, + 0x7F30, 0x7F00, 0x7F10, 0x7EB0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F20, 0x7EC0, 0x7E90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F00, 0x7F20, + 0x7F00, 0x7F00, 0x7F00, 0x7F00, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, 0x7F10, + 0x7F20, 0x7F00, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, + 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x78A0, 0x70D0, 0x68B0, 0x60E0, 0x5980, 0x5390, + 0x4F70, 0x4CA0, 0x4C20, 0x4C80, 0x4D30, 0x4EE0, 0x50D0, 0x5490, 0x5880, 0x5CC0, 0x60B0, 0x6390, 0x6660, 0x67A0, 0x68F0, 0x6A30, + 0x6AF0, 0x6C50, 0x6D90, 0x6E80, 0x7020, 0x7140, 0x7230, 0x7330, 0x73D0, 0x7510, 0x75B0, 0x7740, 0x7890, 0x7A30, 0x7C00, 0x7D20, + 0x7DD0, 0x7E40, 0x7ED0, 0x7E90, 0x7E30, 0x7EC0, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, + 0x7F00, 0x7EF0, 0x7F10, 0x7EA0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F80, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7EE0, + 0x7EF0, 0x7F20, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F00, + 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7720, 0x6890, 0x5950, 0x4970, 0x3C60, 0x3050, 0x2630, 0x12C0, 0x13B0, 0x1530, 0x1740, 0x19A0, + 0x1C50, 0x1FE0, 0x2360, 0x2690, 0x2A90, 0x2D90, 0x30A0, 0x3260, 0x3360, 0x34D0, 0x34B0, 0x34E0, 0x3640, 0x39F0, 0x4030, 0x46C0, + 0x4DC0, 0x5380, 0x57E0, 0x5B80, 0x5D90, 0x6060, 0x62A0, 0x63E0, 0x6490, 0x6400, 0x6230, 0x6040, 0x5C60, 0x5910, 0x5500, 0x50E0, + 0x4BE0, 0x4650, 0x4190, 0x3C20, 0x3640, 0x30D0, 0x2B80, 0x2730, 0x2340, 0x20A0, 0x1F40, 0x1D50, 0x1D90, 0x1D60, 0x1CA0, 0x1C50, + 0x1BF0, 0x1C00, 0x1C00, 0x1BF0, 0x1CB0, 0x1BF0, 0x1BC0, 0x1A90, 0x1930, 0x1820, 0x1680, 0x1580, 0x1440, 0x12A0, 0x1150, 0x0F30, + 0x0E20, 0x0D40, 0x0BE0, 0x0BB0, 0x0A10, 0x0950, 0x08D0, 0x07D0, 0x07C0, 0x0710, 0x0790, 0x06B0, 0x0640, 0x0710, 0x0800, 0x0940, + 0x0AE0, 0x0C30, 0x0DD0, 0x0EC0, 0x1050, 0x1270, 0x1500, 0x1870, 0x1AE0, 0x1E10, 0x2150, 0x2430, 0x27A0, 0x2AC0, 0x2EF0, 0x33B0, + 0x3780, 0x3BC0, 0x3FF0, 0x43F0, 0x48E0, 0x4DE0, 0x52D0, 0x5730, 0x5BF0, 0x6040, 0x6480, 0x6920, 0x6D00, 0x7090, 0x7430, 0x7760, + 0x7AC0, 0x7D30, 0x7E70, 0x7EC0, 0x7E90, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, + 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, + 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EB0, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F20, 0x7EC0, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7E90, 0x7F00, 0x7F20, 0x7F10, 0x7F20, 0x7EC0, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7F30, + 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F40, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F50, 0x7EE0, + 0x7A60, 0x7490, 0x6DF0, 0x6840, 0x62C0, 0x5E10, 0x5AB0, 0x57E0, 0x5570, 0x5410, 0x5360, 0x53D0, 0x5390, 0x52F0, 0x51F0, 0x5010, + 0x4EB0, 0x4CB0, 0x4AF0, 0x49C0, 0x4870, 0x47D0, 0x4700, 0x45C0, 0x4600, 0x45C0, 0x46F0, 0x4820, 0x49A0, 0x4B90, 0x4DA0, 0x5020, + 0x52A0, 0x53D0, 0x55E0, 0x5760, 0x58E0, 0x5990, 0x5B00, 0x5D00, 0x5E00, 0x5E90, 0x5EE0, 0x5EE0, 0x5ED0, 0x5E20, 0x5D20, 0x5C40, + 0x5A90, 0x59E0, 0x58A0, 0x5890, 0x59D0, 0x5CB0, 0x5FE0, 0x6370, 0x6670, 0x6960, 0x6AC0, 0x6BB0, 0x6B60, 0x69F0, 0x6910, 0x6730, + 0x6720, 0x66D0, 0x66F0, 0x67B0, 0x6770, 0x6780, 0x6690, 0x6580, 0x64A0, 0x6280, 0x6180, 0x6000, 0x5D60, 0x5B90, 0x5910, 0x5670, + 0x5280, 0x4EE0, 0x4BA0, 0x4880, 0x45B0, 0x42A0, 0x3FC0, 0x3D50, 0x3A80, 0x37B0, 0x3510, 0x31D0, 0x2F30, 0x2C40, 0x2920, 0x2630, + 0x2390, 0x2230, 0x2140, 0x2230, 0x24A0, 0x27F0, 0x2C90, 0x30B0, 0x33A0, 0x3590, 0x36C0, 0x37B0, 0x3840, 0x3900, 0x38F0, 0x3880, + 0x3870, 0x3840, 0x38B0, 0x3990, 0x3AE0, 0x3CE0, 0x3E50, 0x3F30, 0x3ED0, 0x3D70, 0x3BE0, 0x3A60, 0x3A30, 0x3AF0, 0x3CC0, 0x4070, + 0x45E0, 0x4CB0, 0x5560, 0x5EC0, 0x6910, 0x72B0, 0x7B20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x79E0, 0x6D60, 0x6040, + 0x5370, 0x4AA0, 0x4480, 0x42B0, 0x4490, 0x4A20, 0x5240, 0x5AD0, 0x63B0, 0x6CC0, 0x7350, 0x7910, 0x7DA0, 0x7F10, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7B40, 0x6510, 0x4E50, 0x36A0, 0x1EF0, 0x07F0, 0xF5B0, 0xE6D0, + 0xDB10, 0xD2F0, 0xCDC0, 0xCBA0, 0xCCD0, 0xD090, 0xD850, 0xE250, 0xEE20, 0xFAF0, 0x07D0, 0x1510, 0x20D0, 0x2C40, 0x35C0, 0x3ED0, + 0x46A0, 0x4DA0, 0x5560, 0x5CB0, 0x6290, 0x67B0, 0x6BC0, 0x6E10, 0x6EB0, 0x6D20, 0x6940, 0x6410, 0x5E00, 0x56C0, 0x5010, 0x4A00, + 0x44D0, 0x3F00, 0x3910, 0x32F0, 0x2C00, 0x23C0, 0x1B30, 0x1170, 0x0730, 0xFD70, 0xF290, 0xE940, 0xE100, 0xD9D0, 0xD3A0, 0xCF20, + 0xCC50, 0xCA10, 0xC8C0, 0xC7B0, 0xC780, 0xC8B0, 0xCB10, 0xCE80, 0xD3B0, 0xDA00, 0xE070, 0xE6B0, 0xEBC0, 0xEE30, 0xEF60, 0xEED0, + 0xED60, 0xEAF0, 0xE870, 0xE4A0, 0xDFF0, 0xDCD0, 0xDBE0, 0xDBF0, 0xDF30, 0xE310, 0xE560, 0xE4B0, 0xDE20, 0xD150, 0xBB10, 0x9F60, + 0x87F0, 0x84E0, 0x84D0, 0x8490, 0x8470, 0x8470, 0x84A0, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, + 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x8510, 0x8500, 0x8530, 0x85A0, 0x8630, 0x8730, 0x88D0, 0x8AE0, 0x8D50, 0x8F10, 0x8FC0, + 0x8FB0, 0x8E50, 0x8C30, 0x8A20, 0x8820, 0x86D0, 0x85E0, 0x8560, 0x8520, 0x8500, 0x84F0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84A0, + 0x8490, 0x84C0, 0x8490, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8490, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, + 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x8500, 0x8550, 0x85E0, 0x8710, 0x89C0, 0x8E70, 0x9420, + 0x99B0, 0x9EF0, 0xA490, 0xA9B0, 0xAE10, 0xB120, 0xB270, 0xB2B0, 0xB0B0, 0xAD80, 0xA940, 0xA510, 0xA0C0, 0x9C30, 0x97C0, 0x9310, + 0x8E20, 0x8A70, 0x87E0, 0x8680, 0x85F0, 0x85A0, 0x8590, 0x8590, 0x85C0, 0x8620, 0x86E0, 0x8870, 0x8C10, 0x9250, 0x9930, 0xA190, + 0xAA40, 0xB300, 0xBB10, 0xC320, 0xC9A0, 0xCF80, 0xD380, 0xD6C0, 0xD990, 0xDBE0, 0xDEE0, 0xE080, 0xE190, 0xE1D0, 0xE120, 0xE040, + 0xDF90, 0xDEC0, 0xDE20, 0xDD30, 0xDC90, 0xDBB0, 0xDA60, 0xD950, 0xD990, 0xDA70, 0xDC10, 0xDD70, 0xDF70, 0xE130, 0xE4D0, 0xE810, + 0xECC0, 0xF180, 0xF630, 0xFB00, 0x00A0, 0x04C0, 0x09D0, 0x0E40, 0x1320, 0x1790, 0x1B10, 0x1E80, 0x20D0, 0x2310, 0x2530, 0x2760, + 0x2910, 0x2A50, 0x2B40, 0x2C10, 0x2BE0, 0x2BA0, 0x2AD0, 0x2990, 0x2850, 0x2660, 0x24F0, 0x23F0, 0x2320, 0x1EA0, 0x1D00, 0x1B90, + 0x1970, 0x1860, 0x1640, 0x1470, 0x1380, 0x1260, 0x11B0, 0x10F0, 0x0F50, 0x0EB0, 0x0DA0, 0x0CD0, 0x0B80, 0x0A30, 0x0A40, 0x0A10, + 0x0B50, 0x0CB0, 0x0EA0, 0x1170, 0x1360, 0x1750, 0x1B00, 0x1EA0, 0x2240, 0x24B0, 0x2840, 0x2A60, 0x2CB0, 0x2F00, 0x3050, 0x31B0, + 0x3130, 0x2FA0, 0x2F80, 0x2E90, 0x2E20, 0x2D80, 0x2C90, 0x2C10, 0x2B00, 0x2A00, 0x2990, 0x2A30, 0x2B90, 0x2C90, 0x2DB0, 0x2E20, + 0x2E90, 0x2F30, 0x30E0, 0x33E0, 0x3800, 0x3D10, 0x4260, 0x4800, 0x4D50, 0x5330, 0x5920, 0x5FC0, 0x65D0, 0x6C30, 0x71F0, 0x76F0, + 0x7C20, 0x7EE0, 0x7F70, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F70, 0x7ED0, 0x7EA0, 0x7EE0, + 0x7F10, 0x7F30, 0x7EB0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F20, 0x7F00, 0x7F70, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, + 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7E90, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7F10, + 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, + 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7ED0, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7EC0, 0x7910, 0x7130, 0x68E0, 0x60D0, 0x59B0, 0x5500, 0x5040, 0x4BF0, 0x4710, 0x4100, + 0x3A20, 0x3140, 0x27A0, 0x1C80, 0x1040, 0x0340, 0xF420, 0xE2E0, 0xD050, 0xBCC0, 0xA670, 0x9110, 0x8680, 0x84F0, 0x84C0, 0x8480, + 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8460, 0x8470, 0x84A0, 0x8470, 0x84A0, 0x8470, 0x8470, 0x8480, 0x8470, 0x8480, + 0x84B0, 0x84B0, 0x8480, 0x8480, 0x8440, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8430, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84C0, 0x8490, + 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8510, + 0x8550, 0x8550, 0x85A0, 0x8620, 0x8710, 0x88A0, 0x8B30, 0x8EF0, 0x9390, 0x9820, 0x9C40, 0xA090, 0xA560, 0xA930, 0xACF0, 0xB150, + 0xB530, 0xB8C0, 0xBCE0, 0xC090, 0xC3E0, 0xC640, 0xC860, 0xCA80, 0xCC50, 0xCE90, 0xD160, 0xD320, 0xD530, 0xD6E0, 0xD8A0, 0xD9D0, + 0xDB80, 0xDD80, 0xDEC0, 0xE040, 0xE110, 0xE220, 0xE3B0, 0xE4D0, 0xE6A0, 0xE810, 0xE910, 0xE9E0, 0xEAB0, 0xEBE0, 0xED50, 0xEEF0, + 0xEFA0, 0xF050, 0xF050, 0xF100, 0xF1F0, 0xF2C0, 0xF3D0, 0xF500, 0xF690, 0xF710, 0xF7A0, 0xF7B0, 0xF890, 0xF990, 0xFB10, 0xFCB0, + 0xFE40, 0xFF50, 0xFFB0, 0xFFB0, 0x00A0, 0x0150, 0x0230, 0x02E0, 0x03E0, 0x0450, 0x04C0, 0x0520, 0x0550, 0x0550, 0x04E0, 0x04A0, + 0x04C0, 0x0500, 0x05F0, 0x0720, 0x0790, 0x0870, 0x0860, 0x0820, 0x0850, 0x0810, 0x0860, 0x08E0, 0x0900, 0x0930, 0x0960, 0x0960, + 0x0950, 0x09E0, 0x0AA0, 0x0B00, 0x0B10, 0x0AF0, 0x0AC0, 0x0AD0, 0x0AF0, 0x0AE0, 0x0B60, 0x0B90, 0x0BD0, 0x0C20, 0x0D40, 0x0E70, + 0x0EE0, 0x0F50, 0x0F50, 0x0F90, 0x0F90, 0x0F60, 0x1030, 0x1190, 0x1310, 0x13D0, 0x1460, 0x1500, 0x1680, 0x17F0, 0x1930, 0x1B00, + 0x1BC0, 0x1C10, 0x1C30, 0x1CE0, 0x1E40, 0x1FB0, 0x2130, 0x22C0, 0x23C0, 0x25B0, 0x2620, 0x2710, 0x2810, 0x2930, 0x2B20, 0x2C20, + 0x2DD0, 0x3000, 0x3210, 0x3450, 0x3660, 0x3940, 0x3AB0, 0x3BD0, 0x3D60, 0x3EE0, 0x4080, 0x4250, 0x43E0, 0x4640, 0x4790, 0x4930, + 0x4AE0, 0x4B40, 0x4D70, 0x4F60, 0x5110, 0x5320, 0x5400, 0x5550, 0x5680, 0x5860, 0x5B10, 0x5D80, 0x6020, 0x6220, 0x63C0, 0x65D0, + 0x6790, 0x6A20, 0x6CA0, 0x6EF0, 0x7150, 0x72C0, 0x7580, 0x7730, 0x7870, 0x7A10, 0x7A50, 0x7B20, 0x7B70, 0x7B40, 0x7BD0, 0x7B30, + 0x7C00, 0x7BD0, 0x7B50, 0x7B60, 0x7B00, 0x7B40, 0x7B90, 0x7C10, 0x7CB0, 0x7CB0, 0x7D00, 0x7D40, 0x7D10, 0x7DE0, 0x7E20, 0x7EC0, + 0x7ED0, 0x7EB0, 0x7EC0, 0x7EC0, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F80, 0x7EE0, 0x7F10, 0x7F10, 0x7F20, 0x7F80, 0x7EF0, + 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EC0, 0x7ED0, 0x7E30, 0x7D20, 0x7C00, 0x7AC0, 0x79B0, 0x78C0, 0x7690, 0x74B0, 0x7220, + 0x70C0, 0x6F50, 0x6E00, 0x6DA0, 0x6C80, 0x6C20, 0x6B40, 0x6AD0, 0x6B30, 0x6BA0, 0x6CE0, 0x6E10, 0x6F50, 0x7160, 0x73C0, 0x7640, + 0x7920, 0x7C40, 0x7EC0, 0x7F10, 0x7F70, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F70, 0x7F10, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7E90, 0x7ED0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, + 0x7ED0, 0x7F10, 0x7F10, 0x7F20, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EE0, 0x7F30, + 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7BF0, 0x7390, 0x6BE0, 0x6400, 0x5DC0, 0x57B0, 0x52E0, 0x4F80, 0x4D50, 0x4B60, 0x4F50, + 0x5280, 0x5650, 0x5950, 0x5D70, 0x60E0, 0x6430, 0x6730, 0x6920, 0x6BC0, 0x6D50, 0x6EE0, 0x6FF0, 0x70F0, 0x72B0, 0x7460, 0x7690, + 0x7910, 0x7C10, 0x7E70, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F10, 0x7F30, 0x7EC0, + 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, + 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7F20, 0x7F10, 0x7F30, 0x7EE0, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F70, + 0x7F20, 0x7F10, 0x7EF0, 0x7EF0, 0x7DF0, 0x7090, 0x64D0, 0x5B60, 0x5300, 0x49A0, 0x41C0, 0x3930, 0x3170, 0x2930, 0x20C0, 0x1850, + 0x0EB0, 0x05F0, 0xFBC0, 0xF1E0, 0xE8B0, 0xE010, 0xD710, 0xCEB0, 0xC680, 0xBF50, 0xB820, 0xB130, 0xAC20, 0xA810, 0xA560, 0xA3B0, + 0xA270, 0xA1B0, 0xA030, 0x9E00, 0x9B80, 0x9870, 0x9580, 0x9240, 0x8F30, 0x8BE0, 0x8970, 0x87B0, 0x8680, 0x85E0, 0x8590, 0x8560, + 0x8550, 0x8530, 0x8530, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8510, 0x8510, 0x8510, 0x8500, 0x8500, + 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84D0, 0x84F0, 0x84C0, 0x84D0, 0x84E0, + 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x8510, 0x8510, 0x8520, 0x8530, 0x8530, 0x8520, 0x8510, 0x8530, 0x8520, + 0x8500, 0x84F0, 0x8500, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84F0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x8500, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x8500, + 0x8510, 0x8520, 0x8530, 0x8530, 0x8550, 0x8550, 0x8570, 0x8580, 0x85C0, 0x85F0, 0x8610, 0x8650, 0x8680, 0x86F0, 0x8760, 0x8820, + 0x8900, 0x89E0, 0x8AF0, 0x8C10, 0x8D00, 0x8EF0, 0x9160, 0x9470, 0x9720, 0x9980, 0x9C70, 0x9E80, 0xA140, 0xA440, 0xA770, 0xAB20, + 0xADF0, 0xB0F0, 0xB420, 0xB680, 0xB8F0, 0xBB80, 0xBE30, 0xC010, 0xC190, 0xC390, 0xC500, 0xC740, 0xC960, 0xCBC0, 0xCE00, 0xCF60, + 0xD080, 0xD1A0, 0xD2E0, 0xD430, 0xD520, 0xD5A0, 0xD5C0, 0xD5C0, 0xD5F0, 0xD5C0, 0xD610, 0xD600, 0xD550, 0xD430, 0xD320, 0xD280, + 0xD230, 0xD1F0, 0xD1B0, 0xD070, 0xCF10, 0xCDD0, 0xCCA0, 0xCC90, 0xCC80, 0xCD70, 0xCD50, 0xCCC0, 0xCC90, 0xCB90, 0xCAF0, 0xCA50, + 0xCA00, 0xCA20, 0xCA30, 0xC920, 0xC820, 0xC750, 0xC720, 0xC710, 0xC710, 0xC700, 0xC720, 0xC6A0, 0xC630, 0xC600, 0xC5C0, 0xC610, + 0xC750, 0xC840, 0xC8F0, 0xC8F0, 0xC910, 0xC8F0, 0xC8E0, 0xC880, 0xC850, 0xC840, 0xC870, 0xC900, 0xC920, 0xC8C0, 0xC8E0, 0xC910, + 0xC960, 0xC9A0, 0xC9D0, 0xC9E0, 0xCA40, 0xCA70, 0xCB20, 0xCBD0, 0xCCF0, 0xCE20, 0xCF40, 0xD070, 0xD190, 0xD2F0, 0xD440, 0xD570, + 0xD6E0, 0xD8B0, 0xD9C0, 0xDB70, 0xDD80, 0xDF10, 0xE120, 0xE2F0, 0xE510, 0xE730, 0xE990, 0xEC40, 0xEE90, 0xF140, 0xF3F0, 0xF5F0, + 0xF910, 0xFC30, 0xFEA0, 0x0110, 0x03E0, 0x0710, 0x09D0, 0x0CB0, 0x0FA0, 0x12F0, 0x1590, 0x1790, 0x19C0, 0x1C70, 0x1F10, 0x2150, + 0x2370, 0x2560, 0x2760, 0x28F0, 0x2B10, 0x2CC0, 0x2F00, 0x3120, 0x33C0, 0x35D0, 0x37B0, 0x3900, 0x3A40, 0x3B70, 0x3D70, 0x3FB0, + 0x41E0, 0x4410, 0x4610, 0x4740, 0x4920, 0x4A90, 0x4B70, 0x4CB0, 0x4EA0, 0x5000, 0x5150, 0x52C0, 0x54D0, 0x5730, 0x5950, 0x5B20, + 0x5D40, 0x5EC0, 0x5FF0, 0x6120, 0x6330, 0x6530, 0x6690, 0x6800, 0x68A0, 0x6990, 0x6A60, 0x6C40, 0x6E10, 0x6F30, 0x7040, 0x7070, + 0x7050, 0x70D0, 0x7160, 0x71C0, 0x71A0, 0x70F0, 0x7090, 0x6FB0, 0x6E60, 0x6D20, 0x6BF0, 0x69B0, 0x6720, 0x64C0, 0x6250, 0x6030, + 0x5E20, 0x5B40, 0x5800, 0x54D0, 0x5160, 0x4DE0, 0x4A10, 0x46A0, 0x42E0, 0x3F40, 0x3BB0, 0x37B0, 0x3460, 0x31D0, 0x2FF0, 0x2F30, + 0x2DE0, 0x2CD0, 0x2AF0, 0x2A00, 0x29F0, 0x2A60, 0x2C90, 0x2EF0, 0x3240, 0x3580, 0x38D0, 0x3D00, 0x41C0, 0x4690, 0x4C10, 0x51B0, + 0x57A0, 0x5E50, 0x64B0, 0x6AA0, 0x71D0, 0x7850, 0x7D70, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F50, 0x7E90, 0x7EB0, 0x7EF0, + 0x7EE0, 0x7EF0, 0x7E80, 0x7E70, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7ED0, 0x7F00, 0x7F20, 0x7F00, 0x7F00, 0x7F20, 0x7F20, 0x7F10, + 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7ED0, 0x7C30, 0x72E0, 0x6A70, 0x6380, 0x5D90, 0x5860, 0x54A0, 0x51A0, 0x50A0, + 0x4FE0, 0x50D0, 0x5270, 0x54F0, 0x5970, 0x5EF0, 0x6430, 0x6AE0, 0x7000, 0x74F0, 0x79A0, 0x7CC0, 0x7E80, 0x7E90, 0x7F10, 0x7F20, + 0x7F10, 0x7EB0, 0x7C40, 0x78F0, 0x74B0, 0x6F00, 0x69C0, 0x63C0, 0x5E80, 0x5900, 0x5540, 0x53B0, 0x5400, 0x5560, 0x5750, 0x5990, + 0x5CE0, 0x5FC0, 0x6390, 0x67B0, 0x6B60, 0x7040, 0x73D0, 0x7710, 0x7920, 0x7B40, 0x7C80, 0x7CC0, 0x7C60, 0x7B50, 0x7970, 0x77A0, + 0x7600, 0x74D0, 0x7430, 0x7360, 0x7290, 0x71E0, 0x7070, 0x7040, 0x6FD0, 0x7030, 0x7040, 0x6F90, 0x6F10, 0x6E20, 0x6DD0, 0x6CB0, + 0x6BB0, 0x6B70, 0x6A80, 0x6A90, 0x6BA0, 0x6C40, 0x6ED0, 0x7080, 0x7260, 0x7440, 0x7590, 0x77B0, 0x7960, 0x7B40, 0x7D10, 0x7E20, + 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7F10, 0x7EF0, 0x7EB0, 0x7EE0, 0x7E30, 0x7CB0, 0x7A60, 0x7850, 0x75D0, 0x7330, 0x7020, 0x6DC0, + 0x6AD0, 0x6760, 0x63A0, 0x6080, 0x5E30, 0x5C20, 0x59B0, 0x5750, 0x5430, 0x5200, 0x4F80, 0x4D70, 0x4C60, 0x4A90, 0x4950, 0x4720, + 0x44F0, 0x43C0, 0x4110, 0x3F60, 0x3DC0, 0x3A70, 0x3700, 0x3160, 0x2BE0, 0x2610, 0x1F60, 0x18E0, 0x1090, 0x0A10, 0x0360, 0xFD40, + 0xF890, 0xF4E0, 0xF160, 0xEE00, 0xEA70, 0xE6A0, 0xE3E0, 0xE200, 0xE0B0, 0xDF10, 0xDD30, 0xDA10, 0xD620, 0xD1D0, 0xCC50, 0xC810, + 0xC280, 0xBBB0, 0xB380, 0xAA80, 0xA060, 0x95A0, 0x8C80, 0x8790, 0x85C0, 0x8520, 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, + 0x84A0, 0x8490, 0x8490, 0x8490, 0x84D0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x8500, 0x8510, 0x8520, 0x8530, 0x8560, 0x8590, 0x85C0, 0x8620, + 0x8680, 0x8710, 0x8790, 0x8830, 0x8960, 0x8AA0, 0x8BD0, 0x8D10, 0x8E20, 0x8FB0, 0x9180, 0x93B0, 0x94F0, 0x95B0, 0x9580, 0x9530, + 0x95C0, 0x9680, 0x9780, 0x98A0, 0x98A0, 0x98D0, 0x9830, 0x9760, 0x9710, 0x96C0, 0x9710, 0x96A0, 0x9610, 0x9580, 0x9500, 0x9480, + 0x9430, 0x9490, 0x94C0, 0x9410, 0x93C0, 0x93C0, 0x9410, 0x94D0, 0x9520, 0x9580, 0x95A0, 0x9580, 0x9600, 0x9600, 0x9680, 0x96F0, + 0x9630, 0x95C0, 0x9460, 0x9390, 0x92F0, 0x9280, 0x9300, 0x92C0, 0x91D0, 0x9060, 0x8F10, 0x8DD0, 0x8D70, 0x8D20, 0x8C80, 0x8BA0, + 0x8AD0, 0x89E0, 0x88D0, 0x8830, 0x87C0, 0x8770, 0x8730, 0x86C0, 0x8660, 0x8620, 0x85E0, 0x85C0, 0x85C0, 0x8570, 0x8570, 0x8560, + 0x8550, 0x8520, 0x8550, 0x8530, 0x8530, 0x8520, 0x8510, 0x8510, 0x8500, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84E0, + 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84D0, 0x8460, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, + 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x8450, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84D0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84E0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8530, 0x8580, 0x85F0, 0x8710, 0x8930, 0x8CE0, 0x91F0, + 0x9840, 0x9E70, 0xA4D0, 0xAB60, 0xB0C0, 0xB610, 0xBA80, 0xBE00, 0xC1A0, 0xC570, 0xC900, 0xCC90, 0xD010, 0xD260, 0xD440, 0xD5A0, + 0xD690, 0xD830, 0xDA40, 0xDC40, 0xDE70, 0xDFB0, 0xE060, 0xE150, 0xE1C0, 0xE270, 0xE330, 0xE350, 0xE3D0, 0xE450, 0xE500, 0xE630, + 0xE710, 0xE790, 0xE740, 0xE6A0, 0xE630, 0xE590, 0xE530, 0xE5C0, 0xE5E0, 0xE620, 0xE5A0, 0xE4A0, 0xE380, 0xE2A0, 0xE240, 0xE200, + 0xE190, 0xE190, 0xE0B0, 0xE0D0, 0xE160, 0xE1A0, 0xE270, 0xE250, 0xE2B0, 0xE370, 0xE430, 0xE570, 0xE780, 0xE9E0, 0xEC90, 0xEF10, + 0xF1A0, 0xF3B0, 0xF6B0, 0xF980, 0xFD80, 0x0190, 0x0590, 0x09B0, 0x0E40, 0x1300, 0x1790, 0x1C80, 0x2180, 0x2650, 0x2B20, 0x2FA0, + 0x34D0, 0x3980, 0x3EE0, 0x4420, 0x4940, 0x4D90, 0x51E0, 0x5610, 0x5A90, 0x5E80, 0x62A0, 0x65E0, 0x68F0, 0x6BE0, 0x6DE0, 0x6FC0, + 0x71F0, 0x7420, 0x75A0, 0x76D0, 0x7780, 0x77D0, 0x77D0, 0x7850, 0x78D0, 0x7940, 0x7950, 0x78D0, 0x7750, 0x7600, 0x7560, 0x7580, + 0x75A0, 0x75A0, 0x7550, 0x7510, 0x74A0, 0x7520, 0x75F0, 0x76F0, 0x7820, 0x7950, 0x7A10, 0x7B90, 0x7CC0, 0x7E40, 0x7EF0, 0x7F00, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7EE0, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7ED0, 0x7E10, 0x7D30, 0x7C00, 0x7BC0, 0x7B50, 0x7950, 0x7860, 0x77D0, 0x7690, 0x7610, 0x75A0, + 0x75C0, 0x75F0, 0x7630, 0x76A0, 0x7680, 0x75E0, 0x7560, 0x7540, 0x7580, 0x7630, 0x7760, 0x78F0, 0x7A80, 0x7C80, 0x7DE0, 0x7ED0, + 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F00, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, + 0x7F00, 0x7F10, 0x7EF0, 0x7F30, 0x7EF0, 0x7E90, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7E80, + 0x7EF0, 0x7F10, 0x7EF0, 0x7ED0, 0x7EB0, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, + 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F50, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7F70, 0x7F00, + 0x7ED0, 0x7F10, 0x7F00, 0x7F40, 0x7E90, 0x7C50, 0x7920, 0x7510, 0x70B0, 0x6D10, 0x6940, 0x6680, 0x6350, 0x6030, 0x5DA0, 0x5970, + 0x5660, 0x5370, 0x5090, 0x4F00, 0x4E00, 0x4D60, 0x4C40, 0x4C90, 0x4E00, 0x4F10, 0x5110, 0x5270, 0x5360, 0x5450, 0x5490, 0x5530, + 0x5660, 0x5660, 0x56E0, 0x5720, 0x5670, 0x5600, 0x54A0, 0x5440, 0x5240, 0x4FF0, 0x4D70, 0x4B10, 0x4980, 0x4760, 0x4500, 0x4350, + 0x4150, 0x3FA0, 0x3D60, 0x3B30, 0x3A00, 0x38A0, 0x37C0, 0x36F0, 0x3670, 0x3660, 0x3510, 0x3490, 0x32C0, 0x3090, 0x2F50, 0x2D00, + 0x2C00, 0x2940, 0x26D0, 0x2410, 0x2060, 0x1D80, 0x1A60, 0x16C0, 0x13D0, 0x1050, 0x0C60, 0x08C0, 0x0450, 0x00C0, 0xFCE0, 0xF940, + 0xF610, 0xF230, 0xEF60, 0xEBF0, 0xE830, 0xE490, 0xE070, 0xDC30, 0xD7F0, 0xD470, 0xD140, 0xCEA0, 0xCC60, 0xCA90, 0xC8F0, 0xC7D0, + 0xC600, 0xC4B0, 0xC370, 0xC340, 0xC2A0, 0xC250, 0xC310, 0xC3E0, 0xC540, 0xC700, 0xC9F0, 0xCD20, 0xD030, 0xD290, 0xD580, 0xD780, + 0xDA00, 0xDD00, 0xE040, 0xED40, 0xEFE0, 0xF2D0, 0xF5E0, 0xF8B0, 0xFB50, 0xFD60, 0x0000, 0x0180, 0x03F0, 0x06C0, 0x0950, 0x0BB0, + 0x0D00, 0x0EF0, 0x0FD0, 0x1090, 0x10A0, 0x0F90, 0x0EF0, 0x0D90, 0x0B50, 0x0A30, 0x0860, 0x06E0, 0x0520, 0x0250, 0xFFB0, 0xFC00, + 0xF820, 0xF450, 0xF0C0, 0xEE50, 0xEBF0, 0xEA30, 0xE7E0, 0xE460, 0xE110, 0xDDF0, 0xDB60, 0xD9A0, 0xD7F0, 0xD740, 0xD5D0, 0xD3F0, + 0xD2D0, 0xD1D0, 0xD1F0, 0xD1B0, 0xD230, 0xD330, 0xD3A0, 0xD460, 0xD4D0, 0xD550, 0xD6D0, 0xD800, 0xDA10, 0xDB90, 0xDCF0, 0xDEF0, + 0xE060, 0xE210, 0xE400, 0xE5C0, 0xE7A0, 0xE8E0, 0xEA40, 0xEBC0, 0xEDD0, 0xEFE0, 0xF160, 0xF2A0, 0xF450, 0xF5E0, 0xF910, 0xFBA0, + 0xFED0, 0x0180, 0x0340, 0x0510, 0x06B0, 0x0940, 0x0B70, 0x0E00, 0x10E0, 0x1350, 0x1550, 0x1750, 0x18C0, 0x1B10, 0x1CB0, 0x1E70, + 0x1F40, 0x2090, 0x2230, 0x23E0, 0x2550, 0x2710, 0x2890, 0x2A40, 0x2B80, 0x2B70, 0x2BE0, 0x2C40, 0x2D90, 0x2EA0, 0x2F20, 0x2FC0, + 0x2F50, 0x2EB0, 0x2F50, 0x2FB0, 0x30B0, 0x30C0, 0x30F0, 0x3050, 0x2F20, 0x2FC0, 0x3000, 0x3070, 0x3100, 0x3110, 0x3200, 0x3200, + 0x32C0, 0x32C0, 0x3370, 0x3430, 0x3440, 0x33B0, 0x33D0, 0x3340, 0x33F0, 0x34F0, 0x3500, 0x35C0, 0x3540, 0x3570, 0x34E0, 0x33F0, + 0x33F0, 0x3370, 0x3360, 0x3250, 0x3090, 0x2F30, 0x2D30, 0x2C30, 0x2A30, 0x2950, 0x27C0, 0x24D0, 0x2290, 0x2060, 0x1E00, 0x1C70, + 0x1A40, 0x1940, 0x1770, 0x1540, 0x1460, 0x1290, 0x1130, 0x0F90, 0x0C90, 0x0B10, 0x0900, 0x0740, 0x0590, 0x0490, 0x0420, 0x03A0, + 0x0280, 0x01A0, 0x0020, 0xFFB0, 0xFF50, 0xFF80, 0xFFE0, 0x0040, 0x0130, 0x0130, 0x0190, 0x0180, 0x0190, 0x02C0, 0x03C0, 0x0410, + 0x04A0, 0x0470, 0x04D0, 0x05A0, 0x06C0, 0x0800, 0x08F0, 0x0A40, 0x0A40, 0x0AF0, 0x0C30, 0x0CA0, 0x0E10, 0x0ED0, 0x0EE0, 0x0F40, + 0x0F80, 0x1030, 0x1130, 0x11F0, 0x12D0, 0x1300, 0x1380, 0x1310, 0x1310, 0x13A0, 0x13C0, 0x1450, 0x1450, 0x1520, 0x1530, 0x15B0, + 0x15E0, 0x1640, 0x15D0, 0x1630, 0x1610, 0x1670, 0x1710, 0x17B0, 0x1920, 0x1990, 0x1980, 0x19C0, 0x18E0, 0x1950, 0x19B0, 0x19E0, + 0x1A10, 0x19B0, 0x1960, 0x1900, 0x1840, 0x1820, 0x1740, 0x16A0, 0x15D0, 0x1520, 0x14E0, 0x1430, 0x1470, 0x1400, 0x1420, 0x14F0, + 0x14E0, 0x1590, 0x1550, 0x1530, 0x1560, 0x1520, 0x1590, 0x1510, 0x14E0, 0x1460, 0x1340, 0x12F0, 0x1240, 0x1110, 0x1060, 0x0F80, + 0x0EC0, 0x0DB0, 0x0CB0, 0x0BB0, 0x0980, 0x0860, 0x0640, 0x03A0, 0x0180, 0xFF10, 0xFD00, 0xFA40, 0xF7B0, 0xF450, 0xF180, 0xEEC0, + 0xEC50, 0xE960, 0xE6C0, 0xE490, 0xE2A0, 0xDFE0, 0xDD80, 0xDB20, 0xD930, 0xD750, 0xD620, 0xD530, 0xD490, 0xD3F0, 0xD2F0, 0xD240, + 0xD160, 0xD0C0, 0xD070, 0xD040, 0xD060, 0xD0F0, 0xD150, 0xD1A0, 0xD280, 0xD340, 0xD400, 0xD4A0, 0xD440, 0xD3F0, 0xD390, 0xD3D0, + 0xD480, 0xD520, 0xD620, 0xD680, 0xD6E0, 0xD610, 0xD530, 0xD330, 0xD2F0, 0xD2D0, 0xD290, 0xD2D0, 0xD310, 0xD2F0, 0xD340, 0xD2D0, + 0xD250, 0xD1B0, 0xD170, 0xD190, 0xD1E0, 0xD140, 0xD0D0, 0xD030, 0xCFC0, 0xCF30, 0xCF10, 0xCED0, 0xCED0, 0xCF60, 0xCFE0, 0xD000, + 0xCFF0, 0xD010, 0xD050, 0xD030, 0xD040, 0xD050, 0xD000, 0xD010, 0xD120, 0xD130, 0xD180, 0xD210, 0xD220, 0xD230, 0xD1F0, 0xD1A0, + 0xD1F0, 0xD300, 0xD410, 0xD4C0, 0xD550, 0xD5A0, 0xD600, 0xD5C0, 0xD5B0, 0xD5A0, 0xD560, 0xD5C0, 0xD5C0, 0xD5A0, 0xD580, 0xD550, + 0xD530, 0xD500, 0xD4C0, 0xD450, 0xD450, 0xD400, 0xD440, 0xD4C0, 0xD520, 0xD570, 0xD5D0, 0xD510, 0xD590, 0xD5C0, 0xD650, 0xD710, + 0xD730, 0xD790, 0xD710, 0xD710, 0xD6A0, 0xD6E0, 0xD6B0, 0xD6D0, 0xD730, 0xD7C0, 0xD850, 0xD8C0, 0xD990, 0xDA40, 0xDA70, 0xDAD0, + 0xDB50, 0xDBF0, 0xDC90, 0xDCC0, 0xDDD0, 0xDE70, 0xDED0, 0xDF00, 0xDFA0, 0xDF70, 0xDFF0, 0xE0C0, 0xE130, 0xE1C0, 0xE2B0, 0xE370, + 0xE490, 0xE530, 0xE570, 0xE590, 0xE560, 0xE510, 0xE5C0, 0xE6D0, 0xE7D0, 0xE900, 0xEA60, 0xEB00, 0xEB10, 0xEAF0, 0xEAD0, 0xEAE0, + 0xEC00, 0xECE0, 0xEEE0, 0xF080, 0xF250, 0xF320, 0xF380, 0xF430, 0xF490, 0xF470, 0xF4B0, 0xF610, 0xF750, 0xF870, 0xFA10, 0xFAD0, + 0xFC40, 0xFD70, 0xFE40, 0xFF80, 0xFFF0, 0x0100, 0x0100, 0x0150, 0x0200, 0x02B0, 0x0390, 0x03D0, 0x0440, 0x04C0, 0x04F0, 0x05E0, + 0x0660, 0x0670, 0x06E0, 0x06C0, 0x06C0, 0x0750, 0x0790, 0x0820, 0x0840, 0x0910, 0x0930, 0x0940, 0x09B0, 0x0980, 0x09A0, 0x0A10, + 0x09D0, 0x0A30, 0x0A60, 0x0A40, 0x0AA0, 0x0AA0, 0x0B40, 0x0B50, 0x0AC0, 0x0AC0, 0x0AC0, 0x0AB0, 0x0A70, 0x09B0, 0x09D0, 0x0990, + 0x0970, 0x0990, 0x08F0, 0x0920, 0x08C0, 0x0880, 0x0900, 0x0940, 0x0940, 0x08D0, 0x0830, 0x0800, 0x07F0, 0x07D0, 0x07D0, 0x0810, + 0x07E0, 0x07B0, 0x0870, 0x0840, 0x0910, 0x08B0, 0x07E0, 0x07D0, 0x06E0, 0x0700, 0x06C0, 0x0630, 0x0630, 0x0600, 0x0600, 0x0610, + 0x0570, 0x0640, 0x0600, 0x05A0, 0x05C0, 0x0470, 0x0430, 0x0430, 0x0440, 0x0470, 0x0470, 0x04C0, 0x03E0, 0x0250, 0x01E0, 0x00A0, + 0x0040, 0xFF70, 0xFEE0, 0xFDF0, 0xFD50, 0xFD50, 0xFC60, 0xFBC0, 0xFBB0, 0xFAF0, 0xFAC0, 0xF940, 0xF7F0, 0xF700, 0xF640, 0xF5D0, + 0xF5F0, 0xF5C0, 0xF5D0, 0xF4D0, 0xF430, 0xF3C0, 0xF2B0, 0xF1F0, 0xF140, 0xF090, 0xF000, 0xEF00, 0xEF60, 0xEF80, 0xEF80, 0xEF80, + 0xEEF0, 0xEE50, 0xEDA0, 0xED20, 0xED50, 0xEDB0, 0xEE70, 0xEEE0, 0xEE80, 0xEEA0, 0xEE40, 0xEEB0, 0xEEF0, 0xEF50, 0xF070, 0xF0F0, + 0xF1B0, 0xF2C0, 0xF410, 0xF5E0, 0xF7E0, 0xFAC0, 0xFCC0, 0xFF80, 0x0270, 0x0590, 0x09D0, 0x0E20, 0x12F0, 0x1790, 0x1BA0, 0x2000, + 0x2500, 0x2970, 0x2F60, 0x3460, 0x3A50, 0x3F90, 0x4420, 0x4960, 0x4DC0, 0x5280, 0x5640, 0x5980, 0x5CB0, 0x5E40, 0x6020, 0x6180, + 0x6230, 0x6370, 0x6380, 0x63F0, 0x6460, 0x63A0, 0x6380, 0x6280, 0x60C0, 0x5E60, 0x5B90, 0x58B0, 0x55B0, 0x5280, 0x4F70, 0x4B30, + 0x4780, 0x4310, 0x3DB0, 0x37A0, 0x3100, 0x1400, 0x0B40, 0x0310, 0xFAB0, 0xF360, 0xED00, 0xE750, 0xE270, 0xDD60, 0xD810, 0xD150, + 0xCA70, 0xC340, 0xBB00, 0xB290, 0xA970, 0xA1D0, 0x9D30, 0x9BE0, 0x9EF0, 0xA6C0, 0xB0A0, 0xBB00, 0xC300, 0xC870, 0xC8C0, 0xC4D0, + 0xBCD0, 0xB250, 0xA590, 0x97A0, 0x8AB0, 0x85A0, 0x84E0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, + 0x8520, 0x8550, 0x85B0, 0x8690, 0x8860, 0x8BF0, 0x9130, 0x96C0, 0x9BB0, 0xA150, 0xA620, 0xAA70, 0xADE0, 0xB1F0, 0xB5E0, 0xB8A0, + 0xBC30, 0xC010, 0xC400, 0xC9D0, 0xD000, 0xD740, 0xDFD0, 0xE8B0, 0xF300, 0xFD80, 0x08C0, 0x1450, 0x1E20, 0x27D0, 0x3000, 0x3730, + 0x3D70, 0x42C0, 0x4880, 0x4D00, 0x5160, 0x5590, 0x5860, 0x5B00, 0x5C40, 0x5DB0, 0x5F20, 0x60E0, 0x6310, 0x6490, 0x65E0, 0x6670, + 0x6610, 0x66B0, 0x67E0, 0x6990, 0x6AB0, 0x6B30, 0x6B70, 0x6B10, 0x6A60, 0x69A0, 0x6880, 0x6890, 0x6780, 0x65E0, 0x6550, 0x64D0, + 0x6640, 0x6890, 0x6A90, 0x6E30, 0x7200, 0x7650, 0x7AB0, 0x7DA0, 0x7F00, 0x7EB0, 0x7F20, 0x7F00, 0x7E10, 0x79B0, 0x7440, 0x6EC0, + 0x6990, 0x63B0, 0x5EE0, 0x5980, 0x5510, 0x5180, 0x4E20, 0x4B90, 0x4970, 0x4730, 0x4540, 0x42B0, 0x4220, 0x4260, 0x4250, 0x42D0, + 0x4340, 0x4420, 0x4530, 0x46F0, 0x4A00, 0x4D10, 0x5210, 0x55F0, 0x59F0, 0x5E90, 0x62D0, 0x6900, 0x6EC0, 0x7590, 0x7BA0, 0x7E80, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F10, + 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F60, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F50, 0x7F00, + 0x7F00, 0x7F10, 0x7F20, 0x7F60, 0x7F00, 0x7EF0, 0x7F00, 0x7EE0, 0x7F60, 0x7A90, 0x7120, 0x6CC0, 0x6AF0, 0x6BF0, 0x6FC0, 0x74D0, + 0x7B50, 0x7EF0, 0x7F20, 0x7ED0, 0x7EA0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7EC0, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, + 0x7EE0, 0x7EF0, 0x7F40, 0x7F10, 0x7F60, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, + 0x7F10, 0x7F10, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F30, 0x7F20, 0x7E90, + 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7E70, 0x7EC0, 0x6B40, 0x4E30, 0x2F40, 0x0BE0, 0xEB50, 0xC9F0, 0xA7B0, 0x86C0, 0x84C0, 0x8490, + 0x8470, 0x8450, 0x8430, 0x8420, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8460, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, + 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, + 0x8480, 0x8490, 0x8490, 0x84B0, 0x84D0, 0x8500, 0x9B90, 0xA6F0, 0xB010, 0xB8B0, 0xBFF0, 0xC6A0, 0xCD00, 0xD2C0, 0xD640, 0xD870, + 0xD920, 0xD970, 0xD950, 0xD9E0, 0xDAD0, 0xDBD0, 0xDC60, 0xDC00, 0xDAE0, 0xD850, 0xD4F0, 0xD040, 0xCB30, 0xC4D0, 0xBF90, 0xBA60, + 0xB630, 0xB410, 0xB390, 0xB4F0, 0xB740, 0xB9C0, 0xBCF0, 0xC060, 0xC430, 0xC9A0, 0xCF00, 0xD500, 0xDAF0, 0xE210, 0xE9E0, 0xF2D0, + 0xFBF0, 0x05C0, 0x0E70, 0x16B0, 0x1EB0, 0x2600, 0x2C00, 0x30D0, 0x3350, 0x3350, 0x31F0, 0x2F70, 0x2C50, 0x29A0, 0x25A0, 0x20B0, + 0x1B30, 0x1470, 0x0DC0, 0x06D0, 0x00B0, 0xFBE0, 0xF6F0, 0xF350, 0xEF70, 0xEBA0, 0xE840, 0xE4B0, 0xE180, 0xDF10, 0xDC50, 0xD950, + 0xD4E0, 0xD0C0, 0xCB40, 0xC550, 0xC040, 0xB9B0, 0xB230, 0xAAC0, 0xA250, 0x99C0, 0x9140, 0x8AD0, 0x8760, 0x85D0, 0x8540, 0x8500, + 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x8620, 0x8B20, 0x9A70, + 0xAA60, 0xB800, 0xC430, 0xCF10, 0xD920, 0xE270, 0xEB10, 0xF3E0, 0xFB60, 0x02F0, 0x0940, 0x0D60, 0x1050, 0x1200, 0x1350, 0x14C0, + 0x1580, 0x1740, 0x1820, 0x1800, 0x1740, 0x1580, 0x1320, 0x10C0, 0x0DB0, 0x0BF0, 0x0A70, 0x0A70, 0x0BB0, 0x0DB0, 0x11F0, 0x16F0, + 0x1C90, 0x2340, 0x2A50, 0x32B0, 0x3B60, 0x4340, 0x4A10, 0x4FB0, 0x5520, 0x5940, 0x5D50, 0x6120, 0x6420, 0x6810, 0x6AB0, 0x6CF0, + 0x6E90, 0x6F90, 0x70F0, 0x71E0, 0x7240, 0x7350, 0x7320, 0x7400, 0x74D0, 0x74B0, 0x74C0, 0x7400, 0x7350, 0x72B0, 0x71E0, 0x71B0, + 0x7030, 0x6FA0, 0x6E60, 0x6CD0, 0x6C10, 0x6B40, 0x6AE0, 0x6AD0, 0x6A40, 0x6A40, 0x6990, 0x6900, 0x6870, 0x67C0, 0x6890, 0x68E0, + 0x6930, 0x6990, 0x69E0, 0x6AE0, 0x6C40, 0x6DD0, 0x7030, 0x7220, 0x7440, 0x7650, 0x7870, 0x7A60, 0x7C50, 0x7E70, 0x7F00, 0x7F70, + 0x7ED0, 0x7EB0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, + 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7F10, 0x7F20, 0x7EF0, + 0x7F80, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7EE0, 0x7F50, + 0x7F20, 0x7EE0, 0x7ED0, 0x7ED0, 0x7F30, 0x7EF0, 0x7E90, 0x7ED0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7ED0, + 0x7F10, 0x77A0, 0x6DA0, 0x64C0, 0x5B90, 0x52A0, 0x4B70, 0x4400, 0x3E70, 0x38E0, 0x33B0, 0x2FD0, 0x2C80, 0x2A80, 0x2950, 0x2950, + 0x2C00, 0x2E40, 0x3290, 0x3880, 0x3E40, 0x4580, 0x4C90, 0x5220, 0x5670, 0x59D0, 0x5C30, 0x5DE0, 0x5F30, 0x5F90, 0x5F70, 0x5FA0, + 0x5EF0, 0x5DF0, 0x5CA0, 0x5B40, 0x5A90, 0x5A30, 0x5A70, 0x5B20, 0x5B90, 0x5D50, 0x5EE0, 0x61F0, 0x66E0, 0x6C60, 0x7350, 0x7A00, + 0x7E70, 0x7EE0, 0x7EC0, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F00, 0x7F00, + 0x7F10, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, + 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7ED0, 0x7F70, 0x7F20, 0x7EA0, 0x7ED0, 0x7ED0, + 0x7F00, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, + 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F50, 0x7ED0, 0x6110, 0x4370, 0x25F0, 0x0830, 0xEEF0, 0xD720, 0xC150, + 0xADF0, 0x9BD0, 0x8E90, 0x88A0, 0x86F0, 0x86C0, 0x8790, 0x8AA0, 0x92B0, 0x9DF0, 0xA910, 0xB410, 0xBE70, 0xC790, 0xD050, 0xD830, + 0xDEE0, 0xE590, 0xEBF0, 0xF220, 0xF780, 0xFB50, 0xFFF0, 0x02C0, 0x0510, 0x06E0, 0x0840, 0x09F0, 0x0AB0, 0x0B50, 0x0BE0, 0x0C60, + 0x0E30, 0x0FA0, 0x11A0, 0x1430, 0x16B0, 0x1AA0, 0x1EC0, 0x23D0, 0x29F0, 0x3020, 0x3650, 0x3B30, 0x3FF0, 0x4420, 0x4790, 0x4B10, + 0x4D20, 0x4DF0, 0x4D90, 0x4B70, 0x4940, 0x4640, 0x43F0, 0x42A0, 0x40E0, 0x40F0, 0x4190, 0x4320, 0x4650, 0x4A90, 0x50C0, 0x57C0, + 0x5F90, 0x68B0, 0x7100, 0x7960, 0x7E90, 0x7F30, 0x7F00, 0x7E90, 0x7ED0, 0x7F10, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, + 0x7F10, 0x7EC0, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7E10, 0x5E70, 0x3AF0, 0x1490, 0xEAE0, + 0xC400, 0x9D90, 0x8660, 0x84C0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8420, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, + 0x8480, 0x8460, 0x8470, 0x8480, 0x8480, 0x84B0, 0x84E0, 0x8530, 0x86A0, 0x8DB0, 0x9D20, 0xAB40, 0xB7F0, 0xC4C0, 0xD130, 0xDD30, + 0xE8D0, 0xF3B0, 0xFE00, 0x06A0, 0x0E10, 0x1420, 0x19C0, 0x1F30, 0x2310, 0x2570, 0x2790, 0x2830, 0x27F0, 0x2540, 0x2150, 0x1AE0, + 0x12E0, 0x0890, 0xFD50, 0xF0A0, 0xE460, 0xD8B0, 0xCD10, 0xC1D0, 0xB660, 0xAB80, 0xA180, 0x98E0, 0x9180, 0x8BD0, 0x8870, 0x86C0, + 0x85F0, 0x8590, 0x8570, 0x8570, 0x8570, 0x85C0, 0x85E0, 0x8680, 0x8820, 0x8C40, 0x95F0, 0xA030, 0xAAB0, 0xB510, 0xBFB0, 0xCA30, + 0xD440, 0xDCD0, 0xE380, 0xE900, 0xEC90, 0xF030, 0xF390, 0xF7E0, 0xFC70, 0x00D0, 0x04C0, 0x0860, 0x0BD0, 0x0EA0, 0x1170, 0x1430, + 0x1650, 0x18E0, 0x1BD0, 0x1F80, 0x22B0, 0x2640, 0x28C0, 0x2A50, 0x2BA0, 0x2C60, 0x2D70, 0x2E50, 0x30B0, 0x3360, 0x36D0, 0x3990, + 0x3BC0, 0x3E10, 0x3FF0, 0x42B0, 0x4640, 0x4A20, 0x4D80, 0x5160, 0x54E0, 0x58D0, 0x5D30, 0x6120, 0x65A0, 0x69C0, 0x6DF0, 0x71B0, + 0x75F0, 0x78D0, 0x7BD0, 0x7DF0, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F10, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F70, 0x7F20, 0x7EF0, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7EB0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EB0, + 0x7EA0, 0x7ED0, 0x7F30, 0x7F30, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7F40, 0x7ED0, 0x7F00, 0x7EF0, 0x7F30, 0x7F30, 0x7E70, + 0x7ED0, 0x7EE0, 0x7F10, 0x7F30, 0x7E70, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F00, + 0x7F10, 0x7F10, 0x7F30, 0x7F00, 0x7F40, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, + 0x7F10, 0x7F00, 0x7F20, 0x7F80, 0x7EF0, 0x7EB0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7EB0, + 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, + 0x7EF0, 0x7F00, 0x7F00, 0x7EE0, 0x7F50, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F70, 0x7F10, + 0x7F10, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7F00, 0x7EF0, 0x7EB0, 0x7F60, 0x7EF0, 0x7E90, 0x7EE0, 0x7EE0, 0x7F50, 0x7F20, 0x7EA0, + 0x7ED0, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, + 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F50, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, + 0x7F10, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F10, 0x7EE0, 0x7F60, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7EC0, + 0x7F10, 0x7F10, 0x7EF0, 0x7E10, 0x7D30, 0x7D20, 0x7CC0, 0x7BF0, 0x7B60, 0x7A00, 0x7880, 0x76B0, 0x7500, 0x73E0, 0x7230, 0x71B0, + 0x7170, 0x7110, 0x7190, 0x7250, 0x7340, 0x74C0, 0x7630, 0x7840, 0x7A40, 0x7BD0, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F00, + 0x7F30, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F90, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F70, + 0x7F20, 0x7ED0, 0x7EB0, 0x7EE0, 0x7F50, 0x7F10, 0x7E70, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F10, 0x7F10, + 0x7E90, 0x7EB0, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7EE0, + 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, + 0x7EF0, 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F40, 0x7F10, + 0x7E00, 0x6EE0, 0x5E70, 0x4C30, 0x3BC0, 0x2A90, 0x1AD0, 0x0C00, 0xFDC0, 0xF090, 0xE300, 0xD590, 0xC750, 0xB980, 0xACE0, 0xA110, + 0x9730, 0x8F50, 0x8A50, 0x8800, 0x8720, 0x86E0, 0x8710, 0x8790, 0x8860, 0x89A0, 0x8B10, 0x8D40, 0x9030, 0x9460, 0x9930, 0x9CF0, + 0xA100, 0xA460, 0xA700, 0xA990, 0xAC70, 0xAF40, 0xB1C0, 0xB410, 0xB540, 0xB630, 0xB770, 0xB830, 0xB8C0, 0xB980, 0xBA50, 0xBB00, + 0xBAB0, 0xBAC0, 0xBA80, 0xBAC0, 0xBB40, 0xBB80, 0xBC20, 0xBB80, 0xBAE0, 0xBB40, 0xBC40, 0xBDE0, 0xBFB0, 0xC200, 0xC4E0, 0xC770, + 0xCA80, 0xCDB0, 0xD180, 0xD5E0, 0xDA20, 0xDE40, 0xE340, 0xE830, 0xEE00, 0xF3F0, 0xF9D0, 0xFF90, 0x0370, 0x07A0, 0x0B50, 0x0F30, + 0x1320, 0x1660, 0x1990, 0x1D30, 0x2070, 0x2390, 0x2670, 0x2980, 0x2C00, 0x2DF0, 0x30A0, 0x3260, 0x3440, 0x3710, 0x3830, 0x3A80, + 0x3B50, 0x3AF0, 0x3930, 0x3660, 0x32D0, 0x2F00, 0x2A60, 0x24F0, 0x1ED0, 0x1840, 0x1140, 0x0A10, 0x03F0, 0xFDE0, 0xF840, 0xF120, + 0xEA90, 0xE440, 0xDE80, 0xDB10, 0xD860, 0xD840, 0xD990, 0xDC70, 0xE0E0, 0xE680, 0xED30, 0xF520, 0xFD40, 0x06C0, 0x0FD0, 0x18F0, + 0x2340, 0x2E30, 0x38E0, 0x4440, 0x4F40, 0x5A50, 0x63B0, 0x6D20, 0x7550, 0x7C10, 0x7EE0, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, + 0x7E90, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7F10, 0x7F20, 0x7EA0, 0x7A80, 0x7600, 0x6F60, 0x6880, 0x6180, 0x59A0, + 0x5220, 0x4B70, 0x44D0, 0x3F50, 0x3960, 0x3380, 0x2ED0, 0x2AA0, 0x2840, 0x2510, 0x2270, 0x1FA0, 0x1C00, 0x1880, 0x1330, 0x0E50, + 0x0990, 0x06D0, 0x05E0, 0x0780, 0x0BB0, 0x11B0, 0x1900, 0x20F0, 0x27B0, 0x2CF0, 0x3160, 0x34B0, 0x3890, 0x3C00, 0x3F60, 0x4310, + 0x44A0, 0x4550, 0x4360, 0x3FA0, 0x3AF0, 0x35D0, 0x3040, 0x2B90, 0x2880, 0x2560, 0x22C0, 0x20D0, 0x1F30, 0x1E30, 0x1E80, 0x2030, + 0x2200, 0x2470, 0x2650, 0x2840, 0x29C0, 0x2B00, 0x2B80, 0x2BF0, 0x2BC0, 0x2AD0, 0x2980, 0x2870, 0x2700, 0x25B0, 0x2450, 0x2310, + 0x2230, 0x2160, 0x20E0, 0x2140, 0x2220, 0x2340, 0x2490, 0x25E0, 0x27A0, 0x2970, 0x2BB0, 0x2D40, 0x2F90, 0x3190, 0x3380, 0x35E0, + 0x3800, 0x3A80, 0x3C70, 0x3E90, 0x3FF0, 0x4130, 0x42B0, 0x4480, 0x4680, 0x4890, 0x4A20, 0x4AF0, 0x4B10, 0x4B50, 0x4B20, 0x4B80, + 0x4BF0, 0x4CB0, 0x4D70, 0x4D80, 0x4CD0, 0x4C70, 0x4C80, 0x4C80, 0x4CD0, 0x4C40, 0x4B40, 0x4910, 0x4680, 0x43B0, 0x4150, 0x3EB0, + 0x3C10, 0x3940, 0x3640, 0x32F0, 0x2F30, 0x2B30, 0x27D0, 0x24B0, 0x21A0, 0x1EA0, 0x1C10, 0x1A30, 0x1870, 0x1730, 0x1650, 0x1490, + 0x1270, 0x0F70, 0x0C70, 0x09E0, 0x0760, 0x05D0, 0x03F0, 0x0230, 0xFF20, 0xFC40, 0xF9F0, 0xF730, 0xF580, 0xF390, 0xF180, 0xEF20, + 0xEC20, 0xE9C0, 0xE7A0, 0xE4C0, 0xE230, 0xDE90, 0xDB00, 0xD860, 0xD680, 0xD530, 0xD510, 0xD470, 0xD340, 0xD210, 0xD130, 0xD090, + 0xD0C0, 0xD270, 0xD4A0, 0xD7C0, 0xDB80, 0xDEF0, 0xE140, 0xE3C0, 0xE5F0, 0xE7A0, 0xE870, 0xE8F0, 0xE8B0, 0xE7C0, 0xE800, 0xE890, + 0xE990, 0xEBB0, 0xEDC0, 0xF030, 0xF250, 0xF440, 0xF6D0, 0xF900, 0xFB20, 0xFC80, 0xFD60, 0xFE80, 0xFFF0, 0x0160, 0x02C0, 0x0300, + 0x0230, 0xFFA0, 0xFC10, 0xF7F0, 0xF480, 0xF140, 0xED70, 0xEA30, 0xE6A0, 0xE2C0, 0xDDB0, 0xD910, 0xD4F0, 0xD0A0, 0xCC90, 0xC8F0, + 0xC5E0, 0xC2F0, 0xC0B0, 0xBEA0, 0xBD50, 0xBC20, 0xBA40, 0xB920, 0xB7C0, 0xB780, 0xB850, 0xB880, 0xB8C0, 0xB880, 0xB7C0, 0xB6C0, + 0xB590, 0xB580, 0xB570, 0xB560, 0xB5B0, 0xB520, 0xB4F0, 0xB460, 0xB450, 0xB590, 0xB630, 0xB820, 0xB890, 0xB960, 0xBAA0, 0xBC50, + 0xBEB0, 0xC180, 0xC4C0, 0xC700, 0xC950, 0xCBD0, 0xCDC0, 0xCF30, 0xD100, 0xD1F0, 0xD220, 0xD1B0, 0xD090, 0xCFF0, 0xCF90, 0xD060, + 0xD0E0, 0xD190, 0xD280, 0xD320, 0xD400, 0xD560, 0xD710, 0xDAC0, 0xDE50, 0xE3C0, 0xE9B0, 0xF0E0, 0xF9C0, 0x0340, 0x0DA0, 0x1960, + 0x2600, 0x32B0, 0x3E80, 0x49C0, 0x53D0, 0x5B90, 0x61F0, 0x65C0, 0x6750, 0x6860, 0x6920, 0x6AD0, 0x6BF0, 0x6DC0, 0x6FE0, 0x7150, + 0x73F0, 0x7720, 0x7B90, 0x7EB0, 0x7F00, 0x7EE0, 0x7ED0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, + 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F20, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F00, 0x78C0, 0x7080, 0x6710, 0x5CB0, 0x5190, + 0x44E0, 0x3890, 0x2B30, 0x1EB0, 0x1280, 0x06F0, 0xFC90, 0xF390, 0xED60, 0xE8F0, 0xE600, 0xE520, 0xE560, 0xE650, 0xE780, 0xE8A0, + 0xEA50, 0xEB10, 0xECB0, 0xEEF0, 0xF180, 0xF470, 0xF670, 0xF8E0, 0xFBF0, 0xFF00, 0x02A0, 0x05D0, 0x0A10, 0x0DD0, 0x10A0, 0x1320, + 0x14B0, 0x1520, 0x1510, 0x1340, 0x1150, 0x0EA0, 0x0A70, 0x0630, 0x00F0, 0xFAE0, 0xF360, 0xE830, 0xDC40, 0xCE30, 0xC080, 0xB3B0, + 0xA830, 0x9EF0, 0x97B0, 0x9410, 0x93E0, 0x9690, 0x9C00, 0xA280, 0xA8E0, 0xAE50, 0xB160, 0xB2F0, 0xB220, 0xB030, 0xAD20, 0xA890, + 0xA250, 0x99F0, 0x8F70, 0x8840, 0x8590, 0x8500, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, + 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8460, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, + 0x8470, 0x8470, 0x8470, 0x84A0, 0x8470, 0x8470, 0x84B0, 0x84B0, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8480, + 0x8490, 0x8490, 0x8490, 0x8490, 0x84C0, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84D0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84D0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, + 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84E0, 0x84C0, 0x84C0, 0x84F0, 0x84F0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84E0, 0x84D0, 0x84F0, 0x8510, 0x8550, 0x8590, 0x8630, 0x8780, 0x89D0, + 0x8E30, 0x9460, 0x9C00, 0xA330, 0xAAD0, 0xB320, 0xBB50, 0xC270, 0xC9B0, 0xD030, 0xD680, 0xDCB0, 0xE300, 0xE9C0, 0xEF80, 0xF710, + 0xFEC0, 0x0630, 0x0DD0, 0x1480, 0x1B20, 0x21D0, 0x2880, 0x3090, 0x39C0, 0x4240, 0x4B00, 0x52A0, 0x5A10, 0x6010, 0x6670, 0x6C70, + 0x71F0, 0x7870, 0x7CE0, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7ED0, + 0x7F10, 0x7F20, 0x7F50, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, + 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F50, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, + 0x7EE0, 0x7ED0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, + 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F40, 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, + 0x7F20, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7320, + 0x6620, 0x58D0, 0x4D30, 0x4270, 0x38C0, 0x2FF0, 0x26B0, 0x1D80, 0x1400, 0x0AD0, 0x0330, 0xFCC0, 0xF690, 0xF1B0, 0xEDD0, 0xE9D0, + 0xE550, 0xE060, 0xDB30, 0xD6C0, 0xD2F0, 0xD110, 0xD110, 0xD250, 0xD3A0, 0xD4E0, 0xD4C0, 0xD3E0, 0xD3A0, 0xD4C0, 0xD870, 0xDEF0, + 0xE560, 0xEA70, 0xEC00, 0xE9F0, 0xE440, 0xDD50, 0xD630, 0xD110, 0xCED0, 0xCF30, 0xD1B0, 0xD680, 0xDDE0, 0xE940, 0xF850, 0x0A70, + 0x1D60, 0x30B0, 0x3E50, 0x4620, 0x4840, 0x4650, 0x4130, 0x3BE0, 0x3760, 0x3450, 0x32A0, 0x3210, 0x3040, 0x2D80, 0x28A0, 0x21A0, + 0x18F0, 0x0F10, 0x0550, 0xFCC0, 0xF6B0, 0xF130, 0xEC40, 0xE6C0, 0xE010, 0xD920, 0xD270, 0xCC00, 0xC730, 0xC460, 0xC3A0, 0xC4D0, + 0xC7F0, 0xCC10, 0xD180, 0xD750, 0xDCD0, 0xE210, 0xE6B0, 0xEAD0, 0xEFB0, 0xF5E0, 0xFD20, 0x0410, 0x0AE0, 0x0FB0, 0x1330, 0x1490, + 0x1360, 0x0F20, 0x08F0, 0x00C0, 0xF700, 0xEDA0, 0xE5A0, 0xDEC0, 0xDA00, 0xD670, 0xD310, 0xD070, 0xCE20, 0xCB70, 0xC990, 0xC890, + 0xC7A0, 0xC750, 0xC650, 0xC5B0, 0xC500, 0xC4D0, 0xC4F0, 0xC500, 0xC580, 0xC580, 0xC620, 0xC720, 0xC820, 0xC9F0, 0xCC00, 0xCE60, + 0xD150, 0xD2E0, 0xD510, 0xD640, 0xD650, 0xD670, 0xD560, 0xD2A0, 0xCE80, 0xC800, 0xBFE0, 0xB550, 0xAAC0, 0xA050, 0x9580, 0x8C90, + 0x87E0, 0x8600, 0x8560, 0x8520, 0x8500, 0x84F0, 0x84F0, 0x84E0, 0x84F0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, + 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x84B0, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8490, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x84A0, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8490, 0x8480, 0x8470, 0x8480, 0x8490, + 0x8480, 0x8480, 0x84B0, 0x8490, 0x8480, 0x8480, 0x8410, 0x8480, 0x8480, 0x8490, 0x8490, 0x8480, 0x8490, 0x8460, 0x8490, 0x8480, + 0x84A0, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x8440, 0x84A0, 0x84A0, 0x84D0, 0x84A0, 0x84A0, 0x84A0, 0x84E0, + 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x8450, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, + 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x8500, 0x84E0, 0x8530, 0x8540, 0x8570, 0x85B0, 0x8610, 0x86F0, 0x8890, 0x8C10, 0x9300, + 0x9A20, 0xA190, 0xAA10, 0xB2F0, 0xBCE0, 0xC760, 0xD300, 0xDF70, 0xEE40, 0xFD40, 0x0B90, 0x18B0, 0x2300, 0x29E0, 0x2CF0, 0x2CB0, + 0x2C60, 0x2B00, 0x2BD0, 0x37E0, 0x3A70, 0x3CD0, 0x3D60, 0x3CE0, 0x3AD0, 0x38B0, 0x3A00, 0x4070, 0x5010, 0x63B0, 0x74C0, 0x7D50, + 0x7D70, 0x7470, 0x5FF0, 0x4380, 0x2730, 0x0B90, 0xF200, 0xDA60, 0xC240, 0xAB30, 0x93E0, 0x8720, 0x8500, 0x84C0, 0x8460, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, + 0x8480, 0x84A0, 0x84E0, 0x8540, 0x8730, 0x90F0, 0xA020, 0xAD80, 0xBA30, 0xC670, 0xD0B0, 0xD9F0, 0xDF10, 0xE050, 0xE010, 0xDDA0, + 0xDA90, 0xD7B0, 0xD4C0, 0xD180, 0xCCA0, 0xC650, 0xBE00, 0xB4D0, 0xAA00, 0x9D30, 0x8FB0, 0x8730, 0x8520, 0x84D0, 0x84A0, 0x8480, + 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, + 0x8400, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83E0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83C0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8420, 0x8420, 0x8420, 0x8450, 0x8430, 0x8430, + 0x8430, 0x8450, 0x8440, 0x8450, 0x8410, 0x8450, 0x8460, 0x8480, 0x8470, 0x8480, 0x8490, 0x84C0, 0x84F0, 0x85C0, 0x9040, 0xAD20, + 0xCAB0, 0xE560, 0xFEC0, 0x1780, 0x2E50, 0x4530, 0x5A40, 0x6D40, 0x7C90, 0x7F00, 0x7F10, 0x7F00, 0x7F30, 0x7F00, 0x7F40, 0x7F10, + 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, + 0x7F60, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7E90, 0x7EB0, 0x7EE0, 0x7F10, + 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F00, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F40, 0x7F20, 0x7F10, 0x7F20, + 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F50, 0x7860, 0x6CD0, 0x6210, 0x55B0, 0x4820, 0x3AD0, 0x2DB0, 0x2250, 0x18C0, + 0x11D0, 0x0DF0, 0x0D20, 0x0F10, 0x13F0, 0x1AB0, 0x2300, 0x2B90, 0x3570, 0x3F60, 0x48B0, 0x5250, 0x5C00, 0x66C0, 0x70D0, 0x7A90, + 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7EB0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F40, + 0x7F10, 0x7F80, 0x7F00, 0x7F20, 0x7EF0, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7F10, 0x7EF0, + 0x7F30, 0x7F00, 0x7EE0, 0x7ED0, 0x7EF0, 0x7F20, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F10, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F00, + 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7980, + 0x6EC0, 0x61F0, 0x5490, 0x4880, 0x3E20, 0x34F0, 0x2D90, 0x28A0, 0x2420, 0x1F10, 0x1980, 0x12A0, 0x0B80, 0x0470, 0xFDA0, 0xF850, + 0xF450, 0xF0D0, 0xECD0, 0xE8E0, 0xE3D0, 0xDEB0, 0xDA60, 0xD510, 0xD100, 0xCD50, 0xC9E0, 0xC7B0, 0xC5D0, 0xC5F0, 0xC730, 0xC9C0, + 0xCE10, 0xD210, 0xD5A0, 0xD990, 0xDD40, 0xE0B0, 0xE420, 0xE780, 0xEB10, 0xEF20, 0xF280, 0xF580, 0xF7B0, 0xF8A0, 0xF8E0, 0xF6D0, + 0xF3F0, 0xF1E0, 0xEF80, 0xEDD0, 0xEBC0, 0xE940, 0xE640, 0xE370, 0xDFD0, 0xDD10, 0xDA40, 0xD8A0, 0xD730, 0xD620, 0xD560, 0xD510, + 0xD500, 0xD600, 0xD800, 0xDB10, 0xDDF0, 0xE0F0, 0xE3E0, 0xE6A0, 0xEA10, 0xED20, 0xF080, 0xF3F0, 0xF740, 0xFA10, 0xFDA0, 0x01E0, + 0x0610, 0x0AB0, 0x0E60, 0x10F0, 0x13D0, 0x15B0, 0x1870, 0x1AD0, 0x1D20, 0x1FA0, 0x20A0, 0x2190, 0x21B0, 0x21B0, 0x2160, 0x2030, + 0x1FB0, 0x1F40, 0x1D40, 0x1C70, 0x1B60, 0x1AC0, 0x1A30, 0x1930, 0x1860, 0x1730, 0x15E0, 0x1520, 0x14A0, 0x14F0, 0x1550, 0x15E0, + 0x1610, 0x1600, 0x1770, 0x18A0, 0x1A50, 0x1D50, 0x2030, 0x2320, 0x25B0, 0x27B0, 0x2A40, 0x2C70, 0x2F90, 0x3370, 0x3650, 0x39D0, + 0x3CD0, 0x4030, 0x4340, 0x4630, 0x4970, 0x4C00, 0x4EF0, 0x50D0, 0x5220, 0x5440, 0x55C0, 0x5730, 0x57C0, 0x5770, 0x57B0, 0x5700, + 0x5720, 0x5780, 0x5710, 0x5780, 0x5780, 0x5730, 0x56C0, 0x5680, 0x5780, 0x5890, 0x59B0, 0x5A40, 0x5A50, 0x5A90, 0x5A60, 0x5A50, + 0x5AB0, 0x5A60, 0x5B40, 0x5B90, 0x5B30, 0x5B70, 0x5B70, 0x5DB0, 0x5F60, 0x60E0, 0x6280, 0x6390, 0x6520, 0x6700, 0x68D0, 0x6B90, + 0x6DE0, 0x7090, 0x7290, 0x7470, 0x7760, 0x7950, 0x7BD0, 0x7E20, 0x7F00, 0x7F10, 0x7EA0, 0x7EE0, 0x7F10, 0x7F10, 0x7F10, 0x7EA0, + 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, + 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EF0, 0x7F20, 0x7F10, 0x7F80, 0x7F00, + 0x7ED0, 0x7F10, 0x7F00, 0x7F30, 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7E90, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F20, 0x7F00, 0x7F00, 0x7F10, + 0x7F00, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, + 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, + 0x7EF0, 0x7E90, 0x7EF0, 0x7EE0, 0x7F50, 0x7F00, 0x7440, 0x3C80, 0x0310, 0xC930, 0x90A0, 0x84F0, 0x84A0, 0x8480, 0x8470, 0x8470, + 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x84A0, 0x8470, + 0x8470, 0x8470, 0x8460, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84E0, 0x84F0, 0x8550, 0x8720, 0x92F0, 0xA780, 0xB6C0, + 0xC2F0, 0xCA30, 0xCE00, 0xCC70, 0xC790, 0xC030, 0xB690, 0xAB30, 0x9F80, 0x9470, 0x8BC0, 0x8750, 0x85D0, 0x8540, 0x8500, 0x84E0, + 0x84B0, 0x84A0, 0x8480, 0x8480, 0x8470, 0x8470, 0x8450, 0x8460, 0x8450, 0x8450, 0x8440, 0x8410, 0x8440, 0x8430, 0x8430, 0x8430, + 0x8420, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8520, 0x8560, 0x8600, 0x8740, 0x8A70, 0x9170, 0x9A40, + 0xA170, 0xA890, 0xAD80, 0xB1E0, 0xB450, 0xB5E0, 0xB560, 0xB360, 0xB050, 0xAD90, 0xAB80, 0xACC0, 0xB160, 0xB9A0, 0xC3D0, 0xCF10, + 0xD8B0, 0xDF10, 0xE300, 0xE4E0, 0xE640, 0xE7D0, 0xEA60, 0xEF40, 0xF460, 0xFA90, 0x0240, 0x0800, 0x0DD0, 0x1280, 0x1660, 0x1980, + 0x1C70, 0x2080, 0x2460, 0x2890, 0x2D30, 0x3260, 0x3840, 0x3E10, 0x4370, 0x48E0, 0x4CE0, 0x50B0, 0x5400, 0x55F0, 0x5850, 0x5A00, + 0x5C00, 0x5DC0, 0x5E10, 0x5F10, 0x5E40, 0x5B90, 0x5830, 0x52A0, 0x4B60, 0x4290, 0x38A0, 0x2D20, 0x2050, 0x13B0, 0x0500, 0xF6C0, + 0xE8B0, 0xDAA0, 0xCD70, 0xC0A0, 0xB480, 0xA9D0, 0xA090, 0x9910, 0x9470, 0x91F0, 0x9180, 0x91E0, 0x9440, 0x9770, 0x9BC0, 0xA110, + 0xA6F0, 0xAD40, 0xB410, 0xB9F0, 0xC0E0, 0xC780, 0xCE10, 0xD3F0, 0xD8B0, 0xDD70, 0xE150, 0xE5A0, 0xE940, 0xEC70, 0xF030, 0xF280, + 0xF540, 0xF850, 0xFB70, 0xFEE0, 0x0280, 0x05B0, 0x0940, 0x0CD0, 0x1200, 0x15E0, 0x1950, 0x1CB0, 0x20D0, 0x2500, 0x2940, 0x2DD0, + 0x3200, 0x3640, 0x3A70, 0x3F30, 0x4360, 0x4800, 0x4D50, 0x52F0, 0x5860, 0x5D70, 0x6240, 0x6720, 0x6BE0, 0x7060, 0x7530, 0x79A0, + 0x7CE0, 0x7ED0, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, + 0x7F20, 0x7F10, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, + 0x7F40, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F20, 0x7A60, 0x73F0, 0x6DA0, 0x6800, 0x61D0, + 0x5BB0, 0x5670, 0x5160, 0x4D40, 0x4A00, 0x46A0, 0x4370, 0x40B0, 0x3DD0, 0x3B60, 0x38A0, 0x3610, 0x33B0, 0x31B0, 0x2F70, 0x2C90, + 0x29B0, 0x2660, 0x22E0, 0x1F50, 0x1B70, 0x1760, 0x13E0, 0x0FB0, 0x0BE0, 0x0900, 0x0570, 0x01B0, 0xFE00, 0xFAA0, 0xF690, 0xF3F0, + 0xF0E0, 0xEE90, 0xEBF0, 0xE870, 0xE470, 0xE040, 0xDC50, 0xD830, 0xD4A0, 0xD130, 0xCEE0, 0xCBD0, 0xC8C0, 0xC5B0, 0xC280, 0xBF90, + 0xBD50, 0xBA50, 0xB7B0, 0xB500, 0xB220, 0xAF60, 0xABE0, 0xA920, 0xA590, 0xA240, 0x9EC0, 0x9A50, 0x96D0, 0x92A0, 0x8ED0, 0x8B60, + 0x88F0, 0x8770, 0x8690, 0x8600, 0x85B0, 0x8580, 0x8550, 0x8530, 0x8520, 0x8520, 0x8510, 0x8510, 0x8520, 0x8520, 0x8530, 0x8530, + 0x8530, 0x8540, 0x8550, 0x8550, 0x8560, 0x8570, 0x8570, 0x8570, 0x8580, 0x8570, 0x8580, 0x8590, 0x85B0, 0x85D0, 0x85F0, 0x8610, + 0x8630, 0x8640, 0x8670, 0x8670, 0x8680, 0x86C0, 0x86F0, 0x8720, 0x8740, 0x8760, 0x87B0, 0x87C0, 0x87F0, 0x8810, 0x8850, 0x8890, + 0x88D0, 0x8980, 0x8A10, 0x8AF0, 0x8BF0, 0x8D20, 0x8F10, 0x9140, 0x93B0, 0x96F0, 0x9A00, 0x9CF0, 0x9F50, 0xA0F0, 0xA340, 0xA550, + 0xA7A0, 0xA9C0, 0xAC10, 0xAEB0, 0xB040, 0xB2E0, 0xB4A0, 0xB6D0, 0xB8F0, 0xBB90, 0xBE50, 0xC160, 0xC450, 0xC710, 0xC960, 0xCBF0, + 0xCE50, 0xD030, 0xD270, 0xD390, 0xD5D0, 0xD7E0, 0xD990, 0xDBF0, 0xDDA0, 0xDEB0, 0xDFF0, 0xE040, 0xE010, 0xE000, 0xDFD0, 0xE010, + 0xE070, 0xE110, 0xE150, 0xE110, 0xE0C0, 0xE0A0, 0xE090, 0xE0C0, 0xE110, 0xE180, 0xE130, 0xE160, 0xE0E0, 0xE070, 0xDF50, 0xDEC0, + 0xDE50, 0xDE90, 0xDEA0, 0xDF20, 0xDEF0, 0xDF90, 0xE0E0, 0xE250, 0xE480, 0xE720, 0xE8C0, 0xE970, 0xEAB0, 0xEC00, 0xED90, 0xF010, + 0xF300, 0xF670, 0xFBB0, 0x0110, 0x07E0, 0x0DF0, 0x1410, 0x1A80, 0x1F60, 0x22F0, 0x2650, 0x2930, 0x2C40, 0x2F10, 0x31D0, 0x33B0, + 0x3300, 0x3110, 0x2D30, 0x27A0, 0x1FF0, 0x17F0, 0x0F60, 0x0400, 0xF710, 0xE8D0, 0xD810, 0xC500, 0xAE90, 0x9320, 0x8610, 0x84D0, + 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8430, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8460, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8450, 0x8430, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, + 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8540, 0x8520, 0x8530, 0x8510, 0x8570, 0x85B0, 0x8630, 0x8690, 0x8740, 0x8860, 0x8A70, 0x8C40, + 0x8DE0, 0x8EF0, 0x8F90, 0x90A0, 0x9280, 0x9560, 0x98A0, 0x9B60, 0x9D70, 0x9F70, 0xA130, 0xA360, 0xA4B0, 0xA5F0, 0xA720, 0xA870, + 0xA9F0, 0xAC80, 0xB0B0, 0xB610, 0xBBD0, 0xC210, 0xC880, 0xCF70, 0xD7A0, 0xDFF0, 0xE9E0, 0xF4A0, 0x01A0, 0x1000, 0x1E20, 0x2D40, + 0x3CF0, 0x4D70, 0x5D00, 0x6AF0, 0x7750, 0x7E80, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7ED0, 0x7ED0, 0x7EB0, 0x7F30, 0x7EF0, 0x7EB0, + 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, 0x7F10, 0x7F10, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, + 0x7F40, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, + 0x7F10, 0x7EF0, 0x7EE0, 0x7F30, 0x7EE0, 0x7F00, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7EF0, 0x7F00, 0x7F50, 0x7EF0, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F90, 0x7F20, 0x7F00, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x7EE0, 0x7EE0, + 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7E00, 0x5DF0, + 0x3E20, 0x2360, 0x0C00, 0xF7D0, 0xE790, 0xDB20, 0xD3D0, 0xD090, 0xD190, 0xD4C0, 0xD790, 0xD9F0, 0xD890, 0xD360, 0xCA10, 0xBDE0, + 0xB1F0, 0xA550, 0x9A70, 0x92E0, 0x8D50, 0x8980, 0x8770, 0x8640, 0x85B0, 0x8580, 0x8590, 0x8600, 0x8730, 0x8B20, 0x9440, 0x9CE0, + 0xA200, 0xA3D0, 0xA310, 0x9F40, 0x9980, 0x9360, 0x8D30, 0x8950, 0x86F0, 0x85E0, 0x8570, 0x8530, 0x8510, 0x84F0, 0x84E0, 0x84D0, + 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x8510, 0x85E0, 0x8AE0, 0x9D60, 0xB050, 0xC290, 0xD5B0, + 0xE610, 0xF420, 0xFE80, 0x0550, 0x0690, 0x0460, 0xFEE0, 0xF7E0, 0xF2A0, 0xF100, 0xF450, 0xFC10, 0x0730, 0x1420, 0x20E0, 0x2C10, + 0x3480, 0x39F0, 0x3D30, 0x3E70, 0x3F00, 0x3F40, 0x3FB0, 0x4190, 0x42A0, 0x44C0, 0x46B0, 0x4920, 0x4C80, 0x5000, 0x53E0, 0x5800, + 0x5B40, 0x5E00, 0x5F00, 0x5F80, 0x5E50, 0x5A70, 0x5420, 0x49E0, 0x3C50, 0x2C90, 0x1B20, 0x0980, 0xF630, 0xE550, 0xD5C0, 0xC750, + 0xBA70, 0xAFD0, 0xA680, 0x9F20, 0x9920, 0x94C0, 0x9200, 0x90D0, 0x9070, 0x90B0, 0x9200, 0x93C0, 0x95F0, 0x9930, 0x9E10, 0xA4C0, + 0xAD90, 0xB850, 0xC490, 0xD320, 0xE4D0, 0xF620, 0x07C0, 0x19C0, 0x2A30, 0x38A0, 0x4570, 0x4F90, 0x57F0, 0x5F40, 0x6470, 0x68B0, + 0x6C00, 0x6E10, 0x6FB0, 0x7030, 0x7070, 0x7120, 0x7190, 0x7200, 0x7290, 0x7290, 0x7170, 0x6FC0, 0x6DC0, 0x6C30, 0x6B70, 0x6C10, + 0x6E70, 0x72B0, 0x7790, 0x7C20, 0x7EE0, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7C70, 0x7480, 0x6AC0, 0x5F10, 0x5230, 0x44D0, 0x3810, + 0x2B70, 0x1EA0, 0x1390, 0x0890, 0xFDB0, 0xF3E0, 0xEB00, 0xE390, 0xDD30, 0xD790, 0xD1D0, 0xCCB0, 0xC7E0, 0xC2E0, 0xBE70, 0xBA70, + 0xB6B0, 0xB3B0, 0xB110, 0xADF0, 0xAB90, 0xA910, 0xA720, 0xA4F0, 0xA3C0, 0xA230, 0xA250, 0xA3D0, 0xA7E0, 0xAC90, 0xB2F0, 0xB9D0, + 0xC1A0, 0xC910, 0xD140, 0xD930, 0xE140, 0xEA50, 0xF330, 0xFC70, 0x0560, 0x0EC0, 0x1780, 0x1FC0, 0x2790, 0x2F50, 0x3700, 0x3DE0, + 0x44D0, 0x4B50, 0x5160, 0x5600, 0x59C0, 0x5C30, 0x5D80, 0x5E10, 0x5E10, 0x5D50, 0x5B40, 0x58E0, 0x5580, 0x51E0, 0x4DB0, 0x4970, + 0x4470, 0x4030, 0x3CA0, 0x3880, 0x3490, 0x3160, 0x2E20, 0x2B50, 0x2980, 0x27F0, 0x2710, 0x2530, 0x23D0, 0x20E0, 0x1D40, 0x1850, + 0x12D0, 0x0D00, 0x0600, 0xFED0, 0xF780, 0xF060, 0xE940, 0xE190, 0xDAD0, 0xD400, 0xCD50, 0xC660, 0xC0C0, 0xBB80, 0xB6E0, 0xB320, + 0xB070, 0xAD70, 0xAAC0, 0xA830, 0xA630, 0xA4E0, 0xA400, 0xA3E0, 0xA380, 0xA350, 0xA2C0, 0xA300, 0xA310, 0xA370, 0xA4B0, 0xA580, + 0xA5F0, 0xA660, 0xA6C0, 0xA740, 0xA7C0, 0xA820, 0xA8A0, 0xA9A0, 0xAA90, 0xAB50, 0xAC30, 0xACB0, 0xAE40, 0xB020, 0xB1A0, 0xB370, + 0xB590, 0xB7F0, 0xBAE0, 0xBE90, 0xC230, 0xC5A0, 0xC920, 0xCBC0, 0xCF80, 0xD280, 0xD6C0, 0xDAB0, 0xDEF0, 0xE2A0, 0xE5A0, 0xE990, + 0xED00, 0xF140, 0xF530, 0xF870, 0xFB60, 0xFD80, 0xFFD0, 0x0260, 0x04A0, 0x07D0, 0x0B00, 0x0D60, 0x0ED0, 0x0F80, 0x10B0, 0x1160, + 0x1150, 0x1190, 0x1100, 0x1070, 0x0FB0, 0x0F70, 0x0EC0, 0x0E40, 0x0E60, 0x0D60, 0x0CE0, 0x0C50, 0x0B20, 0x0B20, 0x0B90, 0x0BF0, + 0x0C70, 0x0C60, 0x0C80, 0x0D30, 0x0E20, 0x0F90, 0x10A0, 0x1230, 0x1360, 0x13D0, 0x1600, 0x1700, 0x1920, 0x1B30, 0x1CB0, 0x1E40, + 0x1F10, 0x2070, 0x21F0, 0x2420, 0x2790, 0x2A90, 0x2DF0, 0x3010, 0x3330, 0x36E0, 0x3A40, 0x3F40, 0x4580, 0x4B60, 0x5240, 0x5880, + 0x5E80, 0x6440, 0x6910, 0x6FB0, 0x75E0, 0x7BE0, 0x7ED0, 0x7F20, 0x7F00, 0x7EF0, 0x7F90, 0x7F20, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, + 0x7EE0, 0x7ED0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F10, 0x7EC0, 0x7EB0, 0x7EB0, 0x7EF0, 0x7EF0, + 0x7EB0, 0x7F00, 0x7F20, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7ED0, 0x7F30, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, + 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F50, + 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, + 0x7EB0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, + 0x7F50, 0x7C30, 0x6F70, 0x5F80, 0x4DD0, 0x3A30, 0x2520, 0x1040, 0xFB70, 0xE900, 0xD840, 0xC9F0, 0xBD30, 0xB480, 0xAE20, 0xA930, + 0xA750, 0xA620, 0xA5D0, 0xA4D0, 0xA3B0, 0xA260, 0xA0E0, 0xA080, 0xA0A0, 0xA1E0, 0xA3B0, 0xA6F0, 0xAA90, 0xAFC0, 0xB590, 0xBB30, + 0xC1A0, 0xC740, 0xCD30, 0xD220, 0xD680, 0xD930, 0xDA20, 0xD950, 0xD820, 0xD590, 0xD370, 0xD050, 0xCD90, 0xCBA0, 0xCA40, 0xC900, + 0xCA00, 0xCB70, 0xCDF0, 0xD140, 0xD4B0, 0xD860, 0xDB30, 0xDE00, 0xE160, 0xE5B0, 0xEAD0, 0xEFC0, 0xF560, 0xFB50, 0x0100, 0x0730, + 0x0CC0, 0x1220, 0x1850, 0x1E50, 0x25F0, 0x2D90, 0x37E0, 0x4270, 0x4D50, 0x5990, 0x6520, 0x6F60, 0x7790, 0x7D70, 0x7EF0, 0x7F10, + 0x7F30, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7C10, 0x6CC0, 0x5B60, 0x47F0, 0x3430, 0x1F70, 0x0BC0, 0xF880, 0xE670, + 0xD660, 0xC5C0, 0xB700, 0xA960, 0x9B50, 0x8EC0, 0x87F0, 0x85B0, 0x8510, 0x84F0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, + 0x84A0, 0x8490, 0x8490, 0x8470, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84C0, + 0x84E0, 0x8530, 0x8620, 0x89F0, 0x9440, 0x9D20, 0xA120, 0xA050, 0x9B40, 0x9190, 0x8910, 0x85C0, 0x8500, 0x84D0, 0x84C0, 0x84B0, + 0x8490, 0x84B0, 0x84A0, 0x84B0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, + 0x8500, 0x8520, 0x8540, 0x8580, 0x85E0, 0x8690, 0x8800, 0x8B90, 0x9410, 0xA290, 0xB290, 0xC3E0, 0xD610, 0xE710, 0xF680, 0x0360, + 0x0CC0, 0x1350, 0x1640, 0x16F0, 0x1490, 0x0FF0, 0x0920, 0x01C0, 0xFA70, 0xF3B0, 0xEDE0, 0xE890, 0xE480, 0xE0A0, 0xDC40, 0xD690, + 0xCFB0, 0xC750, 0xBE00, 0xB2F0, 0xA7C0, 0x9E70, 0x95B0, 0x8E30, 0x8980, 0x8700, 0x85E0, 0x8550, 0x8510, 0x84F0, 0x84E0, 0x84D0, + 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84F0, 0x8500, 0x8510, 0x8510, 0x8520, 0x8540, 0x8550, 0x8580, 0x85A0, 0x85C0, 0x85A0, 0x8560, 0x8520, 0x84F0, 0x84C0, 0x84B0, + 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8460, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8420, 0x8470, 0x8420, 0x83F0, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x84C0, 0x8480, 0x8490, + 0x8480, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8510, 0x8590, 0x86E0, 0x8B70, 0x9610, 0xA0B0, 0xADF0, 0xB8A0, 0xC300, 0xCE20, + 0xDAB0, 0xE990, 0xF9D0, 0x0AC0, 0x1C10, 0x2C30, 0x3A60, 0x4410, 0x4AB0, 0x4F40, 0x5220, 0x5480, 0x56F0, 0x5A30, 0x5DA0, 0x6090, + 0x62B0, 0x63A0, 0x63D0, 0x62F0, 0x6280, 0x6320, 0x6560, 0x6A50, 0x7160, 0x79C0, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7D00, 0x7540, 0x6E50, 0x6830, 0x63E0, + 0x61D0, 0x61D0, 0x63C0, 0x67B0, 0x6AB0, 0x6D50, 0x6EA0, 0x6C70, 0x6570, 0x5920, 0x4780, 0x3480, 0x20A0, 0x1180, 0x05E0, 0xFE00, + 0xF890, 0xF520, 0xF200, 0xEE10, 0xEA10, 0xE710, 0xE670, 0xE890, 0xEE40, 0xF880, 0x06F0, 0x1870, 0x2B20, 0x3E20, 0x51B0, 0x6230, + 0x7040, 0x7B90, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7840, 0x68F0, 0x5730, 0x4330, 0x3000, 0x1EC0, 0x0FF0, 0x0800, 0x0440, 0x03F0, 0x0530, + 0x06A0, 0x08E0, 0x0C90, 0x12F0, 0x1EA0, 0x2DB0, 0x3EB0, 0x4D20, 0x5640, 0x57D0, 0x5310, 0x4AB0, 0x42C0, 0x3DB0, 0x3CF0, 0x40A0, + 0x46D0, 0x4D80, 0x5420, 0x59A0, 0x5EE0, 0x6330, 0x67A0, 0x6A80, 0x6D70, 0x7010, 0x71F0, 0x73C0, 0x74B0, 0x7530, 0x7520, 0x74D0, + 0x7370, 0x72A0, 0x7340, 0x7580, 0x7850, 0x7BE0, 0x7E40, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F70, 0x7F10, 0x7E90, 0x7F20, 0x7F20, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F40, 0x7F10, 0x7F00, 0x7EC0, 0x7E90, 0x7EB0, 0x7EB0, + 0x7F00, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F00, 0x7F20, 0x7EE0, 0x7F10, + 0x7D30, 0x6D60, 0x5DF0, 0x4DC0, 0x3C90, 0x2A50, 0x1940, 0x08B0, 0xFB90, 0xF0F0, 0xEB50, 0xE9C0, 0xEBC0, 0xF100, 0xF7B0, 0xFD60, + 0x01A0, 0x03F0, 0x0710, 0x09C0, 0x0DC0, 0x1250, 0x1630, 0x1A60, 0x1C30, 0x1DE0, 0x1F00, 0x2090, 0x2550, 0x2BB0, 0x3520, 0x4060, + 0x4C70, 0x56A0, 0x5B60, 0x5990, 0x4DB0, 0x37E0, 0x1BD0, 0xFD30, 0xE170, 0xCAD0, 0xBD10, 0xB630, 0xB300, 0xB1A0, 0xB110, 0xB0B0, + 0xB060, 0xB150, 0xB450, 0xB820, 0xBD40, 0xC2D0, 0xC8B0, 0xCE30, 0xD340, 0xD580, 0xD770, 0xD800, 0xD7F0, 0xD850, 0xDA10, 0xDCA0, + 0xE050, 0xE4F0, 0xE970, 0xECD0, 0xF060, 0xF270, 0xF450, 0xF690, 0xF8B0, 0xFCA0, 0xFF40, 0x0230, 0x05B0, 0x0810, 0x0A30, 0x0AB0, + 0x0A40, 0x0A40, 0x0910, 0x08A0, 0x08C0, 0x0840, 0x0980, 0x0A00, 0x0B10, 0x0B80, 0x0BE0, 0x0CC0, 0x0D40, 0x0D90, 0x0E60, 0x0F50, + 0x1010, 0x1090, 0x1260, 0x13F0, 0x15B0, 0x1850, 0x1A70, 0x1C30, 0x1F70, 0x22A0, 0x2740, 0x2BD0, 0x2FF0, 0x3540, 0x3910, 0x3DF0, + 0x41F0, 0x45D0, 0x4990, 0x4CB0, 0x50E0, 0x53D0, 0x5590, 0x5700, 0x55C0, 0x5430, 0x5070, 0x4A90, 0x4390, 0x3B30, 0x32E0, 0x2A40, + 0x2210, 0x1BF0, 0x1600, 0x11D0, 0x0E90, 0x0C40, 0x0AE0, 0x0A10, 0x09B0, 0x09D0, 0x0870, 0x07B0, 0x0600, 0x03E0, 0x0190, 0xFEC0, + 0xFBC0, 0xF800, 0xF3F0, 0xEF30, 0xE920, 0xE2D0, 0xDCB0, 0xD670, 0xD060, 0xC9D0, 0xC330, 0xBB90, 0xB2C0, 0xA970, 0x9FD0, 0x9800, + 0x9120, 0x8D10, 0x8B30, 0x8A90, 0x8B30, 0x8D30, 0x8FA0, 0x9340, 0x9670, 0x98B0, 0x9530, 0x93C0, 0x9230, 0x90E0, 0x8F90, 0x8E40, + 0x8CD0, 0x8B20, 0x8990, 0x8870, 0x87C0, 0x8760, 0x8710, 0x86E0, 0x86C0, 0x86B0, 0x8690, 0x8680, 0x8670, 0x8670, 0x8670, 0x8670, + 0x8690, 0x86D0, 0x8750, 0x8820, 0x8980, 0x8C30, 0x8FC0, 0x9360, 0x9670, 0x98F0, 0x9AE0, 0x9C20, 0x9E70, 0xA0B0, 0xA3A0, 0xA6D0, + 0xAA30, 0xADE0, 0xB150, 0xB430, 0xB6B0, 0xBA10, 0xBDA0, 0xC250, 0xC750, 0xCCC0, 0xD220, 0xD790, 0xDD00, 0xE240, 0xE8F0, 0xEF30, + 0xF5B0, 0xFD10, 0x02F0, 0x08F0, 0x0F40, 0x1610, 0x1D20, 0x23F0, 0x2BE0, 0x32D0, 0x3A60, 0x4080, 0x4670, 0x4C70, 0x5170, 0x57C0, + 0x5D90, 0x6330, 0x69E0, 0x7030, 0x7620, 0x7BA0, 0x7E90, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F00, 0x7F10, + 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F70, 0x7DF0, 0x7AA0, 0x78E0, 0x7790, 0x76B0, 0x7720, 0x7800, 0x7A50, + 0x7CE0, 0x7E90, 0x7ED0, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F30, 0x7F20, + 0x7F40, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, + 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F10, 0x7F10, 0x7E90, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7E60, 0x6E40, 0x5F50, 0x50B0, 0x4120, 0x3380, 0x2680, 0x1A60, 0x0F90, + 0x06B0, 0x0010, 0xFB20, 0xF8F0, 0xF950, 0xFB60, 0x0000, 0x0580, 0x0D30, 0x1500, 0x1D10, 0x2600, 0x2D80, 0x3460, 0x3A10, 0x3EB0, + 0x42A0, 0x4580, 0x47F0, 0x49A0, 0x4B80, 0x4D80, 0x4E80, 0x4EF0, 0x4F80, 0x4F70, 0x4EC0, 0x4BE0, 0x47B0, 0x4290, 0x3CA0, 0x3720, + 0x3080, 0x2930, 0x21B0, 0x18D0, 0x1130, 0x0930, 0x0250, 0xFCD0, 0xF850, 0xF430, 0xF060, 0xEC40, 0xE8E0, 0xE540, 0xE050, 0xDAE0, + 0xD330, 0xCAD0, 0xC1C0, 0xB8D0, 0xB030, 0xA770, 0x9FD0, 0x9880, 0x9210, 0x8D30, 0x89A0, 0x87C0, 0x86A0, 0x8600, 0x85A0, 0x8550, + 0x8520, 0x8500, 0x84F0, 0x84E0, 0x84C0, 0x84C0, 0x84B0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, + 0x8430, 0x8420, 0x8410, 0x8400, 0x83F0, 0x83D0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83D0, 0x83C0, 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83C0, + 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8410, 0x8430, 0x8430, 0x8450, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x84B0, 0x8520, 0x8C20, 0xB580, 0xDB30, 0xFF20, + 0x2000, 0x3EC0, 0x5B10, 0x7540, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7EF0, 0x6CD0, 0x57F0, 0x4040, 0x2350, 0x0660, 0xE7E0, 0xC930, 0xAB30, 0x9050, 0x8620, 0x84F0, 0x84C0, + 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84D0, 0x8530, 0x8B10, 0xB130, + 0xD720, 0xFD70, 0x24E0, 0x46E0, 0x6470, 0x7BB0, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7EB0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F40, 0x7EF0, 0x7F20, 0x7F00, 0x7ED0, + 0x7ED0, 0x7EE0, 0x7F40, 0x7EF0, 0x7F10, 0x7F60, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F40, + 0x7F10, 0x7ED0, 0x7F00, 0x7F00, 0x7F40, 0x7F10, 0x7EB0, 0x7EE0, 0x7F10, 0x7F30, 0x7EC0, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x6740, + 0x4E00, 0x32E0, 0x1A10, 0x0050, 0xE860, 0xD1C0, 0xBF40, 0xAF10, 0xA280, 0x9840, 0x8F10, 0x89B0, 0x8730, 0x8610, 0x85A0, 0x8580, + 0x8590, 0x85D0, 0x8670, 0x8810, 0x8B40, 0x90E0, 0x98E0, 0xA1C0, 0xAB30, 0xB520, 0xBE60, 0xC6E0, 0xCFD0, 0xD750, 0xDDC0, 0xE2F0, + 0xE7D0, 0xEBF0, 0xF080, 0xF490, 0xF970, 0x0080, 0x07D0, 0x1250, 0x1E90, 0x2CB0, 0x3B80, 0x4800, 0x50B0, 0x5160, 0x4610, 0x30B0, + 0x0F40, 0xE7A0, 0xBCA0, 0x92C0, 0x8540, 0x84C0, 0x84A0, 0x8490, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, + 0x8480, 0x84A0, 0x84B0, 0x8580, 0x94C0, 0xB5F0, 0xCF30, 0xDFF0, 0xE7D0, 0xE6E0, 0xDF90, 0xD4B0, 0xC960, 0xC170, 0xBF00, 0xC210, + 0xCB50, 0xD960, 0xEC20, 0xFF70, 0x1580, 0x2C90, 0x4550, 0x5F60, 0x7720, 0x7F30, 0x7ED0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, + 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x62D0, 0x3D80, 0x1500, 0xE850, 0xB7B0, 0x8880, 0x84C0, 0x8480, + 0x8460, 0x8460, 0x8440, 0x8440, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x84A0, 0x84D0, 0x8560, 0x8D30, 0xAD50, + 0xC890, 0xE290, 0xF6F0, 0x06B0, 0x1460, 0x1D40, 0x2450, 0x2990, 0x2C30, 0x2CC0, 0x2A00, 0x2500, 0x1670, 0x1970, 0x1D30, 0x2020, + 0x2360, 0x2450, 0x2590, 0x2600, 0x2640, 0x2840, 0x2A10, 0x2D40, 0x2F90, 0x3230, 0x3500, 0x3800, 0x3B80, 0x3FB0, 0x4370, 0x48A0, + 0x4D50, 0x52A0, 0x56E0, 0x58F0, 0x59B0, 0x5720, 0x52E0, 0x4DD0, 0x49B0, 0x4740, 0x4630, 0x46B0, 0x46E0, 0x4690, 0x46C0, 0x46D0, + 0x4720, 0x4810, 0x4AE0, 0x4E60, 0x5280, 0x5770, 0x5C90, 0x6120, 0x6440, 0x6250, 0x59B0, 0x4910, 0x3390, 0x1BF0, 0x0580, 0xF350, + 0xE710, 0xE020, 0xDEF0, 0xE1A0, 0xE850, 0xF1A0, 0xFB90, 0x06B0, 0x1100, 0x19C0, 0x2190, 0x2880, 0x2FA0, 0x3770, 0x3EB0, 0x4660, + 0x4C40, 0x50D0, 0x54B0, 0x57E0, 0x5D40, 0x6280, 0x67E0, 0x6C80, 0x6FD0, 0x7230, 0x7270, 0x71A0, 0x6FC0, 0x6C80, 0x6920, 0x6410, + 0x5FF0, 0x5C70, 0x58A0, 0x5690, 0x5470, 0x5330, 0x52F0, 0x5340, 0x54B0, 0x5870, 0x5E50, 0x6580, 0x6C20, 0x7300, 0x77C0, 0x7910, + 0x7870, 0x7390, 0x6CB0, 0x6260, 0x54C0, 0x44C0, 0x3190, 0x1C80, 0x0500, 0xEB50, 0xD0A0, 0xB700, 0x9E00, 0x8A40, 0x8550, 0x84E0, + 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x8500, 0x8550, 0x8680, 0x8B90, 0x9990, 0xA650, + 0xB160, 0xBA90, 0xC260, 0xC970, 0xD0D0, 0xD8B0, 0xE030, 0xE780, 0xEBE0, 0xEE70, 0xEF60, 0xEE10, 0xEBF0, 0xE7A0, 0xE0C0, 0xD850, + 0xCB20, 0xBD70, 0xAD70, 0x9CA0, 0x8CD0, 0x8620, 0x84F0, 0x84C0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, + 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, + 0x84C0, 0x84F0, 0x8590, 0x8970, 0x9C30, 0xAEB0, 0xC120, 0xD070, 0xDDD0, 0xEA10, 0xF560, 0x0060, 0x0D90, 0x1D00, 0x2F60, 0x44B0, + 0x5970, 0x6C60, 0x7B80, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, + 0x7EE0, 0x7EB0, 0x7F00, 0x7EE0, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7F00, + 0x7EC0, 0x7F30, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, + 0x7F70, 0x7F00, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, + 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F00, + 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F40, + 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, + 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F00, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F30, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7FB0, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7ED0, 0x7EF0, 0x7F20, 0x7F40, 0x7F40, 0x7EB0, + 0x7F00, 0x7F00, 0x7F30, 0x7F30, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F20, 0x7F00, 0x7ED0, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, 0x7E90, 0x7EE0, + 0x7EE0, 0x7EF0, 0x7F20, 0x7E80, 0x7ED0, 0x7F00, 0x7F20, 0x7F10, 0x7EC0, 0x7F10, 0x7F00, 0x7F10, 0x7F00, 0x7EC0, 0x7F00, 0x7F10, + 0x7F20, 0x7F40, 0x7F00, 0x7F50, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F50, 0x7F00, 0x7F20, + 0x7F00, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F00, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EB0, 0x7E70, 0x7F10, + 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7EE0, 0x7F40, 0x7F10, + 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7EF0, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F20, + 0x7EF0, 0x7EF0, 0x7F60, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7E30, 0x7B00, 0x7790, 0x73F0, 0x7180, 0x6ED0, 0x6CB0, + 0x6A30, 0x6720, 0x65C0, 0x64D0, 0x6540, 0x6640, 0x67B0, 0x69F0, 0x6CA0, 0x6F90, 0x72B0, 0x7570, 0x7920, 0x7BC0, 0x7E60, 0x7EE0, + 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, + 0x7F20, 0x7F20, 0x7F70, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7E90, 0x7F00, + 0x7EE0, 0x7EF0, 0x7EB0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F20, 0x7EF0, + 0x7F10, 0x7F30, 0x7F20, 0x7F80, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F80, 0x7EC0, 0x7F10, + 0x7F10, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, 0x7F60, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F90, 0x7F20, + 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, 0x7ED0, 0x7DB0, 0x7C00, 0x7A40, 0x78F0, 0x77B0, 0x75E0, 0x74E0, 0x73B0, 0x72E0, 0x7310, 0x7290, + 0x7370, 0x7400, 0x7440, 0x75C0, 0x7630, 0x7760, 0x7890, 0x79E0, 0x7BE0, 0x7C90, 0x7E00, 0x7EB0, 0x7EE0, 0x7EF0, 0x7EA0, 0x7F00, + 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F00, + 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7ED0, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7E90, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, + 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F30, 0x7600, 0x5D80, 0x4380, + 0x2940, 0x1040, 0xF810, 0xE1B0, 0xCBF0, 0xB770, 0xA0B0, 0x8CC0, 0x85B0, 0x84E0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8410, 0x8430, 0x8430, 0x8430, 0x8460, 0x8430, 0x8430, + 0x8430, 0x8440, 0x8430, 0x8430, 0x8460, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, + 0x8430, 0x8430, 0x8450, 0x8430, 0x8420, 0x8410, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, + 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8430, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8460, 0x8440, 0x8460, 0x8460, + 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8470, 0x8430, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8440, 0x8440, 0x8480, 0x8460, 0x8460, 0x84B0, 0x8490, 0x84A0, 0x84D0, 0x8530, 0x8810, 0x9CB0, 0xB390, 0xC420, 0xCD90, 0xCF10, + 0xC810, 0xB9A0, 0xA4F0, 0x8FB0, 0x8660, 0x8500, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8460, 0x8450, 0x83E0, + 0x8430, 0x8420, 0x8420, 0x8420, 0x8430, 0x8460, 0x8440, 0x8460, 0x8480, 0x84A0, 0x84F0, 0x85B0, 0x8950, 0x9530, 0xA2D0, 0xB180, + 0xC2A0, 0xD230, 0xDF20, 0xE770, 0xEA10, 0xE6A0, 0xDAE0, 0xC4C0, 0xA010, 0x8550, 0x84A0, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8490, 0x84D0, 0x8780, 0xB350, 0xDE50, 0x0290, 0x2130, + 0x3B80, 0x5290, 0x67D0, 0x7AA0, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x62D0, 0x5B20, 0x57B0, + 0x5910, 0x5DE0, 0x6420, 0x6AC0, 0x7130, 0x7720, 0x7BC0, 0x7EB0, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7F10, 0x7EA0, 0x7F20, 0x7EF0, 0x7EF0, 0x7EE0, 0x7E80, 0x7EF0, 0x7F20, 0x7F00, + 0x7F00, 0x7E80, 0x7EB0, 0x7EA0, 0x7F10, 0x7EB0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F30, 0x7F00, 0x7F90, 0x7F20, 0x7F40, 0x7F10, + 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F80, 0x7F00, 0x7EE0, 0x7D60, 0x7C80, 0x7CB0, 0x7D70, 0x7E40, 0x7ED0, 0x7EE0, + 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7ED0, 0x7EB0, 0x7F00, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F00, + 0x7ED0, 0x7300, 0x6700, 0x5A10, 0x4D10, 0x42B0, 0x3B40, 0x3840, 0x3980, 0x3E70, 0x4800, 0x5140, 0x59E0, 0x6160, 0x66F0, 0x6B30, + 0x6D30, 0x6E30, 0x6E40, 0x6CB0, 0x6BA0, 0x6940, 0x6790, 0x66E0, 0x67A0, 0x6B10, 0x7050, 0x7730, 0x7E40, 0x7F10, 0x7F00, 0x7EF0, + 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F60, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7EF0, 0x7EF0, + 0x7EB0, 0x7EC0, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F40, 0x72E0, 0x5EA0, 0x4960, 0x33D0, 0x2090, + 0x0CC0, 0xFBD0, 0xEDB0, 0xE260, 0xD960, 0xD380, 0xD030, 0xCF90, 0xD060, 0xD340, 0xD5C0, 0xD7C0, 0xD940, 0xDAB0, 0xDC30, 0xDE20, + 0xDF50, 0xE0B0, 0xE160, 0xE2C0, 0xE430, 0xE4B0, 0xE610, 0xE6D0, 0xE790, 0xE780, 0xE670, 0xE550, 0xE460, 0xE460, 0xE500, 0xE530, + 0xE820, 0xEB60, 0xF110, 0xF870, 0x01C0, 0x0BD0, 0x1710, 0x2300, 0x2FC0, 0x3CC0, 0x4A80, 0x5720, 0x6340, 0x6F20, 0x7820, 0x7E70, + 0x7F10, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F80, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F10, + 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F60, 0x7EE0, 0x7E90, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, + 0x7EE0, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F40, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F20, + 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F00, 0x7F00, + 0x7E60, 0x7AB0, 0x7740, 0x7380, 0x6F90, 0x6C70, 0x6960, 0x66F0, 0x64D0, 0x6310, 0x6100, 0x5E50, 0x5A30, 0x56E0, 0x52F0, 0x5090, + 0x4D60, 0x4980, 0x46A0, 0x41F0, 0x3F40, 0x3BE0, 0x3810, 0x34B0, 0x30A0, 0x2CC0, 0x28C0, 0x2500, 0x21E0, 0x1FC0, 0x1E30, 0x1CC0, + 0x1A80, 0x1850, 0x1620, 0x1440, 0x1240, 0x1010, 0x0F20, 0x0E00, 0x0DB0, 0x0D20, 0x0C60, 0x0CF0, 0x0CC0, 0x0BF0, 0x0B10, 0x0AD0, + 0x0B10, 0x0B20, 0x0BC0, 0x0C50, 0x0CA0, 0x0D70, 0x0DF0, 0x0F30, 0x10E0, 0x1360, 0x17B0, 0x1CB0, 0x2130, 0x25F0, 0x2AC0, 0x3100, + 0x3770, 0x3D50, 0x4400, 0x49A0, 0x4F50, 0x53D0, 0x56F0, 0x5AA0, 0x5CC0, 0x5FB0, 0x6260, 0x63C0, 0x65D0, 0x6700, 0x67C0, 0x6850, + 0x68D0, 0x69F0, 0x6A80, 0x6B10, 0x6C90, 0x6E60, 0x7170, 0x7450, 0x77D0, 0x7B20, 0x7D80, 0x7F10, 0x7F20, 0x7F80, 0x7F10, 0x7F10, + 0x7EF0, 0x7EF0, 0x7F80, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7F70, 0x7F10, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F00, 0x7EE0, 0x7EE0, + 0x7ED0, 0x7F30, 0x7F20, 0x7E60, 0x7CD0, 0x7B30, 0x7990, 0x78D0, 0x77B0, 0x77E0, 0x7820, 0x78C0, 0x7A90, 0x7C00, 0x7D20, 0x7E60, + 0x7EE0, 0x7F10, 0x7EC0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F20, + 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F80, 0x7EF0, 0x7EB0, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, + 0x7F10, 0x7F30, 0x7EE0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, + 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F40, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7F00, 0x7F10, + 0x7F30, 0x7EF0, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F90, 0x7F20, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EE0, + 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F00, 0x7F20, + 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7ED0, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7F00, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, + 0x7F20, 0x7F00, 0x7F40, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7B50, 0x75B0, 0x6EF0, 0x6880, 0x61E0, 0x5B70, + 0x5540, 0x4FB0, 0x4CD0, 0x4BB0, 0x4D20, 0x5180, 0x56A0, 0x5D60, 0x6350, 0x6870, 0x6B50, 0x6AE0, 0x66C0, 0x5EB0, 0x5270, 0x4490, + 0x3600, 0x27E0, 0x1B00, 0x1030, 0x06C0, 0xFE80, 0xF520, 0xEA50, 0xDF60, 0xD460, 0xC950, 0xBED0, 0xB670, 0xAFE0, 0xAAE0, 0xA7D0, + 0xA520, 0xA3D0, 0xA240, 0xA050, 0x9DB0, 0x99A0, 0x9510, 0x9020, 0x8C80, 0x8A30, 0x8930, 0x88F0, 0x8940, 0x89A0, 0x8AA0, 0x8C10, + 0x8DF0, 0x90F0, 0x9530, 0x99C0, 0x9ED0, 0xA340, 0xA770, 0xABD0, 0xAF50, 0xB370, 0xB790, 0xBBA0, 0xBF60, 0xC2B0, 0xC580, 0xC840, + 0xCAA0, 0xCD40, 0xCFD0, 0xD220, 0xD3D0, 0xD530, 0xD640, 0xD800, 0xD9D0, 0xDBF0, 0xDDD0, 0xDFB0, 0xE040, 0xE090, 0xE0D0, 0xE140, + 0xE180, 0xE200, 0xE2A0, 0xE1D0, 0xE0D0, 0xE060, 0xE070, 0xE080, 0xE090, 0xE0B0, 0xE0C0, 0xE080, 0xDFD0, 0xDFF0, 0xE070, 0xE190, + 0xE230, 0xE2D0, 0xE3C0, 0xE450, 0xE470, 0xE5A0, 0xE640, 0xE660, 0xE540, 0xE300, 0xE090, 0xDE10, 0xDBF0, 0xDA50, 0xD8C0, 0xD600, + 0xD2A0, 0xCDB0, 0xC900, 0xC530, 0xC260, 0xBF40, 0xBBB0, 0xB850, 0xB4D0, 0xB0F0, 0xAE50, 0xAC50, 0xAA20, 0xA780, 0xA410, 0xA0E0, + 0x9DE0, 0x9B80, 0x9A10, 0x98C0, 0x97C0, 0x95C0, 0x9340, 0x90A0, 0x8E30, 0x8C50, 0x8B00, 0x89F0, 0x8900, 0x8850, 0x87C0, 0x8730, + 0x86D0, 0x8690, 0x8660, 0x8620, 0x8620, 0x85C0, 0x8590, 0x8570, 0x8560, 0x8550, 0x8540, 0x8530, 0x8520, 0x8520, 0x8510, 0x8510, + 0x8510, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84D0, + 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84C0, 0x84B0, 0x84C0, + 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84C0, 0x84E0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84B0, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84D0, 0x84F0, 0x84F0, 0x8500, + 0x8500, 0x8510, 0x8530, 0x8540, 0x8560, 0x8590, 0x85D0, 0x8600, 0x8660, 0x86B0, 0x8740, 0x87D0, 0x8860, 0x88E0, 0x8940, 0x89C0, + 0x8A50, 0x8B60, 0x8C10, 0x8C90, 0x8D10, 0x8D60, 0x8E00, 0x8E30, 0x8E90, 0x8F30, 0x8FC0, 0x8FE0, 0x9020, 0x9090, 0x9130, 0x9200, + 0x92F0, 0x93F0, 0x9480, 0x9520, 0x95C0, 0x96F0, 0x9920, 0x9BB0, 0x9E30, 0xA070, 0xA320, 0xA640, 0xAA80, 0xAF70, 0xB550, 0xBC70, + 0xC400, 0xCBD0, 0xD3F0, 0xDBF0, 0xE460, 0xEC60, 0xF3D0, 0xFCD0, 0x0360, 0x0930, 0x0E50, 0x11E0, 0x1520, 0x16D0, 0x1870, 0x18F0, + 0x1890, 0x1770, 0x14A0, 0x10A0, 0x0BD0, 0x05B0, 0xFF30, 0xF6C0, 0xEC90, 0xE1C0, 0xD680, 0xCA50, 0xBDB0, 0xB070, 0xA360, 0x95F0, + 0x8B20, 0x8670, 0x8520, 0x84F0, 0x84D0, 0x84C0, 0x84A0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8460, 0x8440, 0x8450, 0x8440, + 0x8430, 0x8420, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, + 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8460, + 0x8430, 0x8430, 0x8460, 0x8420, 0x8430, 0x8410, 0x8410, 0x8420, 0x8420, 0x8410, 0x8420, 0x8420, 0x8420, 0x8450, 0x8430, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8450, 0x8470, 0x8460, 0x8470, 0x8480, 0x8480, 0x8490, 0x84B0, + 0x84D0, 0x8500, 0x8570, 0x86C0, 0x89E0, 0x8EE0, 0x93C0, 0x97E0, 0x9B80, 0x9EF0, 0xA0F0, 0xA310, 0xA510, 0xA780, 0xAAD0, 0xB070, + 0xB820, 0xC330, 0xD0C0, 0xE1D0, 0xF3A0, 0x07F0, 0x19F0, 0x2AC0, 0x3BA0, 0x4BF0, 0x5C70, 0x6C30, 0x79E0, 0x7EF0, 0x7F00, 0x7F60, + 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7EA0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, + 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7F60, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F00, 0x7F20, 0x7F10, 0x7EF0, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, + 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x72A0, 0x5FE0, 0x4B50, 0x3610, 0x1FE0, 0x0900, 0xF3D0, 0xE030, 0xD020, 0xC2C0, 0xB930, 0xB2F0, + 0xAD90, 0xA750, 0xA110, 0x99C0, 0x92A0, 0x8BD0, 0x87D0, 0x8630, 0x8580, 0x8510, 0x84F0, 0x8510, 0x84C0, 0x84B0, 0x84A0, 0x84A0, + 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8490, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8480, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84A0, 0x8500, 0x84D0, + 0x84E0, 0x8500, 0x8530, 0x85B0, 0x86D0, 0x8A30, 0x9240, 0x9B80, 0xA4D0, 0xADB0, 0xB690, 0xBF90, 0xC8E0, 0xD2F0, 0xDE10, 0xE8D0, + 0xF3D0, 0xFF30, 0x0B00, 0x1640, 0x20F0, 0x2C30, 0x3660, 0x4050, 0x48D0, 0x4F50, 0x56F0, 0x5BC0, 0x5FA0, 0x62B0, 0x64A0, 0x65C0, + 0x6690, 0x6750, 0x6760, 0x6720, 0x66E0, 0x6650, 0x6620, 0x6690, 0x67D0, 0x6990, 0x6C80, 0x70E0, 0x75B0, 0x7B10, 0x7EB0, 0x7F30, + 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7D20, + 0x6AF0, 0x5A30, 0x49D0, 0x39F0, 0x2B30, 0x1D30, 0x0F40, 0x0270, 0xF660, 0xEBA0, 0xE220, 0xDB70, 0xD6D0, 0xD400, 0xD280, 0xD130, + 0xCF80, 0xCD00, 0xCA20, 0xC6C0, 0xC320, 0xBFD0, 0xBDA0, 0xBAF0, 0xB8A0, 0xB6A0, 0xB490, 0xB260, 0xB090, 0xAEB0, 0xACD0, 0xAB20, + 0xA8A0, 0xA5B0, 0xA110, 0x9AF0, 0x9470, 0x8E50, 0x8A00, 0x8790, 0x86B0, 0x8650, 0x8660, 0x8690, 0x8710, 0x87C0, 0x88B0, 0x89E0, + 0x8BB0, 0x8D90, 0x9070, 0x93C0, 0x9890, 0x9E40, 0xA560, 0xADD0, 0xB7A0, 0xC3A0, 0xCF90, 0xDCA0, 0xE9F0, 0xF7D0, 0x0600, 0x14A0, + 0x22C0, 0x3180, 0x4130, 0x4FC0, 0x5D90, 0x6A10, 0x7560, 0x7DF0, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7EF0, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7EB0, 0x7F20, + 0x7F40, 0x7F30, 0x7F10, 0x7EC0, 0x7F10, 0x7EF0, 0x7EB0, 0x7EE0, 0x7E80, 0x7ED0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F00, 0x7F20, 0x7F00, + 0x7F10, 0x7F30, 0x7EE0, 0x7F50, 0x7F00, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7F20, 0x7F10, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EF0, + 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7EF0, 0x7E70, 0x7ED0, + 0x7ED0, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7EF0, + 0x7EE0, 0x7EF0, 0x7F60, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7EA0, 0x7EF0, + 0x7B50, 0x7430, 0x6DC0, 0x6710, 0x6260, 0x5F60, 0x5CD0, 0x5B50, 0x5760, 0x5140, 0x4800, 0x3C50, 0x2FA0, 0x2150, 0x1510, 0x09D0, + 0xFF80, 0xF750, 0xEFB0, 0xE830, 0xDFE0, 0xD550, 0xC7F0, 0xB990, 0xA850, 0x96E0, 0x89C0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x85B0, 0x87B0, 0x8E00, + 0x97B0, 0xA1A0, 0xA970, 0xB020, 0xB5B0, 0xBA70, 0xBD10, 0xBE20, 0xBCB0, 0xBA80, 0xB6B0, 0xB320, 0xB060, 0xAD40, 0xAA10, 0xA7E0, + 0xA660, 0xA5B0, 0xA5F0, 0xA7A0, 0xAA10, 0xAC70, 0xAF60, 0xB1A0, 0xB510, 0xB940, 0xBE10, 0xC340, 0xC800, 0xCC90, 0xD0C0, 0xD2D0, + 0xD550, 0xD680, 0xD6B0, 0xD5C0, 0xD400, 0xD1D0, 0xCEE0, 0xCCF0, 0xCB80, 0xCA20, 0xC910, 0xC730, 0xC4A0, 0xC120, 0xBD30, 0xBA20, + 0xB730, 0xB3D0, 0xB170, 0xAE00, 0x9E70, 0x9B90, 0x9900, 0x9670, 0x9380, 0x9150, 0x8F80, 0x8EB0, 0x8F00, 0x9060, 0x9350, 0x9720, + 0x9BB0, 0xA180, 0xA990, 0xB320, 0xBE60, 0xCB70, 0xD7F0, 0xE420, 0xF210, 0xFF90, 0x0D90, 0x1B00, 0x2740, 0x33F0, 0x40B0, 0x4D00, + 0x5850, 0x62B0, 0x6D60, 0x7660, 0x7D90, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, + 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F70, 0x7ED0, 0x7F10, 0x7F00, 0x7EE0, 0x7F80, 0x7EF0, 0x7EE0, + 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7EF0, 0x7F00, 0x7F20, 0x7ED0, 0x7EB0, 0x7F20, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, + 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F30, 0x7F00, + 0x7F00, 0x7EF0, 0x7F10, 0x7F80, 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x7EF0, + 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F00, 0x7EC0, 0x7EC0, 0x7ED0, 0x7E80, 0x7D60, 0x7B80, 0x7A10, + 0x7930, 0x7780, 0x7690, 0x7500, 0x7440, 0x73D0, 0x7350, 0x73B0, 0x7400, 0x7440, 0x74B0, 0x74A0, 0x75A0, 0x7680, 0x77F0, 0x79E0, + 0x7AD0, 0x7BF0, 0x7D10, 0x7DE0, 0x7E90, 0x7F00, 0x7F00, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, + 0x7F10, 0x7F20, 0x7F70, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EB0, 0x7F00, + 0x7F10, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7EF0, 0x7F20, 0x7EF0, 0x7E00, 0x7BB0, 0x79B0, 0x7780, 0x7610, 0x7460, 0x71E0, 0x6EF0, + 0x6C30, 0x6A40, 0x6800, 0x65D0, 0x6370, 0x6100, 0x5FA0, 0x5E10, 0x5C30, 0x5A80, 0x5790, 0x5570, 0x5330, 0x4FE0, 0x4D50, 0x49B0, + 0x46C0, 0x4400, 0x40F0, 0x3E60, 0x3C00, 0x3AD0, 0x3B50, 0x3CF0, 0x4040, 0x42C0, 0x45B0, 0x4800, 0x4A10, 0x4DB0, 0x5180, 0x5640, + 0x5AD0, 0x5E90, 0x62B0, 0x66A0, 0x6B30, 0x7030, 0x7460, 0x7950, 0x7D10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7F00, 0x7F00, + 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7EF0, 0x7F00, 0x7F30, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, + 0x7BF0, 0x69E0, 0x5A10, 0x48B0, 0x38A0, 0x29A0, 0x1BF0, 0x1100, 0x06A0, 0xFE40, 0xF690, 0xF0A0, 0xEAD0, 0xE770, 0xE550, 0xE3F0, + 0xE3F0, 0xE570, 0xE8C0, 0xECF0, 0xF220, 0xF780, 0xFC70, 0x00C0, 0x0410, 0x06C0, 0x0930, 0x0A30, 0x0AB0, 0x09F0, 0x0830, 0x04F0, + 0x00D0, 0xFAE0, 0xF3B0, 0xECE0, 0xE610, 0xE000, 0xD930, 0xD1D0, 0xC790, 0xB900, 0xA320, 0x8940, 0x84E0, 0x8490, 0x8470, 0x8450, + 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8430, 0x8440, 0x8460, 0x8470, 0x8490, 0x84C0, 0x84E0, 0x8500, 0x8520, 0x8550, 0x85E0, 0x8790, 0x8DE0, 0x9840, 0x9F50, + 0x9F10, 0x9950, 0x8F70, 0x8830, 0x8590, 0x8510, 0x84F0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84A0, 0x84C0, 0x84C0, 0x84D0, + 0x84F0, 0x8510, 0x8540, 0x85D0, 0x86F0, 0x8950, 0x8DC0, 0x9250, 0x96B0, 0x98B0, 0x99A0, 0x9900, 0x9720, 0x9540, 0x93B0, 0x92F0, + 0x9250, 0x9240, 0x9270, 0x9230, 0x9200, 0x9160, 0x90D0, 0x9090, 0x9000, 0x8FE0, 0x8FC0, 0x9060, 0x9080, 0x9100, 0x9060, 0x8F40, + 0x8DE0, 0x8BA0, 0x89A0, 0x8840, 0x8760, 0x86D0, 0x8650, 0x85F0, 0x85A0, 0x8590, 0x8530, 0x8510, 0x84F0, 0x84F0, 0x84E0, 0x84D0, + 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8470, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x84A0, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, + 0x8490, 0x84B0, 0x8490, 0x84A0, 0x8470, 0x84B0, 0x84C0, 0x84F0, 0x84E0, 0x8500, 0x8520, 0x8590, 0x85E0, 0x86F0, 0x88D0, 0x8CB0, + 0x91F0, 0x9760, 0x9D40, 0xA230, 0xA780, 0xACB0, 0xB180, 0xB540, 0xB8B0, 0xBB60, 0xBE80, 0xC1D0, 0xC5E0, 0xCA40, 0xCE50, 0xD300, + 0xD6E0, 0xDB10, 0xDF00, 0xE260, 0xE680, 0xE9F0, 0xED50, 0xF160, 0xF440, 0xF7D0, 0xFA30, 0xFCC0, 0xFD90, 0xFDF0, 0xFF10, 0x0020, + 0x0060, 0x00F0, 0x0020, 0xFEF0, 0xFCF0, 0xFA90, 0xF8A0, 0xF690, 0xF530, 0xF3E0, 0xF240, 0xF1E0, 0xEFF0, 0xEDE0, 0xEAF0, 0xE890, + 0xE770, 0xE560, 0xE490, 0xE410, 0xE400, 0xE420, 0xE350, 0xE360, 0xE3E0, 0xE3A0, 0xE520, 0xE700, 0xE960, 0xECC0, 0xF010, 0xF4C0, + 0xF900, 0xFEB0, 0x0430, 0x0A20, 0x1050, 0x1710, 0x1DF0, 0x25C0, 0x2C10, 0x33F0, 0x3BC0, 0x42F0, 0x4A10, 0x50E0, 0x5800, 0x5EF0, + 0x65E0, 0x6BA0, 0x7190, 0x76F0, 0x7BB0, 0x7EE0, 0x7EF0, 0x7EB0, 0x7EF0, 0x7F10, 0x7F70, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F30, + 0x7EE0, 0x7EC0, 0x7F20, 0x7F20, 0x7F40, 0x7ED0, 0x7EA0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F80, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, + 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F50, + 0x7F10, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7E80, 0x7EB0, 0x7F00, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, 0x7F10, 0x7F10, + 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F40, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, + 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7EE0, 0x7F10, 0x7F30, + 0x7F10, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, + 0x7F70, 0x7F10, 0x7EB0, 0x7F00, 0x7B90, 0x7530, 0x6F70, 0x68A0, 0x6210, 0x5A80, 0x5070, 0x4580, 0x3720, 0x28C0, 0x1940, 0x0770, + 0xF650, 0xE330, 0xD090, 0xBD80, 0xAB20, 0x9960, 0x8C70, 0x86D0, 0x8560, 0x8500, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, + 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8480, 0x8480, + 0x8480, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8490, 0x8480, 0x8480, 0x8480, 0x84B0, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8510, 0x8560, 0x85F0, 0x8770, 0x8B00, + 0x9250, 0x9AA0, 0xA1D0, 0xA910, 0xB020, 0xB760, 0xBED0, 0xC430, 0xC9A0, 0xCCF0, 0xD050, 0xD370, 0xD610, 0xD900, 0xDB50, 0xDD60, + 0xDF60, 0xE110, 0xE3D0, 0xE620, 0xE850, 0xEAF0, 0xED80, 0xF140, 0xF550, 0xF9D0, 0xFF40, 0x0490, 0x0A50, 0x10A0, 0x1570, 0x1AF0, + 0x1FD0, 0x25A0, 0x2B60, 0x3180, 0x37A0, 0x3D20, 0x42D0, 0x47D0, 0x4C10, 0x50E0, 0x5450, 0x57B0, 0x59A0, 0x5AF0, 0x5C50, 0x5D30, + 0x5E60, 0x5F80, 0x5F90, 0x6000, 0x5F40, 0x5EB0, 0x5E20, 0x5D60, 0x5D40, 0x5CF0, 0x5C30, 0x5C00, 0x5AF0, 0x5AE0, 0x5AC0, 0x59D0, + 0x5990, 0x5830, 0x56E0, 0x54C0, 0x5250, 0x5060, 0x4DC0, 0x4B90, 0x49D0, 0x47E0, 0x4790, 0x4780, 0x4910, 0x4B00, 0x4CF0, 0x4F30, + 0x5040, 0x5150, 0x5250, 0x53E0, 0x5700, 0x59C0, 0x5CD0, 0x5F20, 0x60D0, 0x6350, 0x6670, 0x6970, 0x6CE0, 0x7030, 0x7310, 0x74E0, + 0x76B0, 0x77E0, 0x7900, 0x7A00, 0x79D0, 0x7930, 0x77E0, 0x7590, 0x7350, 0x7070, 0x6DD0, 0x6A80, 0x6660, 0x62C0, 0x5E50, 0x59D0, + 0x55A0, 0x5020, 0x4B10, 0x45E0, 0x4000, 0x3A80, 0x3480, 0x2F00, 0x2A40, 0x2530, 0x20D0, 0x1BA0, 0x1680, 0x1190, 0x0C70, 0x08E0, + 0x0490, 0xFFF0, 0xFC30, 0xF870, 0xF4F0, 0xF200, 0xF040, 0xEEE0, 0xED80, 0xEE30, 0xEEE0, 0xEE40, 0xEEF0, 0xEF50, 0xF0A0, 0xF1F0, + 0xF3A0, 0xF590, 0xF790, 0xF9C0, 0xFC10, 0xFED0, 0x00E0, 0x02D0, 0x0450, 0x0610, 0x07A0, 0x0910, 0x0AF0, 0x0C00, 0x0CE0, 0x0DB0, + 0x0E80, 0x1030, 0x1260, 0x1510, 0x1750, 0x1950, 0x1A50, 0x1AF0, 0x1C20, 0x1DA0, 0x1F10, 0x20F0, 0x2300, 0x2560, 0x27F0, 0x2980, + 0x2B20, 0x2CD0, 0x2E10, 0x2EB0, 0x2EB0, 0x2E90, 0x2E30, 0x2DE0, 0x2DE0, 0x2E50, 0x2E70, 0x2E30, 0x2DD0, 0x2CB0, 0x2D00, 0x2C60, + 0x2B10, 0x29B0, 0x2800, 0x2620, 0x23F0, 0x2230, 0x21B0, 0x21E0, 0x2150, 0x21B0, 0x2250, 0x2350, 0x2450, 0x2560, 0x2680, 0x27D0, + 0x2910, 0x2A70, 0x2C00, 0x2E50, 0x3050, 0x31A0, 0x3310, 0x3410, 0x33B0, 0x3340, 0x3270, 0x3160, 0x3010, 0x2E70, 0x2C40, 0x29F0, + 0x2710, 0x2400, 0x20E0, 0x1DD0, 0x19E0, 0x1650, 0x1350, 0x1070, 0x0E70, 0x0CC0, 0x0C10, 0x0BB0, 0x0B00, 0x0A90, 0x0A70, 0x09A0, + 0x0900, 0x0870, 0x07A0, 0x06A0, 0x0500, 0x0350, 0x0040, 0xFD40, 0xFAD0, 0xF870, 0xF680, 0xF470, 0xF230, 0xEFD0, 0xECD0, 0xE990, + 0xE610, 0xE230, 0xDE90, 0xDA90, 0xD630, 0xD1D0, 0xCD00, 0xC880, 0xC3E0, 0xBF00, 0xBAE0, 0xB5E0, 0xB180, 0xAD70, 0xA960, 0xA5A0, + 0xA1B0, 0x9E60, 0x9B40, 0x9990, 0x9880, 0x98C0, 0x99D0, 0x9A80, 0x9B90, 0x9BF0, 0x9CB0, 0x9D80, 0x9EA0, 0xA090, 0xA2E0, 0xA530, + 0xA800, 0xAB10, 0xAD90, 0xB060, 0xB360, 0xB580, 0xB860, 0xBAA0, 0xBCA0, 0xBED0, 0xC180, 0xC400, 0xC6B0, 0xC790, 0xC7B0, 0xC7A0, + 0xC6F0, 0xC650, 0xC5F0, 0xC580, 0xC4E0, 0xC460, 0xC380, 0xC250, 0xC110, 0xBFB0, 0xBEE0, 0xBD80, 0xBC60, 0xBB30, 0xB950, 0xB7D0, + 0xB5C0, 0xB400, 0xB1F0, 0xAEF0, 0xAC60, 0xA970, 0xA6B0, 0xA350, 0x9FB0, 0x9BA0, 0x96A0, 0x9170, 0x8CB0, 0x8940, 0x8740, 0x8610, + 0x8580, 0x8540, 0x8510, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8480, 0x8470, 0x84A0, 0x8480, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84D0, 0x84F0, 0x8530, 0x85C0, 0x88C0, 0x90F0, 0x9CB0, + 0xA680, 0xB010, 0xB7D0, 0xBF50, 0xC530, 0xCA50, 0xCED0, 0xD200, 0xD530, 0xD7D0, 0xDA20, 0xDC90, 0xDE00, 0xDFE0, 0xE1A0, 0xE2E0, + 0xE510, 0xE6A0, 0xE7E0, 0xEA80, 0xEC30, 0xEEE0, 0xF1E0, 0xF3B0, 0xF660, 0xF840, 0xFA70, 0xFC30, 0xFE20, 0x00B0, 0x0310, 0x0690, + 0x0920, 0x0B50, 0x0D10, 0x0DA0, 0x0DC0, 0x0E00, 0x0D50, 0x0CC0, 0x0B10, 0x08F0, 0x0670, 0x0370, 0x0140, 0xFF50, 0xFDA0, 0xFCE0, + 0xFBD0, 0xFBB0, 0xFAA0, 0xF9D0, 0xF850, 0xF7B0, 0xF760, 0xF690, 0xF5E0, 0xF580, 0xF550, 0xF5C0, 0xF650, 0xF720, 0xF900, 0xFB30, + 0xFDC0, 0x00E0, 0x04B0, 0x08B0, 0x0CF0, 0x11C0, 0x1650, 0x1AB0, 0x1FA0, 0x24D0, 0x2A80, 0x2F60, 0x3410, 0x3A00, 0x3F30, 0x44A0, + 0x4A50, 0x4ED0, 0x5470, 0x5900, 0x5D50, 0x61E0, 0x65E0, 0x6A60, 0x6E10, 0x71B0, 0x7530, 0x7810, 0x7AB0, 0x7C70, 0x7E40, 0x7ED0, + 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F20, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, + 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F30, 0x7F20, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, + 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7EC0, + 0x7F40, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F50, + 0x7F00, 0x7F20, 0x7ED0, 0x7F10, 0x7F60, 0x7EE0, 0x7EC0, 0x7F10, 0x7EF0, 0x7F70, 0x7EF0, 0x7EB0, 0x7EC0, 0x7E10, 0x7CB0, 0x7C20, + 0x7B40, 0x7B50, 0x7AF0, 0x7AA0, 0x7AD0, 0x7A00, 0x79C0, 0x79E0, 0x7910, 0x76B0, 0x75B0, 0x74E0, 0x7400, 0x7280, 0x7220, 0x70C0, + 0x70D0, 0x70B0, 0x7070, 0x7110, 0x7100, 0x7290, 0x73B0, 0x7520, 0x77C0, 0x7A40, 0x7D00, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, + 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7E40, 0x79D0, 0x7530, 0x6FE0, 0x6A10, + 0x6330, 0x5C00, 0x5310, 0x48D0, 0x3DD0, 0x31E0, 0x25C0, 0x18F0, 0x0A20, 0xFBD0, 0xED10, 0xE000, 0xD360, 0xC7B0, 0xBCC0, 0xB2B0, + 0xA8A0, 0x9F30, 0x9660, 0x8E90, 0x8980, 0x86D0, 0x85B0, 0x8530, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, + 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8500, 0x8530, 0x8510, + 0x8510, 0x8520, 0x84F0, 0x8530, 0x8520, 0x8520, 0x84C0, 0x8500, 0x84F0, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x8490, 0x84F0, 0x84E0, + 0x84F0, 0x84D0, 0x84C0, 0x84C0, 0x84D0, 0x84B0, 0x8490, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8490, 0x8490, 0x84B0, + 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84C0, 0x84E0, 0x84B0, 0x84B0, 0x84F0, 0x84C0, 0x84D0, 0x84E0, 0x8510, 0x84E0, + 0x84F0, 0x84F0, 0x8510, 0x8520, 0x8530, 0x8550, 0x8560, 0x8570, 0x8580, 0x8590, 0x8590, 0x8580, 0x85A0, 0x8570, 0x8560, 0x8550, + 0x8550, 0x8530, 0x8530, 0x8520, 0x8510, 0x8510, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8510, 0x8530, + 0x8550, 0x85A0, 0x8640, 0x87B0, 0x8BD0, 0x94C0, 0x9FE0, 0xABE0, 0xB9E0, 0xC750, 0xD560, 0xE300, 0xF070, 0xFCD0, 0x08D0, 0x1400, + 0x1EE0, 0x2D30, 0x3940, 0x4620, 0x5270, 0x5E80, 0x69E0, 0x7410, 0x7CF0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x7F40, 0x7F30, + 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x76A0, 0x6B60, 0x5F90, 0x54E0, 0x4AC0, 0x4180, 0x39D0, 0x34D0, 0x3220, + 0x3180, 0x3200, 0x3230, 0x3140, 0x2E50, 0x29D0, 0x2520, 0x2070, 0x1CD0, 0x1990, 0x1640, 0x1320, 0x0F50, 0x0B00, 0x0630, 0x01F0, + 0xFC40, 0xF7D0, 0xF510, 0xF420, 0xF6B0, 0xFBF0, 0x01A0, 0x0680, 0x09D0, 0x0990, 0x0760, 0x0320, 0xFE00, 0xF920, 0xF5F0, 0xF3D0, + 0xF230, 0xF0D0, 0xEF70, 0xED90, 0xEBC0, 0xE9B0, 0xE810, 0xE660, 0xE600, 0xE700, 0xEA00, 0xED50, 0xEFF0, 0xEFC0, 0xEB60, 0xE230, + 0xD690, 0xC960, 0xBD40, 0xB230, 0xA9D0, 0xA460, 0x9FC0, 0x9D70, 0x9CD0, 0x9E30, 0xA000, 0xA2B0, 0xA640, 0xA910, 0xABF0, 0xAE80, + 0xB180, 0xB450, 0xB710, 0xB900, 0xBA50, 0xBAD0, 0xBB50, 0xBC60, 0xBD80, 0xBF70, 0xC2E0, 0xC6A0, 0xCA60, 0xCD20, 0xCF10, 0xCFA0, + 0xCE30, 0xCAF0, 0xC5B0, 0xBDB0, 0xB310, 0xA530, 0x9500, 0x8870, 0x8540, 0x84E0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, + 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8470, 0x8450, 0x8440, 0x8450, 0x8440, 0x8450, 0x8440, 0x8440, 0x83E0, 0x8440, 0x8440, + 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8430, 0x8460, 0x8440, 0x8440, 0x8440, 0x8460, 0x8440, 0x8440, 0x8430, 0x8440, + 0x8430, 0x8430, 0x83E0, 0x8430, 0x8430, 0x8430, 0x83E0, 0x8430, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8400, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8440, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8420, 0x8440, 0x8430, 0x8430, 0x83F0, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, + 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84F0, 0x8560, 0x8970, 0x94E0, 0x9C40, 0x9E50, 0x9C20, 0x95B0, + 0x8D60, 0x87C0, 0x8590, 0x8500, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8490, 0x84A0, 0x84A0, 0x84C0, 0x84F0, 0x8590, 0x8910, 0x9D10, 0xB280, 0xC670, 0xD860, 0xE820, 0xF510, 0x00E0, 0x0980, + 0x10C0, 0x1650, 0x1A60, 0x1D20, 0x2010, 0x2230, 0x2360, 0x2480, 0x24F0, 0x2520, 0x25A0, 0x2570, 0x2630, 0x2620, 0x2760, 0x2830, + 0x28E0, 0x2A40, 0x2B50, 0x2C90, 0x2E30, 0x3040, 0x3390, 0x3780, 0x3BF0, 0x4140, 0x4630, 0x4B80, 0x5060, 0x5510, 0x62C0, 0x6600, + 0x6880, 0x6A20, 0x6CC0, 0x6EC0, 0x7110, 0x7360, 0x75F0, 0x7910, 0x7B20, 0x7CA0, 0x7D80, 0x7E30, 0x7E70, 0x7EC0, 0x7F50, 0x7F10, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7ED0, 0x7ED0, 0x7EB0, 0x7F20, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, + 0x7ED0, 0x7F10, 0x7F00, 0x7F10, 0x7E90, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, + 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, + 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F70, 0x7EE0, 0x7E70, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7EB0, + 0x7F00, 0x7F20, 0x7F40, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F00, 0x7F30, + 0x7EE0, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, + 0x7EF0, 0x7F00, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7EF0, 0x7ED0, 0x7F30, 0x7F00, 0x7EA0, 0x7ED0, 0x7EE0, 0x6FC0, 0x5AB0, 0x4400, + 0x2E20, 0x1860, 0x03F0, 0xF230, 0xE1E0, 0xD330, 0xC790, 0xBDF0, 0xB780, 0xB330, 0xB1C0, 0xB440, 0xB9A0, 0xC1B0, 0xCD40, 0xDA90, + 0xE940, 0xF850, 0x07A0, 0x1580, 0x2110, 0x2AB0, 0x3220, 0x3850, 0x4610, 0x4920, 0x4BA0, 0x4D90, 0x5020, 0x5180, 0x5340, 0x53B0, + 0x5460, 0x55C0, 0x56C0, 0x5890, 0x5B40, 0x5D40, 0x6010, 0x6230, 0x6440, 0x66A0, 0x6880, 0x6AB0, 0x6CE0, 0x6E70, 0x7010, 0x70B0, + 0x7120, 0x70E0, 0x7060, 0x6F80, 0x6DC0, 0x6C30, 0x6A70, 0x68F0, 0x6800, 0x65F0, 0x64A0, 0x61D0, 0x5E90, 0x5B00, 0x55E0, 0x5160, + 0x4BD0, 0x45B0, 0x4030, 0x3A10, 0x33A0, 0x2D20, 0x2740, 0x2240, 0x1CA0, 0x1720, 0x1250, 0x0D10, 0x0890, 0x0340, 0xFF10, 0xFB90, + 0xF7E0, 0xF550, 0xF290, 0xF090, 0xEE40, 0xEBA0, 0xE9B0, 0xE800, 0xE650, 0xE580, 0xE460, 0xE4C0, 0xE550, 0xE680, 0xE790, 0xE8E0, + 0xEA00, 0xEB30, 0xEC40, 0xED20, 0xEF50, 0xF290, 0xF5A0, 0xF850, 0xFBA0, 0xFD60, 0xFF10, 0x00B0, 0x01E0, 0x0420, 0x0660, 0x08C0, + 0x0AF0, 0x0CF0, 0x0E70, 0x0F10, 0x1070, 0x1240, 0x1480, 0x1730, 0x1980, 0x1BE0, 0x1DB0, 0x1EA0, 0x2020, 0x2190, 0x2370, 0x2460, + 0x2540, 0x2670, 0x26C0, 0x27C0, 0x2750, 0x25B0, 0x2440, 0x2250, 0x2070, 0x1EB0, 0x1CC0, 0x1BA0, 0x1930, 0x1760, 0x1650, 0x15C0, + 0x1770, 0x1A60, 0x1ED0, 0x2770, 0x3010, 0x39D0, 0x4520, 0x50E0, 0x5C40, 0x66D0, 0x6FB0, 0x7620, 0x7AE0, 0x7DC0, 0x7ED0, 0x7F00, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F40, 0x7F30, + 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F60, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7E60, 0x7A30, 0x7670, 0x7340, 0x7040, 0x6CB0, 0x6820, 0x6240, 0x5AB0, 0x5290, 0x4AD0, 0x45F0, 0x42F0, 0x4220, 0x4300, 0x44F0, + 0x47B0, 0x4B00, 0x4EA0, 0x5330, 0x5740, 0x5C40, 0x6120, 0x6590, 0x6AB0, 0x6F40, 0x7360, 0x76D0, 0x7960, 0x7A40, 0x7970, 0x7710, + 0x7360, 0x6F40, 0x6A30, 0x64F0, 0x5F60, 0x5880, 0x5230, 0x4B90, 0x44C0, 0x3E00, 0x36B0, 0x3010, 0x29E0, 0x2540, 0x2100, 0x1EC0, + 0x1D90, 0x1D80, 0x1DB0, 0x1EC0, 0x20A0, 0x2350, 0x2650, 0x28C0, 0x29D0, 0x2890, 0x24D0, 0x1FE0, 0x1990, 0x12D0, 0x0BB0, 0x0320, + 0xF950, 0xED30, 0xE060, 0xD230, 0xC330, 0xB520, 0xA720, 0x9A50, 0x8FD0, 0x8920, 0x86A0, 0x85B0, 0x8540, 0x8500, 0x84E0, 0x84D0, + 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, + 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84F0, 0x8510, 0x8550, 0x85D0, 0x8700, 0x89C0, 0x8F90, 0x96F0, 0x9EA0, 0xA5A0, 0xACD0, + 0xB490, 0xBB20, 0xC110, 0xC620, 0xC980, 0xCDC0, 0xD110, 0xD4C0, 0xD880, 0xDAB0, 0xDD80, 0xDF30, 0xE0F0, 0xE240, 0xE350, 0xE640, + 0xE8C0, 0xEB40, 0xEF20, 0xF2C0, 0xF790, 0xFC90, 0x02D0, 0x0900, 0x0FD0, 0x16D0, 0x1D40, 0x23C0, 0x2AD0, 0x3130, 0x3820, 0x3DC0, + 0x4370, 0x4960, 0x4DF0, 0x53B0, 0x58B0, 0x5D60, 0x6190, 0x64F0, 0x67B0, 0x6960, 0x69F0, 0x6A00, 0x67E0, 0x6590, 0x6130, 0x5B30, + 0x5470, 0x4C00, 0x43D0, 0x3B00, 0x30B0, 0x2750, 0x1E60, 0x15C0, 0x0EE0, 0x0890, 0x0460, 0x0100, 0xFDD0, 0xFC20, 0xFB20, 0xFA70, + 0xFAA0, 0xFA60, 0xFA60, 0xF9E0, 0xF9B0, 0xF900, 0xF850, 0xF880, 0xF880, 0xF9A0, 0xF9B0, 0xF990, 0xFAB0, 0xFBA0, 0xFDD0, 0x0020, + 0x0300, 0x0680, 0x0950, 0x0D30, 0x11A0, 0x16D0, 0x1C50, 0x2270, 0x2940, 0x2F80, 0x35E0, 0x3C80, 0x4340, 0x4A30, 0x5190, 0x5760, + 0x5D80, 0x61B0, 0x65A0, 0x6890, 0x6AC0, 0x6D00, 0x6E00, 0x6E50, 0x6E90, 0x6DC0, 0x6D80, 0x6C90, 0x6C00, 0x6A70, 0x6890, 0x67B0, + 0x6620, 0x6500, 0x64D0, 0x64C0, 0x6720, 0x68F0, 0x6C50, 0x7070, 0x75C0, 0x7C40, 0x7EF0, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, + 0x7F80, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F10, 0x7F70, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F20, 0x7F60, 0x7EE0, 0x7E90, 0x7F00, 0x7F10, 0x7F30, + 0x7EF0, 0x7F60, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, + 0x7F20, 0x7EE0, 0x7E90, 0x7EE0, 0x7EF0, 0x7F30, 0x7AE0, 0x6E40, 0x61D0, 0x5490, 0x46B0, 0x3A70, 0x2D30, 0x22A0, 0x1960, 0x10C0, + 0x0990, 0x0420, 0x0060, 0xFE40, 0xFC80, 0xFBA0, 0xFBA0, 0xFC80, 0xFD50, 0xFD70, 0xFD50, 0xFB70, 0xF870, 0xF440, 0xEE60, 0xE920, + 0xE320, 0xDDE0, 0xD9F0, 0xD7B0, 0xD6E0, 0xD7C0, 0xD910, 0xDA60, 0xDB40, 0xDB60, 0xDB30, 0xDBC0, 0xDBE0, 0xDC50, 0xDDD0, 0xE060, + 0xE2B0, 0xE600, 0xE910, 0xED40, 0xF110, 0xF560, 0xFA00, 0xFE10, 0x02D0, 0x0640, 0x08D0, 0x0BF0, 0x0E00, 0x0FA0, 0x10C0, 0x1050, + 0x1060, 0x0FC0, 0x0EA0, 0x0CA0, 0x0A00, 0x0790, 0x05F0, 0x02E0, 0x0060, 0xFD30, 0xFA50, 0xF6A0, 0xF2B0, 0xEF30, 0xEC20, 0xE940, + 0xE610, 0xE3F0, 0xE260, 0xE0E0, 0xDFB0, 0xDEA0, 0xDD90, 0xDC70, 0xDB10, 0xD940, 0xD5E0, 0xD270, 0xD000, 0xCE20, 0xCD50, 0xCF10, + 0xD1A0, 0xD500, 0xD8C0, 0xDCE0, 0xDF40, 0xE210, 0xE590, 0xE920, 0xEDF0, 0xF3D0, 0xFA30, 0x0170, 0x0840, 0x0EF0, 0x14F0, 0x19A0, + 0x1D10, 0x2000, 0x21F0, 0x2500, 0x2850, 0x2CF0, 0x3260, 0x3870, 0x3FF0, 0x4670, 0x4D90, 0x5490, 0x5A60, 0x5FC0, 0x6460, 0x6990, + 0x6E70, 0x73A0, 0x7790, 0x7B10, 0x7DA0, 0x7EC0, 0x7F50, 0x7F20, 0x7EE0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7D90, 0x7C60, + 0x7BF0, 0x7C90, 0x7D80, 0x7EC0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7B30, + 0x7790, 0x7400, 0x70E0, 0x6E10, 0x6BB0, 0x6A00, 0x6900, 0x6830, 0x6770, 0x66C0, 0x6710, 0x67A0, 0x6920, 0x6A50, 0x6BA0, 0x6D40, + 0x6EF0, 0x70B0, 0x71B0, 0x7260, 0x72D0, 0x7250, 0x7130, 0x6F90, 0x6CF0, 0x6A90, 0x67E0, 0x6480, 0x6150, 0x5D70, 0x59A0, 0x54C0, + 0x4EF0, 0x4B60, 0x4790, 0x45B0, 0x4500, 0x45F0, 0x4990, 0x5000, 0x5770, 0x5F90, 0x6530, 0x6930, 0x6AC0, 0x6BC0, 0x6B50, 0x6A60, + 0x6A00, 0x6980, 0x68A0, 0x67A0, 0x6450, 0x6050, 0x59A0, 0x2DA0, 0x1E80, 0x1000, 0x0360, 0xF590, 0xE990, 0xDE30, 0xD2D0, 0xC700, + 0xBA10, 0xACE0, 0x9F90, 0x9420, 0x8C30, 0x8860, 0x86F0, 0x8610, 0x85D0, 0x85B0, 0x8590, 0x8590, 0x8560, 0x8540, 0x8540, 0x8530, + 0x8530, 0x8530, 0x8530, 0x8540, 0x8540, 0x8550, 0x8560, 0x8560, 0x8570, 0x8570, 0x8570, 0x8560, 0x8550, 0x8540, 0x8530, 0x8520, + 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84D0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, + 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x8500, 0x8520, 0x8530, 0x8560, 0x8590, 0x85E0, 0x8640, 0x86F0, 0x87D0, 0x88E0, + 0x8A60, 0x8C20, 0x8E50, 0x9050, 0x9240, 0x93D0, 0x9520, 0x9660, 0x97B0, 0x98C0, 0x9940, 0x9930, 0x9930, 0x9890, 0x9880, 0x97D0, + 0x97A0, 0x9780, 0x9760, 0x96B0, 0x9560, 0x94E0, 0x9460, 0x93D0, 0x93E0, 0x93B0, 0x93E0, 0x93B0, 0x9410, 0x94A0, 0x95B0, 0x96C0, + 0x98B0, 0x99E0, 0x9BA0, 0x9D70, 0x9FC0, 0xA250, 0xA5B0, 0xA8A0, 0xAB80, 0xAE00, 0xB150, 0xB520, 0xB970, 0xBDC0, 0xC110, 0xC440, + 0xC690, 0xC890, 0xCA30, 0xCD20, 0xCFA0, 0xD2F0, 0xD600, 0xD940, 0xDC30, 0xDE60, 0xE0E0, 0xE310, 0xE530, 0xE7E0, 0xEA60, 0xEC80, + 0xEDD0, 0xEE60, 0xEE70, 0xEDD0, 0xEC70, 0xEA70, 0xE7B0, 0xE430, 0xE010, 0xDB80, 0xD5D0, 0xD0C0, 0xCBB0, 0xC760, 0xC380, 0xBE70, + 0xB8D0, 0xB350, 0xAD40, 0xA6A0, 0xA0F0, 0x9BD0, 0x9690, 0x9200, 0x8DB0, 0x8AA0, 0x88A0, 0x8750, 0x8680, 0x8600, 0x85B0, 0x8580, + 0x8560, 0x8540, 0x8530, 0x8530, 0x8530, 0x8520, 0x8520, 0x8530, 0x8530, 0x8530, 0x8530, 0x8540, 0x8550, 0x8550, 0x8570, 0x8590, + 0x85C0, 0x85E0, 0x8620, 0x8660, 0x86B0, 0x8710, 0x87C0, 0x8880, 0x89E0, 0x8B80, 0x8D30, 0x8F80, 0x9210, 0x9590, 0x98F0, 0x9CC0, + 0xA100, 0xA4C0, 0xA990, 0xAE50, 0xB3F0, 0xBA50, 0xC0B0, 0xC790, 0xCE00, 0xD500, 0xDB40, 0xE130, 0xE770, 0xECD0, 0xF1E0, 0xF6F0, + 0xFAF0, 0xFF30, 0x0340, 0x06B0, 0x0A10, 0x0C80, 0x0F90, 0x1190, 0x1370, 0x1660, 0x1980, 0x1DF0, 0x22E0, 0x26B0, 0x2A80, 0x2DA0, + 0x3180, 0x34C0, 0x36D0, 0x38E0, 0x3940, 0x38D0, 0x3760, 0x3520, 0x31F0, 0x2E00, 0x2A40, 0x25E0, 0x2010, 0x1B00, 0x1560, 0x0FD0, + 0x0A50, 0x0530, 0x0040, 0xFA40, 0xF410, 0xEDD0, 0xE680, 0xE070, 0xD980, 0xD220, 0xCAB0, 0xC2B0, 0xBB80, 0xB3A0, 0xACA0, 0xA670, + 0xA110, 0x9C70, 0x9800, 0x9460, 0x9120, 0x8ED0, 0x8D50, 0x8CE0, 0x8D10, 0x8DB0, 0x8E70, 0x9050, 0x9240, 0x94E0, 0x9800, 0x9B00, + 0x9DD0, 0xA120, 0xA430, 0xA850, 0xABD0, 0xB040, 0xB3D0, 0xB6F0, 0xBA70, 0xBD80, 0xC080, 0xC420, 0xC780, 0xCB60, 0xCE90, 0xD1A0, + 0xD4A0, 0xD710, 0xDA60, 0xDD60, 0xDFF0, 0xE1B0, 0xE2A0, 0xE380, 0xE3A0, 0xE3D0, 0xE4B0, 0xE4E0, 0xE580, 0xE550, 0xE570, 0xE530, + 0xE530, 0xE580, 0xE580, 0xE4C0, 0xE410, 0xE2C0, 0xE1B0, 0xE170, 0xE090, 0xDFF0, 0xDDB0, 0xDBE0, 0xDA00, 0xD7E0, 0xD680, 0xD550, + 0xD480, 0xD350, 0xD180, 0xCF50, 0xCC60, 0xCA90, 0xC880, 0xC720, 0xC5F0, 0xC510, 0xC4D0, 0xC520, 0xC770, 0xCC60, 0xD320, 0xDE40, + 0xEC70, 0xFC30, 0x5030, 0x6230, 0x72F0, 0x7D70, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7E90, + 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, + 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F10, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, + 0x7E90, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7EB0, 0x7B80, 0x78C0, 0x7590, 0x7290, 0x7040, 0x6C30, 0x69B0, 0x66C0, 0x63F0, + 0x6180, 0x5E40, 0x5BA0, 0x5710, 0x51D0, 0x4BC0, 0x4550, 0x3FF0, 0x3A30, 0x34F0, 0x30F0, 0x2CA0, 0x29A0, 0x2760, 0x2550, 0x2410, + 0x22E0, 0x2180, 0x2030, 0x1E70, 0x1DC0, 0x1D10, 0x1D80, 0x1E60, 0x1F50, 0x20E0, 0x2180, 0x2380, 0x2550, 0x26B0, 0x28B0, 0x2A00, + 0x2A80, 0x2AB0, 0x2A20, 0x2A10, 0x2A40, 0x2A80, 0x29F0, 0x2810, 0x2610, 0x2200, 0x1E50, 0x1AB0, 0x1660, 0x1250, 0x0D80, 0x07F0, + 0x0270, 0xFD40, 0xF920, 0xF520, 0xF0F0, 0xEC90, 0xE750, 0xE1C0, 0xDBC0, 0xD590, 0xCF80, 0xC7F0, 0xBFE0, 0xB6A0, 0xACF0, 0xA240, + 0x9690, 0x8C50, 0x8730, 0x8570, 0x8500, 0x8490, 0x84C0, 0x84B0, 0x84A0, 0x8430, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84B0, + 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84C0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8550, 0x8590, 0x85E0, 0x8650, 0x86F0, + 0x8790, 0x8850, 0x8930, 0x8A30, 0x8BA0, 0x8D10, 0x8EC0, 0x90E0, 0x92F0, 0x9560, 0x9810, 0x9BC0, 0x9ED0, 0xA1F0, 0xA520, 0xA850, + 0xAB50, 0xADB0, 0xB030, 0xB290, 0xB420, 0xB5A0, 0xB650, 0xB690, 0xB670, 0xB640, 0xB5A0, 0xB4E0, 0xB340, 0xB110, 0xAEC0, 0xAC60, + 0xAA80, 0xA810, 0xA610, 0xA330, 0xA070, 0x9CD0, 0x98B0, 0x9580, 0x9280, 0x8F80, 0x8CE0, 0x8B30, 0x8A20, 0x8930, 0x8850, 0x87A0, + 0x8710, 0x86B0, 0x8670, 0x8650, 0x8630, 0x8630, 0x8640, 0x8650, 0x8660, 0x86B0, 0x8700, 0x8760, 0x87A0, 0x8810, 0x88C0, 0x8930, + 0x8A40, 0x8B30, 0x8C00, 0x8D10, 0x8E60, 0x8FC0, 0x9190, 0x9330, 0x9500, 0x9650, 0x9820, 0x9990, 0x9B20, 0x9CF0, 0x9F50, 0xA120, + 0xA330, 0xA500, 0xA680, 0xA890, 0xA9D0, 0xABB0, 0xAD00, 0xADF0, 0xAE20, 0xAE30, 0xAE70, 0xAE50, 0xAE90, 0xAE10, 0xADE0, 0xAD60, + 0xAD00, 0xACD0, 0xAD10, 0xAD60, 0xAD70, 0xADC0, 0xAE70, 0xAF00, 0xB040, 0xB1A0, 0xB370, 0xB5D0, 0xB880, 0xBAE0, 0xBEA0, 0xC2A0, + 0xC7C0, 0xCDD0, 0xD440, 0xDBE0, 0xE3F0, 0xEB40, 0x06E0, 0x0DF0, 0x1410, 0x1A60, 0x2130, 0x2790, 0x2EE0, 0x36F0, 0x3ED0, 0x46C0, + 0x4F10, 0x5750, 0x5EE0, 0x6720, 0x6F50, 0x7670, 0x7C90, 0x7F10, 0x7F30, 0x7F40, 0x7F40, 0x7F50, 0x7F30, 0x7F40, 0x7F40, 0x7F30, + 0x7F40, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7CA0, 0x7360, 0x6AB0, 0x6230, 0x5A30, 0x5260, 0x4B90, 0x44F0, 0x3D60, 0x36C0, 0x3070, 0x2B20, 0x2740, 0x24C0, + 0x22F0, 0x21F0, 0x2140, 0x2180, 0x2190, 0x2280, 0x2340, 0x23F0, 0x2490, 0x25C0, 0x2750, 0x2910, 0x2B20, 0x2D40, 0x2F30, 0x3170, + 0x3360, 0x3560, 0x3680, 0x37D0, 0x38C0, 0x3970, 0x39E0, 0x39F0, 0x3A80, 0x3AF0, 0x3B90, 0x3BE0, 0x3C40, 0x3C80, 0x3C00, 0x3A40, + 0x3800, 0x3480, 0x2FF0, 0x2980, 0x2090, 0x1640, 0x0A10, 0xFBF0, 0xEE70, 0xE0D0, 0xD420, 0xC7F0, 0xBD10, 0xB270, 0xA830, 0x9F60, + 0x9630, 0x8F30, 0x8A90, 0x8800, 0x86A0, 0x85F0, 0x8590, 0x8550, 0x8530, 0x8510, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, 0x8500, + 0x8510, 0x8510, 0x8530, 0x8510, 0x8510, 0x8510, 0x8530, 0x8530, 0x8540, 0x8570, 0x85C0, 0x8660, 0x8750, 0x88E0, 0x8BF0, 0x9040, + 0x9560, 0x9A40, 0x9F30, 0xA4B0, 0xAAA0, 0xB010, 0xB4D0, 0xB920, 0xBCF0, 0xC070, 0xC3A0, 0xC700, 0xC970, 0xCCE0, 0xCE70, 0xCF70, + 0xCEB0, 0xCD00, 0xCB80, 0xC9E0, 0xC870, 0xC700, 0xC520, 0xC3B0, 0xC190, 0xBF60, 0xBCE0, 0xBA40, 0xB780, 0xB480, 0xB1C0, 0xAF20, + 0xAD70, 0xAC90, 0xABF0, 0xAD00, 0xAEA0, 0xB100, 0xB520, 0xBA30, 0xC030, 0xC5B0, 0xCB60, 0xD1E0, 0xD7C0, 0xDDD0, 0xE490, 0xEAA0, + 0xF110, 0xF780, 0xFD00, 0x0140, 0x0460, 0x0720, 0x0860, 0x0880, 0x0870, 0x0730, 0x06A0, 0x06B0, 0x0830, 0x0BE0, 0x1040, 0x1480, + 0x1750, 0x1720, 0x1480, 0x0EF0, 0x0820, 0x0220, 0xFDF0, 0xFC00, 0xFD30, 0x00C0, 0x0480, 0x07B0, 0x0950, 0x07D0, 0x03A0, 0xFD00, + 0xF490, 0xEB90, 0xE1F0, 0xD860, 0xCF90, 0xC720, 0xC0E0, 0xBCF0, 0xBAD0, 0xB990, 0xB7F0, 0xB7B0, 0xB790, 0xB780, 0xB8D0, 0xBB40, + 0xBF70, 0xC4A0, 0xC9D0, 0xCF10, 0xD330, 0xD720, 0xD940, 0xDB70, 0xDDE0, 0xE0D0, 0xE530, 0xEB60, 0xF2B0, 0xFB20, 0x0390, 0x0C30, + 0x14C0, 0x1B90, 0x2130, 0x2580, 0x2940, 0x2B10, 0x2BB0, 0x2B70, 0x2970, 0x25B0, 0x1FF0, 0x17F0, 0x0DD0, 0x01D0, 0xF6E0, 0xED10, + 0xE6D0, 0xE510, 0xE810, 0xEEF0, 0xF830, 0x0170, 0x0AC0, 0x1150, 0x1750, 0x1B00, 0x1D50, 0x1FF0, 0x2140, 0x2220, 0x23D0, 0x2530, + 0x2730, 0x2940, 0x2B50, 0x2D20, 0x2E80, 0x3080, 0x31C0, 0x32E0, 0x33D0, 0x3430, 0x3530, 0x3520, 0x35A0, 0x3610, 0x3640, 0x38B0, + 0x3B10, 0x3DD0, 0x4100, 0x4390, 0x4510, 0x4430, 0x4080, 0x3B10, 0x3370, 0x2DE0, 0x28D0, 0x25F0, 0x2530, 0x2570, 0x2690, 0x26B0, + 0x2560, 0x21D0, 0x1D70, 0x1750, 0x0F80, 0x0540, 0xFA90, 0xEE60, 0xE210, 0xD650, 0xCB00, 0xC020, 0xB600, 0xAC10, 0xA180, 0x9790, + 0x8FB0, 0x8A20, 0x8780, 0x8670, 0x85B0, 0x8580, 0x8560, 0x8540, 0x8530, 0x8520, 0x8510, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84E0, + 0x84E0, 0x84F0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8500, 0x8510, 0x8510, 0x8510, 0x8500, 0x8500, + 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, + 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84F0, 0x84E0, 0x84E0, + 0x84F0, 0x8500, 0x8530, 0x8550, 0x85B0, 0x86A0, 0x8840, 0x8C20, 0x92A0, 0x9A90, 0xA1E0, 0xA8F0, 0xB020, 0xB610, 0xBB90, 0xC160, + 0xC6C0, 0xCAF0, 0xCF20, 0xD320, 0xD6C0, 0xDA30, 0xDCE0, 0xDF00, 0xDF90, 0xDF80, 0xDDC0, 0xDAF0, 0xD630, 0xCF80, 0xC6C0, 0xBBA0, + 0xAD80, 0x9D40, 0x8E50, 0x8700, 0x8530, 0x84E0, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8460, 0x8470, 0x8470, 0x84B0, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x84F0, 0x8550, + 0x8670, 0x8A60, 0x9470, 0x9E10, 0xA6B0, 0xADF0, 0xB2F0, 0xB750, 0xBB10, 0xBDE0, 0xBF80, 0xC210, 0xC560, 0xC920, 0xD030, 0xD720, + 0xDEC0, 0xE7C0, 0xF100, 0xFB00, 0x05C0, 0x1000, 0x1B50, 0x27C0, 0x33D0, 0x4030, 0x4D20, 0x5AE0, 0x6750, 0x7320, 0x7BC0, 0x7F10, + 0x7F20, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, 0x7EF0, 0x7390, 0x6670, 0x5860, 0x4B60, 0x3FD0, 0x3610, 0x2FD0, + 0x2C00, 0x2A40, 0x2B00, 0x2DA0, 0x3210, 0x3710, 0x3DB0, 0x46C0, 0x51C0, 0x5F50, 0x6E00, 0x7C50, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F20, 0x7EC0, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, + 0x7F40, 0x7F10, 0x7F90, 0x7F00, 0x7F20, 0x7EF0, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7EB0, 0x7F10, + 0x7EF0, 0x7F70, 0x7F20, 0x7ED0, 0x7ED0, 0x7EE0, 0x7F30, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E70, 0x7ED0, 0x7F10, + 0x7F20, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, 0x7F10, 0x7E90, 0x6200, 0x4A60, 0x3740, 0x2710, 0x1C70, 0x1200, 0x08C0, 0x0080, 0xF900, + 0xF4E0, 0xF200, 0xF0F0, 0xF0A0, 0xEFF0, 0xEE60, 0xEA80, 0xE490, 0xDCF0, 0xD2C0, 0xC660, 0xB780, 0xA4A0, 0x9160, 0x86D0, 0x8510, + 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84E0, 0x8510, 0x85C0, 0x8840, 0x91A0, 0x9DA0, 0xA7F0, 0xB220, 0xBB50, + 0xC520, 0xCF70, 0xDB20, 0xE6F0, 0xF420, 0x00D0, 0x0DF0, 0x1B80, 0x27A0, 0x3390, 0x3FD0, 0x4B60, 0x5770, 0x63E0, 0x7010, 0x7A50, + 0x7F00, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7910, 0x6DF0, 0x61B0, 0x5740, 0x4BB0, 0x4140, 0x36C0, 0x2C10, 0x2100, 0x15B0, 0x09A0, + 0xFD70, 0xF160, 0xE440, 0xD920, 0xCE50, 0xC350, 0xB880, 0xACE0, 0xA170, 0x9680, 0x8D80, 0x87F0, 0x8600, 0x8550, 0x8510, 0x8530, + 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, + 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8510, 0x8520, 0x8540, 0x8560, 0x85A0, 0x8600, 0x8680, 0x8760, 0x8890, 0x8AA0, + 0x8D70, 0x9180, 0x9600, 0x9A90, 0x9F10, 0xAC50, 0xAF40, 0xB290, 0xB5C0, 0xB840, 0xBA80, 0xBC30, 0xBDA0, 0xBE40, 0xBEA0, 0xBE70, + 0xBDD0, 0xBCF0, 0xBAD0, 0xB9A0, 0xB7D0, 0xB620, 0xB570, 0xB4F0, 0xB5E0, 0xB6B0, 0xB790, 0xB870, 0xB9B0, 0xBA20, 0xBA10, 0xB980, + 0xB990, 0xB950, 0xB8F0, 0xB8D0, 0xB820, 0xB790, 0xB620, 0xB4C0, 0xB2E0, 0xB190, 0xAFF0, 0xAE80, 0xACA0, 0xAB50, 0xAB20, 0xAAF0, + 0xAAD0, 0xAAE0, 0xAAF0, 0xAAE0, 0xAAA0, 0xAB30, 0xABA0, 0xAC90, 0xADB0, 0xAEA0, 0xAF60, 0xB050, 0xB120, 0xB200, 0xB370, 0xB4F0, + 0xB620, 0xB620, 0xB650, 0xB650, 0xB650, 0xB5F0, 0xB4F0, 0xB440, 0xB2A0, 0xB140, 0xAFC0, 0xAE40, 0xAD80, 0xACD0, 0xABB0, 0xAA10, + 0xA8C0, 0xA600, 0xA3E0, 0xA1F0, 0xA010, 0x9DC0, 0x9B10, 0x9760, 0x93C0, 0x9030, 0x8C90, 0x8A00, 0x8800, 0x86B0, 0x85D0, 0x8560, + 0x8520, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84E0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, + 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, + 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x8480, 0x84C0, + 0x84C0, 0x84C0, 0x8490, 0x84D0, 0x84E0, 0x84E0, 0x8510, 0x84F0, 0x8500, 0x8540, 0x8530, 0x8560, 0x85A0, 0x8620, 0x86F0, 0x8800, + 0x8990, 0x8BD0, 0x8ED0, 0x91C0, 0x9390, 0x9550, 0x9610, 0x9490, 0x91B0, 0x8D30, 0x8970, 0x86E0, 0x85A0, 0x8530, 0x8500, 0x84D0, + 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8520, 0x85C0, 0x87E0, 0x9030, + 0x9D90, 0xAC30, 0xB8B0, 0xC410, 0xCF70, 0xD8B0, 0xE0A0, 0xE780, 0xEED0, 0xF5D0, 0xFC80, 0x0310, 0x09D0, 0x1010, 0x16C0, 0x1D00, + 0x2350, 0x2A40, 0x3160, 0x3B10, 0x4440, 0x4F00, 0x5A70, 0x6600, 0x72B0, 0x7C70, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, + 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F60, 0x7ED0, + 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F40, 0x74F0, 0x71A0, 0x7340, 0x7910, 0x7EB0, 0x7E90, 0x7F10, 0x7EF0, 0x7EF0, + 0x7F10, 0x7EA0, 0x6000, 0x3B80, 0x1650, 0xF320, 0xD640, 0xBBD0, 0xA370, 0x8D10, 0x8590, 0x84E0, 0x84A0, 0x8490, 0x8470, 0x8460, + 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8450, 0x8470, 0x8480, 0x84A0, + 0x84D0, 0x8510, 0x85A0, 0x8760, 0x8D50, 0x9A80, 0xAA50, 0xBC20, 0xCF10, 0xE290, 0xF390, 0x03B0, 0x11A0, 0x1E20, 0x2A00, 0x3480, + 0x3F70, 0x4980, 0x5410, 0x5D00, 0x6440, 0x6B70, 0x7040, 0x7480, 0x7760, 0x7890, 0x7990, 0x7840, 0x75C0, 0x71D0, 0x6B60, 0x6460, + 0x5C50, 0x53B0, 0x49F0, 0x4060, 0x3690, 0x2E70, 0x26A0, 0x1FE0, 0x1A10, 0x1570, 0x11A0, 0x0D40, 0x0910, 0x0300, 0xFCC0, 0xF5B0, + 0xEE30, 0xE660, 0xDD60, 0xD580, 0xCD80, 0xC660, 0xBFA0, 0xB9E0, 0xB4C0, 0xAFB0, 0xAA70, 0xA6A0, 0xA400, 0xA390, 0xA4C0, 0xA940, + 0xAF90, 0xB760, 0xBE80, 0xC490, 0xC8F0, 0xCC10, 0xCD40, 0xCCF0, 0xCBB0, 0xCA20, 0xC8D0, 0xC7B0, 0xC7A0, 0xC6A0, 0xC3D0, 0xBE90, + 0xB7B0, 0xAED0, 0xA680, 0x9FB0, 0x9A60, 0x9680, 0x9270, 0x8FD0, 0x8D80, 0x8C00, 0x8B30, 0x8B00, 0x8B60, 0x8CB0, 0x8F80, 0x9520, + 0x9E00, 0xA9C0, 0xB6B0, 0xC680, 0xD3F0, 0xE0B0, 0xEC20, 0xF6A0, 0x00D0, 0x0A30, 0x11B0, 0x17C0, 0x1930, 0x17E0, 0x1380, 0x0CB0, + 0x05A0, 0xFF40, 0xF9C0, 0xF5B0, 0xF290, 0xF260, 0xF380, 0xF5D0, 0xF900, 0xFC80, 0x00D0, 0x0580, 0x0AC0, 0x1140, 0x1900, 0x2100, + 0x2840, 0x2ED0, 0x3570, 0x3AC0, 0x4080, 0x4610, 0x4BB0, 0x51C0, 0x5650, 0x5AF0, 0x5FA0, 0x63F0, 0x6810, 0x6C30, 0x7100, 0x74E0, + 0x78B0, 0x7B70, 0x7DC0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, 0x7E90, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7F30, + 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F30, 0x7F10, 0x7EB0, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F40, + 0x7F10, 0x7F70, 0x7EE0, 0x7F10, 0x7F20, 0x7F00, 0x7F70, 0x7EF0, 0x7F20, 0x7F10, 0x7F00, 0x7F90, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, + 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F50, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7E90, 0x7ED0, 0x7F10, 0x7EF0, + 0x7F10, 0x7EB0, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F40, 0x7F10, + 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F60, 0x7F00, 0x7ED0, 0x7F00, 0x7EF0, + 0x7EF0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, + 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7EE0, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F30, + 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F40, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7B50, 0x7570, 0x6FE0, 0x6A80, 0x6690, 0x63A0, 0x6240, 0x6180, 0x6190, 0x6320, 0x6540, 0x6750, 0x6A30, + 0x6CE0, 0x7030, 0x72B0, 0x75B0, 0x7800, 0x79C0, 0x7B10, 0x7BF0, 0x7C60, 0x7C70, 0x7BF0, 0x7B60, 0x7AC0, 0x7A50, 0x79F0, 0x7940, + 0x7840, 0x7790, 0x76E0, 0x7600, 0x7550, 0x7530, 0x7530, 0x7440, 0x73D0, 0x7350, 0x72E0, 0x7290, 0x7250, 0x72E0, 0x7320, 0x73C0, + 0x7450, 0x74B0, 0x74E0, 0x7590, 0x7610, 0x76E0, 0x77E0, 0x7990, 0x7AF0, 0x7C60, 0x7DA0, 0x7E50, 0x7EE0, 0x7F20, 0x7F30, 0x7F10, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F00, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F00, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7DA0, 0x7740, 0x7050, 0x6930, 0x62A0, 0x5C00, + 0x5490, 0x4DB0, 0x4740, 0x4160, 0x3B70, 0x3570, 0x2F60, 0x28E0, 0x21C0, 0x1940, 0x11A0, 0x0A90, 0x0430, 0xFEB0, 0xF970, 0xF450, + 0xEF90, 0xE9E0, 0xE420, 0xDF10, 0xD990, 0xD470, 0xD080, 0xCC50, 0xC950, 0xC600, 0xC350, 0xC0B0, 0xBE30, 0xBB90, 0xB910, 0xB6B0, + 0xB570, 0xB540, 0xB4C0, 0xB4A0, 0xB8D0, 0xBA60, 0xBCE0, 0xBFB0, 0xC230, 0xC520, 0xC770, 0xCAC0, 0xCDC0, 0xD150, 0xD4E0, 0xD720, + 0xD950, 0xDB70, 0xDBE0, 0xDD00, 0xDD20, 0xDD10, 0xDC80, 0xDB80, 0xDB50, 0xDAE0, 0xDC00, 0xDC80, 0xDCE0, 0xDDE0, 0xDDE0, 0xDDE0, + 0xDD40, 0xDD00, 0xDDF0, 0xDEB0, 0xDF30, 0xE010, 0xE110, 0xE230, 0xE310, 0xE330, 0xE3C0, 0xE300, 0xE2B0, 0xE150, 0xDF90, 0xDD20, + 0xDA00, 0xD690, 0xD220, 0xCD80, 0xC840, 0xC260, 0xBD20, 0xB7F0, 0xB310, 0xAEA0, 0xAA10, 0xA5F0, 0xA200, 0x9E90, 0x9A90, 0x9760, + 0x9530, 0x9340, 0x9120, 0x8FE0, 0x8FC0, 0x8F90, 0x8FD0, 0x9070, 0x91D0, 0x9310, 0x9490, 0x9690, 0x99A0, 0x9D70, 0xA120, 0xA550, + 0xA9B0, 0xAE80, 0xB370, 0xB900, 0xBE90, 0xC530, 0xCB60, 0xD120, 0xD640, 0xDBA0, 0xE0A0, 0xE590, 0xEB30, 0xF070, 0xF670, 0xFBB0, + 0xFFE0, 0x04A0, 0x0970, 0x0DB0, 0x11F0, 0x15A0, 0x1970, 0x1C90, 0x1FF0, 0x2280, 0x2530, 0x2790, 0x28E0, 0x29D0, 0x2AD0, 0x2AC0, + 0x2B00, 0x2A90, 0x2960, 0x27C0, 0x25F0, 0x2450, 0x21B0, 0x1EC0, 0x1C40, 0x1890, 0x1500, 0x1090, 0x0CB0, 0x0980, 0x0640, 0x03F0, + 0x01B0, 0xFF00, 0xFCC0, 0xF950, 0xF700, 0xF3F0, 0xF170, 0xF070, 0xEF00, 0xEDF0, 0xED50, 0xEC30, 0xEB80, 0xEA80, 0xEA10, 0xEA20, + 0xE980, 0xE910, 0xE890, 0xE860, 0xE830, 0xE860, 0xE8D0, 0xE8D0, 0xE8D0, 0xE8D0, 0xE830, 0xE840, 0xE7D0, 0xE680, 0xE540, 0xE440, + 0xE3E0, 0xE340, 0xE230, 0xE170, 0xDFB0, 0xDEE0, 0xDD20, 0xDB30, 0xDAA0, 0xD910, 0xD920, 0xD920, 0xD940, 0xD940, 0xD8D0, 0xD910, + 0xD950, 0xD9D0, 0xDAE0, 0xDBA0, 0xDCC0, 0xDE10, 0xDF30, 0xE060, 0xE160, 0xE230, 0xE260, 0xE1F0, 0xE1B0, 0xE130, 0xE100, 0xE0D0, + 0xE0A0, 0xE0C0, 0xDFF0, 0xDF70, 0xDE40, 0xDC90, 0xDB70, 0xDAA0, 0xD940, 0xD560, 0xD4A0, 0xD440, 0xD310, 0xD2A0, 0xD210, 0xD120, + 0xD010, 0xCE40, 0xCD30, 0xCC70, 0xCB70, 0xCAA0, 0xC9C0, 0xC980, 0xC880, 0xC7E0, 0xC7B0, 0xC720, 0xC730, 0xC6E0, 0xC740, 0xC8A0, + 0xC9D0, 0xCBA0, 0xCDE0, 0xD040, 0xD360, 0xD5D0, 0xD870, 0xDB60, 0xDE90, 0xE310, 0xE780, 0xEC90, 0xF190, 0xF620, 0xFB20, 0xFF80, + 0x04F0, 0x0B20, 0x10A0, 0x1790, 0x1EC0, 0x2580, 0x2C80, 0x32B0, 0x39B0, 0x4000, 0x45D0, 0x4B30, 0x50A0, 0x56F0, 0x5B70, 0x5F60, + 0x6260, 0x6490, 0x6670, 0x66A0, 0x65C0, 0x6490, 0x62E0, 0x61E0, 0x6040, 0x5EF0, 0x5DC0, 0x5BD0, 0x5A50, 0x5890, 0x5660, 0x5450, + 0x51F0, 0x5070, 0x4EF0, 0x4D10, 0x4C00, 0x4A40, 0x49D0, 0x48C0, 0x4740, 0x4660, 0x44B0, 0x4380, 0x41C0, 0x4090, 0x40D0, 0x4180, + 0x42C0, 0x4500, 0x4690, 0x4980, 0x4C00, 0x4F10, 0x5230, 0x5500, 0x5810, 0x5B10, 0x5E20, 0x6140, 0x63F0, 0x6700, 0x6980, 0x6CB0, + 0x6F90, 0x71A0, 0x7470, 0x77B0, 0x7AE0, 0x7D60, 0x7ED0, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, + 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EF0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, + 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F70, + 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F70, 0x7F20, 0x7EF0, 0x7ED0, 0x7EB0, 0x7F30, 0x7EF0, + 0x7EB0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, + 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7F50, + 0x7EF0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F80, 0x7ED0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F50, 0x7EE0, + 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7E70, 0x6C20, 0x5750, 0x42B0, 0x2CE0, 0x16A0, 0xFF90, 0xE850, 0xD400, 0xC160, + 0xB3D0, 0xA920, 0xA380, 0xA340, 0xA630, 0xACC0, 0xB790, 0xC590, 0xD750, 0xEB20, 0x0250, 0x1830, 0x2D00, 0x3F40, 0x4C10, 0x5170, + 0x4E20, 0x40F0, 0x2CD0, 0x12E0, 0xFA00, 0xE510, 0xD380, 0xC590, 0xB820, 0xA990, 0x9980, 0x8BB0, 0x8610, 0x8520, 0x84F0, 0x84E0, + 0x84D0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x84C0, 0x84C0, 0x8480, 0x8470, 0x8490, 0x8480, 0x8490, 0x84B0, 0x8510, 0x8540, 0x8630, + 0x8810, 0x8A00, 0x89F0, 0x88F0, 0x87A0, 0x8690, 0x85D0, 0x8540, 0x8510, 0x84F0, 0x84E0, 0x84D0, 0x84E0, 0x8500, 0x8570, 0x8630, + 0x8A20, 0x95C0, 0xA100, 0xA910, 0xAEA0, 0xB220, 0xB610, 0xBAD0, 0xC1A0, 0xCA20, 0xD380, 0xDCC0, 0xE3D0, 0xE790, 0xE830, 0xE550, + 0xE100, 0xDD30, 0xDB00, 0xDB90, 0xDED0, 0xE4F0, 0xED60, 0xF760, 0x0400, 0x1080, 0x1D40, 0x2A00, 0x35D0, 0x41F0, 0x4DC0, 0x5910, + 0x6350, 0x6C20, 0x7240, 0x75D0, 0x7840, 0x79D0, 0x7B10, 0x7C00, 0x7C70, 0x7CC0, 0x7BF0, 0x7AA0, 0x77C0, 0x72D0, 0x6C90, 0x6470, + 0x5AA0, 0x5090, 0x45B0, 0x3B00, 0x3240, 0x2A80, 0x2520, 0x20E0, 0x1E50, 0x1E00, 0x1F90, 0x21F0, 0x23F0, 0x2530, 0x2470, 0x2240, + 0x1DD0, 0x17F0, 0x1160, 0x09E0, 0x0110, 0xF5A0, 0xE960, 0xDA40, 0xC810, 0xB4F0, 0xA1D0, 0x9080, 0x8810, 0x85D0, 0x8540, 0x8520, + 0x8500, 0x84E0, 0x84D0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8520, 0x8550, 0x8590, 0x8630, 0x8770, + 0x89A0, 0x8E80, 0x96D0, 0x9E40, 0xA600, 0xAF00, 0xB710, 0xBFD0, 0xC720, 0xCE60, 0xD440, 0xD8D0, 0xDBF0, 0xDEE0, 0xE240, 0xE590, + 0xE9A0, 0xEEC0, 0xF480, 0xFAF0, 0x0320, 0x0A70, 0x1040, 0x1490, 0x1640, 0x1540, 0x12E0, 0x0ED0, 0x0AA0, 0x06C0, 0x0400, 0x0230, + 0x00E0, 0xFE40, 0xFAB0, 0xF520, 0xEEA0, 0xE770, 0xDF40, 0xD880, 0xD220, 0xCCF0, 0xC960, 0xC6A0, 0xC4F0, 0xC410, 0xC3D0, 0xC4C0, + 0xC570, 0xC650, 0xC760, 0xC900, 0xCB70, 0xCED0, 0xD250, 0xD6A0, 0xDB20, 0xDF50, 0xE320, 0xE730, 0xEAB0, 0xEE00, 0xF120, 0xF440, + 0xF790, 0xFB60, 0xFE40, 0x00D0, 0x0220, 0x02A0, 0x0290, 0x0210, 0x02B0, 0x0400, 0x0790, 0x0C00, 0x10E0, 0x1710, 0x1C10, 0x2100, + 0x25C0, 0x2AD0, 0x3030, 0x35F0, 0x3B10, 0x3FF0, 0x4410, 0x4860, 0x4B70, 0x4F10, 0x5300, 0x55E0, 0x59B0, 0x5BA0, 0x5DC0, 0x5E50, + 0x5ED0, 0x6020, 0x60C0, 0x6200, 0x6390, 0x64C0, 0x6610, 0x6580, 0x6460, 0x63A0, 0x6180, 0x60B0, 0x6030, 0x5FE0, 0x5FF0, 0x5FF0, + 0x6070, 0x5F50, 0x5D30, 0x5A20, 0x5580, 0x5050, 0x4A10, 0x41E0, 0x3910, 0x30B0, 0x27E0, 0x1DE0, 0x12C0, 0x06A0, 0xF880, 0xE920, + 0xD580, 0xC160, 0xAC30, 0x84F0, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8480, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8510, 0x8530, + 0x8550, 0x8590, 0x8600, 0x86B0, 0x87F0, 0x8A50, 0x8E60, 0x9420, 0x99D0, 0x9F00, 0xA500, 0xAB00, 0xB120, 0xB7C0, 0xBD60, 0xC300, + 0xC830, 0xCD70, 0xD210, 0xD710, 0xDCD0, 0xE270, 0xE8B0, 0xEEF0, 0xF4A0, 0xFA80, 0x00B0, 0x0670, 0x0D40, 0x13B0, 0x1AF0, 0x2160, + 0x2750, 0x2CB0, 0x3120, 0x35F0, 0x3A80, 0x3D30, 0x4020, 0x4240, 0x44B0, 0x44E0, 0x4510, 0x4550, 0x4530, 0x4520, 0x4470, 0x4450, + 0x4410, 0x43C0, 0x4410, 0x4460, 0x4460, 0x45C0, 0x4650, 0x4710, 0x4820, 0x48E0, 0x4990, 0x4900, 0x48A0, 0x47C0, 0x46F0, 0x4700, + 0x4680, 0x4590, 0x4490, 0x4180, 0x3F90, 0x3CB0, 0x3A30, 0x38E0, 0x36F0, 0x3610, 0x3500, 0x3320, 0x31D0, 0x3100, 0x30D0, 0x3090, + 0x3130, 0x3230, 0x3360, 0x3550, 0x3830, 0x3BE0, 0x4010, 0x44F0, 0x4B00, 0x5180, 0x5890, 0x7700, 0x7D80, 0x7F00, 0x7F00, 0x7EF0, + 0x7ED0, 0x7F30, 0x7F00, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7520, 0x6960, 0x5BB0, 0x4E30, 0x4200, 0x3750, 0x2DD0, + 0x22B0, 0x1820, 0x0BC0, 0xFE00, 0xEE20, 0xDA30, 0xC750, 0xB3A0, 0xA0A0, 0x9110, 0x88E0, 0x8650, 0x85A0, 0x8570, 0x8570, 0x8580, + 0x85D0, 0x8670, 0x8820, 0x8CC0, 0x9540, 0x9EF0, 0xA820, 0xB190, 0xBA50, 0xC270, 0xCA70, 0xD270, 0xD9F0, 0xE240, 0xE9C0, 0xF050, + 0xF500, 0xF6A0, 0xF530, 0xF060, 0xE960, 0xE280, 0xDC80, 0xD930, 0xD9C0, 0xDDF0, 0xE430, 0xEBF0, 0xF380, 0xF8F0, 0xFB10, 0xF880, + 0xF1C0, 0xE810, 0xDA20, 0xCCC0, 0xC0D0, 0xB5B0, 0xAD60, 0xA690, 0xA110, 0x9BE0, 0x9680, 0x9110, 0x8D00, 0x8A30, 0x88D0, 0x8840, + 0x88D0, 0x8A80, 0x8E20, 0x93F0, 0x9B70, 0xA300, 0xAAE0, 0xB2A0, 0xB9E0, 0xC190, 0xC990, 0xD110, 0xD7F0, 0xDF50, 0xE580, 0xEB20, + 0xF040, 0xF4F0, 0xFA90, 0x0020, 0x06F0, 0x0D30, 0x13A0, 0x19F0, 0x1E90, 0x22F0, 0x26A0, 0x2950, 0x2CD0, 0x3000, 0x3400, 0x38F0, + 0x3D40, 0x4200, 0x45C0, 0x49B0, 0x4C20, 0x4D00, 0x4E90, 0x4ED0, 0x4E70, 0x4D80, 0x4C80, 0x4B80, 0x4B80, 0x4D80, 0x5070, 0x5520, + 0x5A60, 0x6010, 0x64B0, 0x68A0, 0x6AF0, 0x6CD0, 0x6DC0, 0x6EC0, 0x6F90, 0x7110, 0x73E0, 0x7650, 0x7930, 0x7BB0, 0x7D40, 0x7E40, + 0x7E80, 0x7D30, 0x79F0, 0x7390, 0x6BA0, 0x6160, 0x5510, 0x4930, 0x3CE0, 0x3180, 0x26D0, 0x1BF0, 0x12A0, 0x0950, 0x0060, 0xF680, + 0xEC40, 0xE1C0, 0xD730, 0xCC20, 0xC040, 0xB290, 0xA410, 0x9420, 0x8870, 0x8540, 0x84E0, 0x84E0, 0x84A0, 0x8490, 0x8480, 0x8470, + 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8490, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, + 0x8490, 0x84A0, 0x84A0, 0x84F0, 0x84C0, 0x84D0, 0x84F0, 0x8540, 0x8610, 0x8800, 0x8BC0, 0x90E0, 0x92A0, 0x9240, 0x8FB0, 0x8CD0, + 0x8A40, 0x8830, 0x8710, 0x8670, 0x8620, 0x85F0, 0x8600, 0x8630, 0x86B0, 0x87B0, 0x89F0, 0x8EE0, 0x9670, 0x9F90, 0xA7D0, 0xAFA0, + 0xB560, 0xB9D0, 0xBC60, 0xBCE0, 0xBBF0, 0xB9A0, 0xB5E0, 0xB1D0, 0xAD70, 0xA8B0, 0xA460, 0x9FB0, 0x9B10, 0x96C0, 0x92E0, 0x8F10, + 0x8C30, 0x89F0, 0x88B0, 0x87F0, 0x8790, 0x8780, 0x87B0, 0x8820, 0x88D0, 0x89A0, 0x8A90, 0x8C30, 0x8E50, 0x9170, 0x9590, 0x9940, + 0x9E40, 0xA260, 0xA530, 0xA840, 0xA9F0, 0xAAE0, 0xABF0, 0xADC0, 0xB020, 0xB2B0, 0xB530, 0xB840, 0xBB40, 0xBDF0, 0xC0B0, 0xC370, + 0xC5F0, 0xC870, 0xCB20, 0xCDD0, 0xD080, 0xD3C0, 0xD7D0, 0xDBF0, 0xDFF0, 0xE370, 0xE660, 0xE810, 0xE910, 0xE9A0, 0xE9E0, 0xE980, + 0xE930, 0xE8A0, 0xE850, 0xE7E0, 0xE780, 0xE730, 0xE6E0, 0xE590, 0xE4B0, 0xE3E0, 0xE380, 0xE3B0, 0xE490, 0xE510, 0xE680, 0xE680, + 0xE680, 0xE650, 0xE680, 0xE630, 0xE560, 0xE4D0, 0xE480, 0xE440, 0xE3A0, 0xE310, 0xE330, 0xE3D0, 0xE4C0, 0xE610, 0xE720, 0xE830, + 0xE930, 0xEA80, 0xEBC0, 0xED00, 0xEDB0, 0xEDD0, 0xEE20, 0xEDD0, 0xEDD0, 0xED90, 0xECC0, 0xEBD0, 0xEA90, 0xE990, 0xE870, 0xE770, + 0xE6D0, 0xE5C0, 0xE4C0, 0xE450, 0xE3D0, 0xE3E0, 0xE400, 0xE4D0, 0xE580, 0xE660, 0xE750, 0xE870, 0xE9E0, 0xEBE0, 0xEDB0, 0xF080, + 0xF2D0, 0xF620, 0xF980, 0xFD90, 0x00C0, 0x0490, 0x0830, 0x0BB0, 0x0EE0, 0x1260, 0x16F0, 0x1AA0, 0x1E70, 0x2270, 0x25B0, 0x27A0, + 0x29C0, 0x2BB0, 0x2D30, 0x2EE0, 0x3090, 0x31E0, 0x3340, 0x3480, 0x35F0, 0x36D0, 0x37E0, 0x3A00, 0x3C90, 0x3F80, 0x4420, 0x4980, + 0x4F50, 0x5670, 0x5DB0, 0x64F0, 0x6B90, 0x71E0, 0x7690, 0x7A00, 0x7B70, 0x7BB0, 0x7A80, 0x7740, 0x7230, 0x6B70, 0x6250, 0x58B0, + 0x4D40, 0x4220, 0x36C0, 0x2C50, 0x2280, 0x1AA0, 0x13A0, 0x0CE0, 0x06C0, 0xFF20, 0xF650, 0xEB20, 0xDCE0, 0xCAC0, 0xB470, 0x9A80, + 0x86E0, 0x84E0, 0x84A0, 0x8480, 0x8490, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83E0, + 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x83A0, 0x8380, + 0x8380, 0x8370, 0x8370, 0x8370, 0x8360, 0x8390, 0x8360, 0x8360, 0x8360, 0x8370, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, + 0x8390, 0x83A0, 0x8370, 0x8380, 0x83B0, 0x8390, 0x8380, 0x8390, 0x8390, 0x8380, 0x8380, 0x83B0, 0x8380, 0x8380, 0x8380, 0x8390, + 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, + 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8470, 0x8430, 0x8430, 0x8440, + 0x8430, 0x8440, 0x8450, 0x8460, 0x8460, 0x8470, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, 0x84D0, + 0x84E0, 0x84E0, 0x8500, 0x8550, 0x86B0, 0x94F0, 0xAFF0, 0xCBD0, 0xE440, 0xF480, 0xFAF0, 0xF8E0, 0xF170, 0xEA90, 0xE560, 0xE4F0, + 0xE8F0, 0xEEF0, 0xF6E0, 0xFE40, 0x03D0, 0x0810, 0x09A0, 0x0A30, 0x08D0, 0x0760, 0x05E0, 0x04D0, 0x05E0, 0x0900, 0x0E40, 0x1650, + 0x2000, 0x2B80, 0x3910, 0x46B0, 0x5660, 0x6650, 0x7590, 0x7EE0, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, + 0x7F50, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F70, 0x7F20, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, + 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EF0, + 0x7EB0, 0x7EF0, 0x7EF0, 0x7F50, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F30, 0x7EF0, 0x7F00, 0x7F10, 0x7F20, 0x7F10, + 0x7EB0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, + 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7EF0, 0x7F60, 0x7F20, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, + 0x7EF0, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7ED0, 0x7F10, 0x7F60, 0x7F00, 0x7F30, 0x7F00, 0x7F00, + 0x7F50, 0x7EF0, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, 0x7F30, + 0x7EC0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7EF0, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, + 0x7F70, 0x7F00, 0x7EE0, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7EE0, 0x7F00, 0x7EE0, 0x7F30, 0x7F10, 0x7ED0, 0x7ED0, 0x7EB0, 0x7F20, + 0x7EF0, 0x7E90, 0x7EE0, 0x7F20, 0x7E60, 0x7890, 0x7160, 0x6A80, 0x6380, 0x5CB0, 0x57C0, 0x5300, 0x5010, 0x4DB0, 0x4BE0, 0x4C50, + 0x4B80, 0x4B80, 0x4B00, 0x4910, 0x4830, 0x4670, 0x4460, 0x41B0, 0x3FB0, 0x3E60, 0x3C50, 0x39F0, 0x3770, 0x3500, 0x32D0, 0x30B0, + 0x2EC0, 0x2D50, 0x2AB0, 0x2840, 0x2560, 0x2230, 0x1E90, 0x1B20, 0x1840, 0x1390, 0x1040, 0x0D80, 0x0AF0, 0x0910, 0x0740, 0x05C0, + 0x0550, 0x0530, 0x0590, 0x0590, 0x0570, 0x0620, 0x06B0, 0x0750, 0x07F0, 0x08C0, 0x0A40, 0x0C00, 0x0E60, 0x0FF0, 0x1190, 0x1380, + 0x15E0, 0x1890, 0x1AD0, 0x1C70, 0x1E80, 0x1F60, 0x1EA0, 0x1C20, 0x1770, 0x1110, 0x0890, 0xFF60, 0xF4D0, 0xE830, 0xDC40, 0xCF00, + 0xC090, 0xB190, 0xA1A0, 0x9250, 0x8850, 0x8570, 0x84F0, 0x84D0, 0x84B0, 0x84A0, 0x84A0, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, + 0x8460, 0x8470, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, + 0x84E0, 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x85D0, 0x8980, 0x9930, 0xAAE0, 0xBCE0, 0xCFD0, 0xE110, 0xF2B0, 0x0420, 0x16B0, 0x2930, + 0x3BF0, 0x4E60, 0x60D0, 0x7500, 0x7EE0, 0x7F50, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, + 0x7F20, 0x7F10, 0x7F10, 0x5FF0, 0x3260, 0x0190, 0xD6B0, 0xAE80, 0x8C40, 0x8500, 0x84B0, 0x8490, 0x8470, 0x8470, 0x8460, 0x8460, + 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84C0, 0x84F0, 0x8530, 0x8620, 0x8A00, 0x9670, 0xA1E0, 0xAAE0, 0xB280, + 0xBC70, 0xC970, 0xDC30, 0xF4C0, 0x1260, 0x33A0, 0x5350, 0x6D10, 0x7B90, 0x7EC0, 0x7A50, 0x67B0, 0x4A40, 0x2740, 0x0180, 0xDA90, + 0xAE80, 0x8750, 0x84B0, 0x8470, 0x8450, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, + 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x8400, 0x8400, 0x8410, 0x83F0, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x83F0, 0x8430, + 0x8440, 0x83F0, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x8520, 0x86F0, + 0x9880, 0xB440, 0xCE20, 0xE650, 0xFD20, 0x1260, 0x2630, 0x38C0, 0x4A90, 0x59D0, 0x6840, 0x7500, 0x7E30, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F30, + 0x7F40, 0x7F10, 0x7EB0, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7F00, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, + 0x7ED0, 0x7F10, 0x7EF0, 0x7F50, 0x7F20, 0x7EC0, 0x7F20, 0x7EF0, 0x7F10, 0x7EE0, 0x7E70, 0x7F10, 0x7EE0, 0x7F20, 0x7ED0, 0x7EB0, + 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F00, 0x7F40, + 0x7ED0, 0x7F10, 0x7F30, 0x7EE0, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, + 0x7EF0, 0x7EE0, 0x7EF0, 0x7F50, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7F10, 0x7F20, 0x7EA0, + 0x7F00, 0x7EF0, 0x7F20, 0x7F20, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, + 0x7F10, 0x7F20, 0x7EF0, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7F50, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F30, 0x7ED0, 0x7E90, + 0x7F10, 0x7F20, 0x7F40, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, + 0x7F10, 0x7F10, 0x7F30, 0x7F00, 0x7F40, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F80, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, + 0x7ED0, 0x7F00, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, 0x7F00, 0x7ED0, 0x7F30, 0x7F00, 0x7EA0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, + 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F40, + 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7EE0, 0x7F40, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, + 0x7F60, 0x7ED0, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7EE0, 0x7F70, + 0x7EF0, 0x7F20, 0x7F20, 0x7EF0, 0x7F70, 0x7EE0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F30, 0x7F10, + 0x7F00, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7ED0, 0x7EF0, 0x7F30, 0x7EF0, 0x7EB0, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7F00, 0x7F10, 0x7F00, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F90, 0x7F00, + 0x7EE0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x79E0, 0x7110, + 0x6680, 0x5990, 0x4920, 0x3850, 0x2580, 0x11A0, 0xFBE0, 0xE2F0, 0xCA50, 0xAF80, 0x9470, 0x8660, 0x84E0, 0x84B0, 0x8490, 0x8480, + 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x83E0, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, 0x8400, 0x83B0, + 0x8400, 0x8400, 0x8420, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, + 0x84D0, 0x84A0, 0x84B0, 0x84D0, 0x84F0, 0x85B0, 0x88F0, 0x9530, 0xA320, 0xB0A0, 0xBBA0, 0xC530, 0xCCB0, 0xD120, 0xD390, 0xD470, + 0xD360, 0xD220, 0xD010, 0xCD30, 0xCA90, 0xC830, 0xC710, 0xC200, 0xB060, 0x8FE0, 0x84E0, 0x8490, 0x8460, 0x8430, 0x8430, 0x8420, + 0x8410, 0x8400, 0x8400, 0x83E0, 0x8400, 0x83E0, 0x83E0, 0x83D0, 0x83F0, 0x83C0, 0x83C0, 0x83A0, 0x83B0, 0x83C0, 0x83C0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83F0, + 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8420, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83E0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, + 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83D0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, 0x8440, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x84B0, + 0x84B0, 0x84C0, 0x84F0, 0x8530, 0x85C0, 0x87B0, 0x8F00, 0x9D10, 0xAB20, 0xB880, 0xC430, 0xCF00, 0xD640, 0xDB10, 0xDDB0, 0xDEE0, + 0xDFE0, 0xE0A0, 0xE150, 0xE0F0, 0xDE50, 0xD7F0, 0xCD20, 0xBCE0, 0xA810, 0x9000, 0x85A0, 0x84D0, 0x84A0, 0x8490, 0x8480, 0x8480, + 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8460, 0x8490, 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84D0, + 0x8510, 0x8670, 0x9510, 0xB180, 0xCF10, 0xEE60, 0x0FA0, 0x32B0, 0x5900, 0x7760, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F00, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, + 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F70, 0x7F20, 0x7EC0, 0x7F00, + 0x7F10, 0x7EF0, 0x7EF0, 0x7E70, 0x7EF0, 0x7EC0, 0x7EE0, 0x7ED0, 0x7E80, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7ED0, 0x7F10, + 0x7F00, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F30, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, + 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7F40, 0x7EF0, 0x7EE0, 0x7F40, 0x7F10, 0x7F40, 0x7F00, 0x7EC0, 0x7EF0, + 0x7F00, 0x7F50, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7E90, 0x7F00, 0x7EE0, + 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F00, 0x7F20, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7F30, + 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x73F0, 0x6290, 0x50E0, 0x3EF0, 0x2D50, 0x19F0, 0x09A0, + 0xFA40, 0xECB0, 0xE230, 0xD960, 0xD340, 0xCD90, 0xC9D0, 0xC810, 0xC650, 0xC630, 0xC660, 0xC660, 0xC6F0, 0xC750, 0xC800, 0xC860, + 0xC810, 0xC820, 0xC760, 0xC6D0, 0xC6C0, 0xC6E0, 0xC8E0, 0xCB40, 0xCE30, 0xD1C0, 0xD440, 0xD730, 0xD9E0, 0xDBC0, 0xDD50, 0xDED0, + 0xE0E0, 0xE2E0, 0xE5D0, 0xE910, 0xEC50, 0xEF90, 0xF200, 0xF3A0, 0xF4B0, 0xF480, 0xF3E0, 0xF2C0, 0xF0F0, 0xEF60, 0xECE0, 0xEA80, + 0xE7F0, 0xE4A0, 0xE1F0, 0xDEC0, 0xDB90, 0xD800, 0xD4D0, 0xD180, 0xCE10, 0xCBA0, 0xC8E0, 0xC5D0, 0xC360, 0xBFA0, 0xBD80, 0xBB10, + 0xB8E0, 0xB6D0, 0xB4A0, 0xB310, 0xB120, 0xAF10, 0xACD0, 0xAAE0, 0xA8D0, 0xA6F0, 0xA510, 0xA320, 0x9FF0, 0x9C70, 0x9900, 0x94F0, + 0x9140, 0x8D70, 0x8A10, 0x87E0, 0x8680, 0x85C0, 0x8560, 0x8520, 0x8500, 0x8520, 0x84E0, 0x84E0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84D0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, + 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84E0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84D0, 0x8500, 0x8530, + 0x8580, 0x8650, 0x8830, 0x8CA0, 0x9400, 0x9CB0, 0xA430, 0xAC10, 0xB370, 0xBA90, 0xC390, 0xCBD0, 0xD580, 0xDEC0, 0xE840, 0xF210, + 0xFC10, 0x06B0, 0x1140, 0x1CB0, 0x26A0, 0x2FC0, 0x39F0, 0x4290, 0x4A70, 0x5260, 0x58D0, 0x5F30, 0x6480, 0x6890, 0x6C90, 0x7020, + 0x7440, 0x7890, 0x7BB0, 0x7E30, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7EC0, 0x7F10, + 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7F10, + 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7F00, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7EA0, + 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F00, 0x7EE0, 0x7F50, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F70, 0x7ED0, 0x7EB0, 0x7F00, + 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F40, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F70, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7EE0, + 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7ED0, 0x7EB0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7E70, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, + 0x7F10, 0x7F00, 0x7F10, 0x7E90, 0x7EE0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F20, + 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F10, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7ED0, 0x7F30, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F20, 0x7F70, 0x7ED0, 0x7EB0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7E90, 0x7F00, + 0x7F10, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, + 0x7F10, 0x7F20, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7F30, 0x7F10, 0x7F70, 0x7D20, 0x5D10, 0x40B0, 0x2400, 0x0840, 0xEE30, 0xD660, + 0xC1C0, 0xAF00, 0x9F50, 0x9250, 0x8B60, 0x8820, 0x86D0, 0x85F0, 0x85D0, 0x8580, 0x8550, 0x8510, 0x84F0, 0x84D0, 0x84F0, 0x84B0, + 0x84A0, 0x8490, 0x84B0, 0x8480, 0x8470, 0x8430, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84E0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, + 0x8490, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8460, 0x8470, 0x8470, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8460, 0x8490, 0x8410, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8470, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x85B0, + 0x87B0, 0x8E70, 0x9950, 0xA330, 0xAAD0, 0xB040, 0xB350, 0xB4B0, 0xB570, 0xB470, 0xB260, 0xAF80, 0xABD0, 0xA810, 0xA2B0, 0x9D40, + 0x96B0, 0x9070, 0x8B90, 0x8860, 0x86D0, 0x8600, 0x85D0, 0x8570, 0x8560, 0x8560, 0x8590, 0x85C0, 0x8650, 0x87A0, 0x8B40, 0x9380, + 0x9F10, 0xAAB0, 0xB620, 0xC0D0, 0xC940, 0xCF80, 0xD360, 0xD4B0, 0xD360, 0xCFB0, 0xCA90, 0xC3B0, 0xBAE0, 0xB010, 0xA330, 0x94A0, + 0x89A0, 0x85B0, 0x84F0, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84F0, 0x8670, 0x9DC0, 0xBF90, 0xE0F0, 0x03B0, 0x2A70, 0x4E90, 0x6FD0, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F70, 0x7F20, 0x7F10, 0x7F30, + 0x7F00, 0x7F50, 0x7EF0, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F10, 0x7ED0, 0x7EB0, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, + 0x7F60, 0x7F10, 0x7F20, 0x7F10, 0x7EF0, 0x7F30, 0x7F30, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F40, 0x7F50, 0x7EB0, 0x7F00, 0x7EE0, 0x7B80, + 0x6630, 0x4E00, 0x3540, 0x1B30, 0x0420, 0xEFA0, 0xDC00, 0xC950, 0xB610, 0xA220, 0x8FB0, 0x8710, 0x8530, 0x84F0, 0x84E0, 0x84E0, + 0x84E0, 0x84F0, 0x8530, 0x8570, 0x8600, 0x8730, 0x8900, 0x8BE0, 0x8E70, 0x90B0, 0x9230, 0x9310, 0x92D0, 0x9180, 0x8FF0, 0x8E30, + 0x8D40, 0x8C70, 0x8C10, 0x8C20, 0x8BD0, 0x8B80, 0x8B70, 0x8BB0, 0x8C20, 0x8CA0, 0x8D70, 0x8F10, 0x90C0, 0x9300, 0x9530, 0x9680, + 0x97B0, 0x9880, 0x99F0, 0x9B50, 0x9CB0, 0x9E20, 0x9FA0, 0xA0B0, 0xA1D0, 0xA220, 0xA290, 0xA2E0, 0xA370, 0xA3F0, 0xA300, 0xA160, + 0x9F00, 0x9B60, 0x96B0, 0x9150, 0x8BC0, 0x87E0, 0x85E0, 0x8530, 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x8490, 0x8490, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, 0x8470, 0x8480, 0x84A0, 0x84E0, 0x8790, 0xB3E0, 0xE6B0, 0x1220, 0x37F0, + 0x5850, 0x7100, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, + 0x7EA0, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, + 0x7F80, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7BB0, 0x4AA0, 0x1F10, 0xF790, + 0xD690, 0xBB30, 0xA890, 0x9D10, 0x9B60, 0xA110, 0xAB60, 0xB7E0, 0xC2A0, 0xCAA0, 0xCE90, 0xCCA0, 0xC730, 0xC110, 0xBB30, 0xB9E0, + 0xBCE0, 0xC510, 0xD2E0, 0xE370, 0xF380, 0x0080, 0x0800, 0x12E0, 0x1A70, 0x24E0, 0x31C0, 0x4090, 0x4F10, 0x5D30, 0x6960, 0x7390, + 0x7C80, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F50, 0x7F00, 0x7F20, 0x7EF0, 0x7F00, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, + 0x7F00, 0x7F90, 0x7F10, 0x7EF0, 0x7F10, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EE0, 0x7F00, 0x7EF0, + 0x7F30, 0x7F00, 0x7E70, 0x7EC0, 0x7EF0, 0x7F10, 0x7EF0, 0x7E90, 0x7ED0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F20, + 0x7F10, 0x7F70, 0x7F00, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7F10, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, 0x7F00, 0x7F10, + 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7E20, 0x7C40, 0x7A50, 0x7800, 0x75E0, 0x7440, 0x7210, 0x7100, 0x6F20, 0x6DD0, 0x6CB0, 0x6B70, + 0x6B20, 0x6A00, 0x6910, 0x6820, 0x6700, 0x6650, 0x6520, 0x63C0, 0x6290, 0x60B0, 0x5F70, 0x5D60, 0x5AD0, 0x58B0, 0x54E0, 0x5190, + 0x4D30, 0x4820, 0x4340, 0x3DD0, 0x38B0, 0x32E0, 0x2D20, 0x2730, 0x20E0, 0x1B10, 0x1490, 0x0F30, 0x09A0, 0x04A0, 0x00D0, 0xFCD0, + 0xF790, 0xF250, 0xEBF0, 0xE5F0, 0xDED0, 0xD6F0, 0xD050, 0xC880, 0xC0C0, 0xB780, 0xAE90, 0xA650, 0x9DB0, 0x95C0, 0x8E60, 0x8960, + 0x86C0, 0x85B0, 0x8530, 0x8500, 0x84E0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8530, + 0x85E0, 0x8800, 0x8F90, 0x9BF0, 0xA910, 0xB400, 0xBBF0, 0xC1F0, 0xC5F0, 0xC820, 0xC760, 0xC4E0, 0xC0F0, 0xBAB0, 0xB450, 0x9DA0, + 0x9A10, 0x99F0, 0x9BA0, 0xA080, 0xA7D0, 0xB060, 0xBBE0, 0xC770, 0xD500, 0xE250, 0xF090, 0xFFB0, 0x0EC0, 0x1E70, 0x2E00, 0x3E90, + 0x4E50, 0x5C70, 0x69C0, 0x7410, 0x7BB0, 0x7F00, 0x7EC0, 0x7EC0, 0x7EE0, 0x7F30, 0x7F10, 0x7E90, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F10, + 0x7F00, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7EC0, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F00, + 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, 0x7F70, + 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F20, 0x7EE0, + 0x7E90, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F20, 0x7F10, 0x7F10, 0x7F20, + 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7EB0, 0x63E0, 0x4780, 0x2A10, 0x0D20, 0xF1F0, 0xD980, 0xC490, 0xB480, 0xA5F0, + 0x99A0, 0x8EC0, 0x87D0, 0x8590, 0x8510, 0x84E0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84C0, 0x84B0, 0x8490, 0x8480, + 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, + 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x83E0, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x8500, 0x8550, + 0x8680, 0x8AB0, 0x9790, 0xA740, 0xB7D0, 0xC880, 0xDA50, 0xEC20, 0xFD00, 0x0D50, 0x1B80, 0x2760, 0x31F0, 0x3B10, 0x4470, 0x4DC0, + 0x5810, 0x6310, 0x6E40, 0x7820, 0x7E90, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F80, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F20, 0x7F20, 0x7EF0, + 0x7ED0, 0x7F10, 0x7F20, 0x7EF0, 0x7EB0, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7C40, 0x6680, 0x4C30, 0x3370, 0x1AB0, 0x0580, + 0xF3A0, 0xE4D0, 0xDA50, 0xD220, 0xCC10, 0xC650, 0xC180, 0xBC50, 0xB5C0, 0xADD0, 0xA560, 0x9CC0, 0x9520, 0x8EA0, 0x89F0, 0x8790, + 0x8640, 0x85B0, 0x84F0, 0x8530, 0x8520, 0x8510, 0x8540, 0x8510, 0x8510, 0x8530, 0x8570, 0x85B0, 0x86B0, 0x8980, 0x90A0, 0x9A40, + 0xA450, 0xAD50, 0xB630, 0xBE70, 0xC660, 0xCF10, 0xD7F0, 0xE0E0, 0xE940, 0xF1D0, 0xF8D0, 0xFE80, 0x0310, 0x0750, 0x0B30, 0x0EE0, + 0x10F0, 0x1250, 0x1400, 0x1450, 0x1470, 0x13E0, 0x11C0, 0x0F90, 0x0D30, 0x0B00, 0x0960, 0x0830, 0x0890, 0x09A0, 0x0B80, 0x0EA0, + 0x1230, 0x16C0, 0x1B80, 0x2010, 0x24E0, 0x28F0, 0x2DB0, 0x3250, 0x36A0, 0x3B50, 0x3FF0, 0x4570, 0x49C0, 0x4D90, 0x5070, 0x5300, + 0x56C0, 0x59F0, 0x5D70, 0x6100, 0x6440, 0x67B0, 0x6AE0, 0x6D90, 0x70B0, 0x7340, 0x7680, 0x7980, 0x7BB0, 0x7DE0, 0x7E70, 0x7F10, + 0x7F00, 0x7F20, 0x7ED0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7ED0, 0x7F30, 0x7F00, + 0x7F40, 0x7F30, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, + 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F60, 0x7EF0, 0x7E90, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F00, 0x7F20, 0x7F20, 0x7E90, 0x7F00, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F00, 0x7F10, + 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F60, 0x7F00, + 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, + 0x7F10, 0x7D60, 0x70A0, 0x62E0, 0x5510, 0x4760, 0x3A20, 0x2DF0, 0x2110, 0x1520, 0x06F0, 0xF880, 0xE770, 0xD2C0, 0xBB10, 0xA190, + 0x8AB0, 0x84F0, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8480, 0x84B0, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8480, + 0x8480, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, + 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x8400, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84D0, 0x8500, 0x8570, 0x8760, + 0x9100, 0x9F00, 0xA8E0, 0xAE20, 0xAE30, 0xA9D0, 0xA180, 0x9750, 0x8D00, 0x8720, 0x8550, 0x84F0, 0x84C0, 0x84C0, 0x8490, 0x8490, + 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8480, 0x8450, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, + 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8420, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, + 0x8490, 0x8480, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8520, 0x8580, 0x8650, 0x8830, 0x8CF0, 0x93F0, 0x9BC0, 0xA250, + 0xA920, 0xAE40, 0xB340, 0xB830, 0xBC30, 0xC090, 0xC3F0, 0xC710, 0xCA40, 0xCC10, 0xCD50, 0xCDE0, 0xCDF0, 0xCED0, 0xCFD0, 0xD100, + 0xD230, 0xD330, 0xD450, 0xD560, 0xD600, 0xD5D0, 0xD4C0, 0xD400, 0xD280, 0xD130, 0xCFC0, 0xCEF0, 0xCE30, 0xCCB0, 0xC7E0, 0xC660, + 0xC550, 0xC480, 0xC340, 0xC280, 0xC2E0, 0xC320, 0xC4B0, 0xC580, 0xC6E0, 0xC820, 0xC8A0, 0xCA00, 0xCB20, 0xCC90, 0xCF80, 0xD270, + 0xD540, 0xD7B0, 0xDA50, 0xDCB0, 0xDF60, 0xE210, 0xE5B0, 0xEA30, 0xEE60, 0xF300, 0xF660, 0xF890, 0xFA30, 0xFB30, 0xFAB0, 0xFA50, + 0xF9A0, 0xF990, 0xFB40, 0xFE40, 0x0270, 0x0700, 0x0B90, 0x0F90, 0x1190, 0x1250, 0x10E0, 0x0D90, 0x0880, 0x0240, 0xFBD0, 0xF450, + 0xEC80, 0xE3C0, 0xDB00, 0xD180, 0xC6E0, 0xBC00, 0xAFA0, 0xA200, 0x92F0, 0x8850, 0x8550, 0x84E0, 0x84B0, 0x84A0, 0x8490, 0x8480, + 0x8480, 0x8470, 0x8470, 0x8470, 0x8440, 0x8470, 0x8470, 0x8450, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, + 0x84E0, 0x8500, 0x8540, 0x8600, 0x8810, 0x8E30, 0x9850, 0xA180, 0xAAB0, 0xB260, 0xB930, 0xBF30, 0xC590, 0xCB00, 0xD000, 0xD530, + 0xDA30, 0xDF80, 0xE3D0, 0xE7B0, 0xEB00, 0xEE80, 0xF210, 0xF610, 0xFA30, 0xFE00, 0x01B0, 0x0520, 0x0880, 0x0BB0, 0x0DE0, 0x0F70, + 0x1070, 0x1120, 0x11D0, 0x1280, 0x1330, 0x1440, 0x1580, 0x1670, 0x16B0, 0x1750, 0x1810, 0x1890, 0x1980, 0x1AB0, 0x1C00, 0x1D70, + 0x1F50, 0x2110, 0x2270, 0x2450, 0x25A0, 0x2770, 0x2970, 0x2BB0, 0x2DB0, 0x3040, 0x3320, 0x3590, 0x3800, 0x3AE0, 0x3DD0, 0x4130, + 0x4500, 0x48C0, 0x4C10, 0x4F30, 0x5190, 0x54C0, 0x5730, 0x5A30, 0x5CE0, 0x5F50, 0x6150, 0x6310, 0x6470, 0x65A0, 0x6690, 0x67B0, + 0x68A0, 0x6930, 0x68F0, 0x68B0, 0x68E0, 0x68F0, 0x68D0, 0x6860, 0x67D0, 0x6780, 0x6700, 0x66A0, 0x6600, 0x65D0, 0x6550, 0x6440, + 0x63D0, 0x62E0, 0x6240, 0x6210, 0x6230, 0x6320, 0x6500, 0x6630, 0x66F0, 0x6770, 0x67C0, 0x6770, 0x6750, 0x6790, 0x6820, 0x68D0, + 0x6B30, 0x6E30, 0x7150, 0x75B0, 0x7980, 0x7D00, 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F20, 0x7ED0, 0x7F10, 0x7EB0, 0x7EE0, 0x7F10, + 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F60, 0x7F10, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F40, 0x7F50, 0x7EB0, 0x7F00, 0x7ED0, 0x7F30, 0x7F40, + 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7F20, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7E90, + 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F30, 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F50, + 0x7F00, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, + 0x7E90, 0x7EF0, 0x7EF0, 0x7F30, 0x7EB0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, + 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F90, 0x7F00, 0x7F20, 0x7EF0, 0x7EF0, 0x7F80, + 0x7F10, 0x7F20, 0x7F00, 0x7ED0, 0x7F30, 0x7F00, 0x7EE0, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F40, 0x7F10, + 0x7C60, 0x7A40, 0x7A50, 0x7BF0, 0x7EA0, 0x7EA0, 0x7ED0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, + 0x7F20, 0x7840, 0x6DB0, 0x6740, 0x6280, 0x6130, 0x63F0, 0x6980, 0x7110, 0x7810, 0x7D70, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F50, + 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F60, 0x7EC0, 0x7840, 0x6ED0, 0x6430, 0x57F0, 0x4AC0, 0x3C90, 0x2F30, 0x20C0, 0x15F0, 0x0F90, + 0x0F40, 0x1580, 0x2090, 0x2F70, 0x41E0, 0x5550, 0x6AB0, 0x7B70, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7E90, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7EF0, 0x7F10, 0x7E60, 0x7900, + 0x7380, 0x6FB0, 0x6D30, 0x6CC0, 0x6ED0, 0x7230, 0x7710, 0x7C30, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, + 0x7F70, 0x7F00, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F00, + 0x7EF0, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, + 0x7F10, 0x7F60, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, + 0x7F70, 0x7F00, 0x7ED0, 0x7F00, 0x7EE0, 0x7F90, 0x7EF0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, 0x7F50, + 0x7ED0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F20, 0x7ED0, 0x70B0, 0x6130, + 0x4F00, 0x3F90, 0x3280, 0x29A0, 0x2560, 0x25D0, 0x2910, 0x2F20, 0x3640, 0x3EB0, 0x46E0, 0x4F40, 0x5810, 0x60F0, 0x6940, 0x6FA0, + 0x73F0, 0x75B0, 0x73D0, 0x7010, 0x6A30, 0x6270, 0x59E0, 0x5110, 0x48B0, 0x40A0, 0x3910, 0x31B0, 0x2C20, 0x2800, 0x25D0, 0x2470, + 0x2460, 0x24C0, 0x25B0, 0x26B0, 0x26F0, 0x2720, 0x2540, 0x2350, 0x20D0, 0x1DA0, 0x1A70, 0x1600, 0x1160, 0x0D20, 0x08C0, 0x05D0, + 0x02D0, 0x0020, 0xFD90, 0xFB40, 0xF9D0, 0xF820, 0xF640, 0xF3B0, 0xF090, 0xED20, 0xE8C0, 0xE370, 0xDD20, 0xD5F0, 0xCE50, 0xC720, + 0xC020, 0xBA20, 0xB480, 0xB0A0, 0xADD0, 0xAAE0, 0xA7F0, 0xA460, 0xA040, 0x9BB0, 0x96B0, 0x9200, 0x8E10, 0x8B80, 0x89B0, 0x88D0, + 0x88A0, 0x8910, 0x8A40, 0x8C60, 0x9080, 0x9580, 0x9B40, 0xA140, 0xA7C0, 0xADF0, 0xB560, 0xBC30, 0xC2E0, 0xC900, 0xCEC0, 0xD510, + 0xDA80, 0xDF80, 0xE540, 0xE980, 0xEE20, 0xF1D0, 0xF590, 0xF990, 0xFD40, 0x00F0, 0x0420, 0x06B0, 0x0A30, 0x0C30, 0x0EA0, 0x1000, + 0x10D0, 0x10D0, 0x10E0, 0x1190, 0x1290, 0x13C0, 0x1490, 0x1520, 0x1570, 0x14F0, 0x1450, 0x1430, 0x14A0, 0x1690, 0x1850, 0x1A70, + 0x1CC0, 0x1DD0, 0x1F40, 0x2020, 0x20C0, 0x2190, 0x2290, 0x2360, 0x2310, 0x21B0, 0x1FE0, 0x1C60, 0x17C0, 0x1210, 0x0B60, 0x03A0, + 0xFA90, 0xF220, 0xEA20, 0xE190, 0xDA10, 0xD270, 0xCBA0, 0xC590, 0xC0E0, 0xBD80, 0xBB60, 0xBB30, 0xBB40, 0xBC10, 0xBEF0, 0xC2A0, + 0xC7C0, 0xCCC0, 0xD320, 0xD7C0, 0xDB90, 0xDF80, 0xE290, 0xE570, 0xE950, 0xEC00, 0xEEF0, 0xF090, 0xF1D0, 0xF200, 0xF0F0, 0xEF30, + 0xEBD0, 0xE720, 0xE120, 0xD7B0, 0xCED0, 0xC480, 0xB990, 0xAE00, 0xA200, 0x95D0, 0x8BD0, 0x86B0, 0x8550, 0x84F0, 0x84D0, 0x84B0, + 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8460, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8470, 0x8460, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84D0, 0x84F0, 0x8530, 0x85C0, 0x87E0, 0x9080, + 0x9D20, 0xA9F0, 0xB740, 0xC430, 0xD0E0, 0xDD70, 0xEA00, 0xF670, 0x0350, 0x0F60, 0x1B10, 0x2630, 0x30C0, 0x54E0, 0x5CC0, 0x63B0, + 0x6A20, 0x70D0, 0x7630, 0x7AA0, 0x7DD0, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F30, + 0x7F30, 0x7F40, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7EE0, 0x7CC0, 0x7990, 0x75E0, 0x7140, 0x6BA0, 0x6690, 0x61F0, 0x5E20, + 0x5B40, 0x58D0, 0x56D0, 0x55A0, 0x55E0, 0x56E0, 0x58C0, 0x5B50, 0x5E30, 0x6170, 0x6470, 0x6820, 0x6B50, 0x6E10, 0x7120, 0x7410, + 0x76D0, 0x7990, 0x7B70, 0x7D80, 0x7EB0, 0x7F10, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, + 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, + 0x7F40, 0x7F10, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F70, 0x7F40, 0x7EC0, 0x7F10, 0x7F40, 0x7F50, 0x7F10, 0x7E70, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7E80, 0x7EC0, + 0x7F00, 0x7F20, 0x7EE0, 0x7980, 0x7270, 0x6B70, 0x6460, 0x5E80, 0x57A0, 0x52E0, 0x4E10, 0x4900, 0x44A0, 0x3F80, 0x3910, 0x32B0, + 0x2BC0, 0x2450, 0x1D70, 0x1740, 0x12C0, 0x0F30, 0x0E20, 0x0E60, 0x0FD0, 0x1280, 0x15A0, 0x1970, 0x1D30, 0x2120, 0x25E0, 0x2B80, + 0x3330, 0x3BB0, 0x45A0, 0x5160, 0x5C40, 0x66F0, 0x70B0, 0x7930, 0x7EC0, 0x7E90, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, + 0x7EC0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7F10, + 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7BB0, 0x6DA0, 0x5F10, 0x5010, 0x4220, 0x3420, 0x26E0, 0x1AC0, 0x0F60, + 0x03D0, 0xF9A0, 0xEFA0, 0xE650, 0xDCF0, 0xD2F0, 0xC8B0, 0xBD30, 0xB010, 0x9FD0, 0x8FE0, 0x8720, 0x8520, 0x84E0, 0x84C0, 0x84C0, + 0x84A0, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, + 0x84E0, 0x8510, 0x8590, 0x8790, 0x9180, 0x9FA0, 0xABC0, 0xB700, 0xC0D0, 0xCA90, 0xD3A0, 0xDC60, 0xE4E0, 0xEE90, 0xF7E0, 0x0110, + 0x0A10, 0x11E0, 0x1840, 0x1DD0, 0x2210, 0x2530, 0x2880, 0x2B90, 0x2FA0, 0x33E0, 0x3A70, 0x4230, 0x4AD0, 0x5440, 0x5C90, 0x6580, + 0x6C20, 0x7150, 0x7610, 0x7960, 0x7C40, 0x7E50, 0x7EF0, 0x7F00, 0x7E90, 0x7ED0, 0x7D60, 0x78A0, 0x72D0, 0x6AD0, 0x61E0, 0x57E0, + 0x4C10, 0x3F40, 0x3380, 0x2800, 0x1CE0, 0x1260, 0x0950, 0x0030, 0xF750, 0xEF20, 0xE690, 0xE030, 0xDA90, 0xD5A0, 0xD290, 0xD110, + 0xD100, 0xD320, 0xD6D0, 0xDE70, 0xE750, 0xF230, 0xFEB0, 0x0C60, 0x1B70, 0x2A40, 0x39E0, 0x4820, 0x55D0, 0x7B20, 0x7ED0, 0x7EF0, + 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7960, 0x6550, 0x4C50, + 0x3100, 0x1480, 0xF650, 0xDB30, 0xC040, 0xA750, 0x9020, 0x8690, 0x8510, 0x84E0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x84F0, 0x8510, 0x8550, 0x8600, 0x87D0, 0x8DF0, 0x9850, 0xA390, + 0xADF0, 0xB820, 0xC1F0, 0xCB70, 0xD490, 0xDCC0, 0xE5A0, 0xECC0, 0xF2D0, 0xF850, 0xFC20, 0x00A0, 0x0390, 0x05B0, 0x07A0, 0x0740, + 0x0640, 0x0410, 0x0020, 0xFC80, 0xF790, 0xF250, 0xEC60, 0xE660, 0xDE30, 0xD4A0, 0xCA10, 0xBE10, 0xB0B0, 0xA230, 0x9340, 0x88E0, + 0x85B0, 0x8500, 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, + 0x84A0, 0x84B0, 0x84C0, 0x84F0, 0x8510, 0x8570, 0x86B0, 0x8B50, 0x9690, 0xA2D0, 0xAEE0, 0xBA00, 0xC580, 0xCF80, 0xD920, 0xE210, + 0xEBD0, 0xF570, 0xFFA0, 0x0AC0, 0x1680, 0x2400, 0x2F90, 0x39E0, 0x42B0, 0x4A00, 0x50C0, 0x5510, 0x57A0, 0x5860, 0x5500, 0x4F20, + 0x4480, 0x3690, 0x2730, 0x1660, 0x0500, 0xF4B0, 0xE530, 0xD580, 0xC820, 0xBD20, 0xB340, 0xAAF0, 0xA460, 0x9FE0, 0x9C00, 0x9920, + 0x9780, 0x9670, 0x9630, 0x9510, 0x9500, 0x9520, 0x94A0, 0x9300, 0x8F70, 0x8B70, 0x8840, 0x8650, 0x8570, 0x8510, 0x8520, 0x84D0, + 0x84C0, 0x84B0, 0x84A0, 0x84C0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x84A0, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84E0, 0x8500, 0x8530, 0x8580, 0x8660, + 0x8890, 0x8F70, 0x9AF0, 0xA710, 0xB340, 0xBE80, 0xC970, 0xD0D0, 0xD590, 0xD7D0, 0xD740, 0xD4C0, 0xCF20, 0xC770, 0xBE20, 0xB1F0, + 0xA3F0, 0x9430, 0x88B0, 0x8560, 0x84E0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8460, 0x8450, 0x8450, + 0x8460, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, + 0x8550, 0x8550, 0x85A0, 0x8620, 0x86B0, 0x8710, 0x8780, 0x87B0, 0x87C0, 0x87E0, 0x87B0, 0x8790, 0x8760, 0x8700, 0x86D0, 0x86A0, + 0x8680, 0x8670, 0x8650, 0x8630, 0x8610, 0x85F0, 0x8560, 0x8580, 0x8550, 0x8530, 0x8510, 0x84F0, 0x8500, 0x84D0, 0x84C0, 0x8480, + 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, + 0x84C0, 0x84D0, 0x8500, 0x8540, 0x8610, 0x8810, 0x8D90, 0x9770, 0xA050, 0xA890, 0xB030, 0xB560, 0xB920, 0xBAF0, 0xBC50, 0xBCC0, + 0xBC60, 0xBB10, 0xB980, 0xB6D0, 0xB3F0, 0xAF60, 0xA9C0, 0xA390, 0x9CA0, 0x94E0, 0x8DF0, 0x88F0, 0x8660, 0x8560, 0x8500, 0x84E0, + 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x84A0, + 0x84A0, 0x84C0, 0x84D0, 0x8500, 0x8540, 0x85F0, 0x8750, 0x8A20, 0x8E60, 0x9370, 0x9960, 0x9F80, 0xA5F0, 0xACD0, 0xB2A0, 0xB690, + 0xB820, 0xB6D0, 0xB190, 0xA7E0, 0x9B20, 0x8D70, 0x8630, 0x8500, 0x84C0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8480, + 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, + 0x84B0, 0x84D0, 0x84F0, 0x8530, 0x8600, 0x8730, 0x8AB0, 0x9160, 0x98C0, 0x9F80, 0xA600, 0xAC70, 0xB260, 0xB7F0, 0xBCE0, 0xC1C0, + 0xC670, 0xCB20, 0xCFB0, 0xD400, 0xD820, 0xDBA0, 0xDEB0, 0xE1B0, 0xE500, 0xE780, 0xE8E0, 0xE960, 0xE6E0, 0xE500, 0xE310, 0xE050, + 0xDD10, 0xD930, 0xD4C0, 0xD0D0, 0xCCE0, 0xC880, 0xC560, 0xC2E0, 0xBFE0, 0xBCA0, 0xB9D0, 0xB740, 0xB490, 0xB200, 0xAFD0, 0xAE20, + 0xADE0, 0xADB0, 0xADF0, 0xADF0, 0xAE40, 0xAE90, 0xAEA0, 0xAED0, 0xAFC0, 0xB090, 0xB190, 0xB2C0, 0xB4C0, 0xB6B0, 0xB920, 0xBBA0, + 0xBE00, 0xBFF0, 0xC220, 0xC430, 0xC710, 0xC9F0, 0xCD00, 0xD050, 0xD3F0, 0xD6D0, 0xDA40, 0xDC70, 0xDE80, 0xE0F0, 0xE360, 0xE590, + 0xE750, 0xE9A0, 0xEB80, 0xED80, 0xEFC0, 0xF180, 0xF330, 0xF470, 0xF5E0, 0xF7C0, 0xF930, 0xFAD0, 0xFC60, 0xFCF0, 0xFD30, 0xFD80, + 0xFD60, 0xFD90, 0xFD30, 0xFD90, 0xFDA0, 0xFDB0, 0xFDB0, 0xFCE0, 0xFCD0, 0xFCB0, 0xFC10, 0xFC20, 0xFBC0, 0xFC60, 0xFCD0, 0xFCD0, + 0xFDB0, 0xFE20, 0xFEA0, 0xFE90, 0xFE60, 0xFF60, 0x0040, 0x0190, 0x02A0, 0x0420, 0x0640, 0x0860, 0x0A70, 0x0CC0, 0x0EF0, 0x11F0, + 0x1560, 0x1870, 0x1B70, 0x1F80, 0x23F0, 0x28F0, 0x2EA0, 0x3510, 0x3AD0, 0x4130, 0x4660, 0x4C50, 0x5200, 0x5640, 0x5B60, 0x5F90, + 0x63B0, 0x67A0, 0x6A50, 0x6D30, 0x6F60, 0x7070, 0x71C0, 0x7210, 0x72A0, 0x7300, 0x7210, 0x7150, 0x6F60, 0x6E00, 0x6BB0, 0x68B0, + 0x6660, 0x6340, 0x6080, 0x5DB0, 0x5AD0, 0x5910, 0x5800, 0x5800, 0x5950, 0x5B90, 0x5F70, 0x63C0, 0x68F0, 0x6F20, 0x74E0, 0x7B60, + 0x7ED0, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7280, 0x6460, 0x55C0, 0x44A0, + 0x3560, 0x26F0, 0x1910, 0x0DB0, 0x02E0, 0xFA10, 0xF400, 0xEF60, 0xEC90, 0xEB60, 0xEAB0, 0xEB00, 0xEBD0, 0xED30, 0xEEB0, 0xF020, + 0xF350, 0xF700, 0xFB40, 0x00B0, 0x05E0, 0x0BA0, 0x1090, 0x1610, 0x1BE0, 0x2140, 0x2810, 0x2E80, 0x3570, 0x3B40, 0x40D0, 0x45F0, + 0x49C0, 0x4CD0, 0x4F10, 0x5040, 0x50D0, 0x5010, 0x4E90, 0x4C60, 0x4940, 0x4610, 0x4100, 0x3A70, 0x3270, 0x2910, 0x1E40, 0x1270, + 0x05B0, 0xF920, 0xEC20, 0xDFC0, 0xD450, 0xC8A0, 0xBF20, 0xB610, 0xAE20, 0xA6F0, 0xA020, 0x9B80, 0x9770, 0x9440, 0x9170, 0x8F00, + 0x8D40, 0x8B90, 0x8A80, 0x8990, 0x88F0, 0x88A0, 0x8830, 0x87F0, 0x87D0, 0x8790, 0x8780, 0x8740, 0x8700, 0x86C0, 0x86B0, 0x8710, + 0x8770, 0x87F0, 0x88B0, 0x89E0, 0x8C00, 0x8EE0, 0x9270, 0x9600, 0x98A0, 0x9A70, 0x9B90, 0x9C20, 0x9C30, 0x9BF0, 0x9BF0, 0x9A70, + 0x99B0, 0x9850, 0x9620, 0x9480, 0x9240, 0x90F0, 0x8FA0, 0x8E50, 0x8DA0, 0x8D00, 0x8C40, 0x8B90, 0x8B00, 0x8AA0, 0x8A60, 0x8A50, + 0x8AB0, 0x8B70, 0x8CC0, 0x8F10, 0x9210, 0x95C0, 0x9A10, 0x9EB0, 0xA320, 0xA950, 0xAF30, 0xB4A0, 0xBB60, 0xC150, 0xC800, 0xCEA0, + 0xD470, 0xDAB0, 0xE140, 0xE750, 0xED70, 0xF1D0, 0xF6C0, 0xFAB0, 0xFF30, 0x0450, 0x0920, 0x0F10, 0x13C0, 0x18C0, 0x1DF0, 0x23D0, + 0x2AA0, 0x30C0, 0x36F0, 0x3BB0, 0x3FF0, 0x44B0, 0x4870, 0x4CF0, 0x50D0, 0x5430, 0x5870, 0x5C00, 0x5F70, 0x6330, 0x65C0, 0x68C0, + 0x6B50, 0x6D70, 0x6FE0, 0x7110, 0x72B0, 0x7430, 0x7540, 0x7630, 0x7600, 0x7620, 0x7650, 0x7650, 0x76B0, 0x7640, 0x75C0, 0x7520, + 0x7420, 0x7380, 0x7290, 0x7170, 0x6FE0, 0x6D10, 0x6B80, 0x68A0, 0x6510, 0x62B0, 0x5EB0, 0x5B60, 0x57F0, 0x5490, 0x50B0, 0x4C80, + 0x4890, 0x44F0, 0x4140, 0x3E20, 0x3B80, 0x3980, 0x3760, 0x3590, 0x34F0, 0x33B0, 0x33D0, 0x3390, 0x3430, 0x3540, 0x3590, 0x3710, + 0x38A0, 0x3A40, 0x3C30, 0x3DE0, 0x3F60, 0x4000, 0x40B0, 0x41B0, 0x4240, 0x42D0, 0x4270, 0x4100, 0x3FD0, 0x3E00, 0x3C60, 0x3C10, + 0x3BD0, 0x3CB0, 0x3D60, 0x3E50, 0x3F50, 0x4090, 0x4210, 0x4320, 0x4460, 0x45D0, 0x4710, 0x4770, 0x4660, 0x4470, 0x4230, 0x3EB0, + 0x3B70, 0x3780, 0x3380, 0x2FA0, 0x2C00, 0x28F0, 0x2600, 0x21F0, 0x1F10, 0x1B70, 0x1830, 0x14C0, 0x1150, 0x0DB0, 0x0860, 0x0290, + 0xFB10, 0xF2F0, 0xEB20, 0xE330, 0xDCD0, 0xD820, 0xD4C0, 0xD330, 0xD300, 0xD3B0, 0xD450, 0xD5E0, 0xD8C0, 0xDC60, 0xE0B0, 0xE5B0, + 0xEBC0, 0xF380, 0xFC40, 0x04F0, 0x0E80, 0x1820, 0x22C0, 0x2D90, 0x37F0, 0x4160, 0x48F0, 0x5150, 0x5670, 0x5A60, 0x5CF0, 0x5D90, + 0x5D20, 0x5AA0, 0x55F0, 0x4ED0, 0x4420, 0x39A0, 0x2D50, 0x2030, 0x11E0, 0x01F0, 0xF270, 0xE280, 0xD3A0, 0xC4D0, 0xB840, 0xACB0, + 0xA250, 0x9890, 0x90D0, 0x8B30, 0x8840, 0x86C0, 0x8600, 0x85C0, 0x8590, 0x8590, 0x8550, 0x8590, 0x85B0, 0x85D0, 0x8610, 0x85E0, + 0x85F0, 0x8610, 0x8630, 0x8650, 0x86A0, 0x86C0, 0x86E0, 0x86E0, 0x86C0, 0x86C0, 0x86B0, 0x86A0, 0x8690, 0x8670, 0x8660, 0x8640, + 0x8640, 0x8630, 0x8620, 0x8630, 0x8640, 0x8650, 0x8660, 0x8670, 0x86A0, 0x8700, 0x87B0, 0x88C0, 0x8AB0, 0x8DE0, 0x9200, 0x9730, + 0x9D00, 0xA2F0, 0xA940, 0xB040, 0xB7C0, 0xBF30, 0xC6F0, 0xD150, 0xD930, 0xE140, 0xE880, 0xEF50, 0xF680, 0xFD80, 0x0550, 0x0DD0, + 0x1600, 0x1F00, 0x28F0, 0x3280, 0x3BC0, 0x4520, 0x4EF0, 0x57F0, 0x6060, 0x6840, 0x6F40, 0x7520, 0x7970, 0x7CB0, 0x7E70, 0x7EE0, + 0x7F00, 0x7ED0, 0x7D90, 0x7A20, 0x74D0, 0x6E70, 0x6720, 0x5E40, 0x5430, 0x48B0, 0x3CE0, 0x2FA0, 0x2210, 0x1440, 0x0760, 0xFBD0, + 0xF0D0, 0xE720, 0xDF80, 0xD8F0, 0xD3B0, 0xCF60, 0xCC40, 0xCA70, 0xC960, 0xC910, 0xC910, 0xC9B0, 0xCAC0, 0xCB70, 0xCBD0, 0xCC50, + 0xCBE0, 0xCAD0, 0xCA30, 0xC8B0, 0xC820, 0xC780, 0xC7B0, 0xC810, 0xC7B0, 0xC7B0, 0xC6E0, 0xC600, 0xC580, 0xC4B0, 0xC420, 0xC2C0, + 0xC120, 0xBE90, 0xBC20, 0xBA20, 0xB8D0, 0xB830, 0xB6C0, 0xB530, 0xB310, 0xB090, 0xADE0, 0xAB70, 0xA930, 0xA740, 0xA5A0, 0xA470, + 0xA2E0, 0xA190, 0xA0E0, 0xA0C0, 0xA030, 0x9F50, 0x9E20, 0x9DA0, 0x9D10, 0x9C00, 0x9AF0, 0x98C0, 0x95F0, 0x9360, 0x90A0, 0x8E90, + 0x8D10, 0x8BB0, 0x8AF0, 0x8AD0, 0x8AB0, 0x8A70, 0x8AE0, 0x8BC0, 0x8E60, 0x9320, 0x9A90, 0xA440, 0xAE60, 0xB940, 0xC560, 0xD130, + 0xDC70, 0xE730, 0xF150, 0xFAB0, 0x0340, 0x0AC0, 0x1130, 0x18C0, 0x1FF0, 0x2770, 0x2E00, 0x3340, 0x35B0, 0x3300, 0x29C0, 0x1A80, + 0x0530, 0xEF70, 0xDB20, 0xCB20, 0xBF60, 0xB730, 0xB1C0, 0xAD00, 0xA810, 0xA180, 0x9AE0, 0x93D0, 0x8DD0, 0x89C0, 0x8760, 0x8610, + 0x8580, 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, + 0x8450, 0x8470, 0x8470, 0x8470, 0x8490, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, + 0x84C0, 0x84F0, 0x8570, 0x8920, 0x9F80, 0xB7A0, 0xD0A0, 0xE550, 0xF730, 0x0670, 0x1340, 0x1E90, 0x2860, 0x2FC0, 0x35F0, 0x3930, + 0x3900, 0x3590, 0x3010, 0x29B0, 0x2220, 0x19D0, 0x11C0, 0x08A0, 0x0040, 0xF7C0, 0xEE70, 0xCB00, 0xBE20, 0xAFA0, 0x9EE0, 0x8E30, + 0x8630, 0x84F0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8480, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8430, 0x8420, 0x8420, 0x8430, 0x8420, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8490, + 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8510, 0x8540, 0x85B0, 0x8690, 0x8860, 0x8C40, 0x9260, 0x99A0, 0xA000, + 0xA650, 0xABD0, 0xB020, 0xB400, 0xB710, 0xBAA0, 0xBDC0, 0xC070, 0xC430, 0xC770, 0xC8F0, 0xCA00, 0xC940, 0xC860, 0xC600, 0xC3B0, + 0xC0C0, 0xBE50, 0xBCC0, 0xBB90, 0xB9D0, 0xB870, 0xB770, 0xB6B0, 0xB5C0, 0xB650, 0xB7E0, 0xBB70, 0xBFA0, 0xC4A0, 0xC9E0, 0xCF00, + 0xD400, 0xDA20, 0xE0B0, 0xE770, 0xEEF0, 0xF690, 0xFE90, 0x0570, 0x0BF0, 0x1320, 0x18D0, 0x2000, 0x26C0, 0x2D20, 0x3350, 0x39E0, + 0x4010, 0x45B0, 0x4B70, 0x5160, 0x55C0, 0x5B10, 0x5FD0, 0x6460, 0x6950, 0x6D00, 0x7080, 0x73A0, 0x75D0, 0x7830, 0x79B0, 0x7B20, + 0x7BD0, 0x7C60, 0x7D40, 0x7D90, 0x7DF0, 0x7DC0, 0x7DC0, 0x7D90, 0x7D90, 0x7D40, 0x7C90, 0x7BB0, 0x7AB0, 0x78E0, 0x7650, 0x7310, + 0x6EE0, 0x56F0, 0x4F30, 0x4870, 0x4180, 0x3AB0, 0x3430, 0x2E60, 0x29A0, 0x25C0, 0x2290, 0x1FD0, 0x1CC0, 0x1AE0, 0x19C0, 0x1930, + 0x1AA0, 0x1C40, 0x1F50, 0x2230, 0x2570, 0x2960, 0x2D10, 0x3120, 0x3560, 0x39F0, 0x4100, 0x46A0, 0x4CC0, 0x52D0, 0x58B0, 0x5F20, + 0x6540, 0x6A90, 0x6FF0, 0x7490, 0x78F0, 0x7BC0, 0x7DC0, 0x7EC0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7E70, 0x7E20, 0x7E40, 0x7EB0, + 0x7F30, 0x7F00, 0x7F00, 0x7F10, 0x7EF0, 0x7DB0, 0x79A0, 0x7400, 0x6D90, 0x6750, 0x6260, 0x5EA0, 0x5D80, 0x5E80, 0x6120, 0x64C0, + 0x69C0, 0x6F10, 0x7570, 0x7BE0, 0x7EF0, 0x7F00, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, + 0x7EA0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F50, 0x7F10, 0x7F10, 0x7F40, 0x7F10, 0x7F60, 0x7EE0, 0x7F10, 0x7F10, 0x7F10, + 0x7F60, 0x7F10, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, + 0x7F10, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F30, 0x7EF0, 0x7E90, 0x7ED0, 0x7F00, 0x7F10, 0x7F10, 0x7E90, 0x7F00, 0x6050, 0x4390, 0x3110, + 0x2800, 0x27C0, 0x2E40, 0x39A0, 0x4900, 0x59D0, 0x6BD0, 0x79E0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, + 0x7F50, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7D20, 0x6360, 0x3EB0, 0x14E0, 0xE7D0, 0xBAD0, 0x9200, 0x8570, 0x84E0, 0x84C0, + 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8520, 0x8540, 0x8560, 0x8570, 0x8550, 0x8530, 0x8520, + 0x8510, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x8500, 0x8520, 0x8560, 0x85E0, 0x8740, 0x8B20, 0x9540, 0x9F20, 0xA860, 0xAFC0, + 0xB4F0, 0xB8E0, 0xBA80, 0xBB50, 0xBA60, 0xB830, 0xB450, 0xAEF0, 0xA7D0, 0x9F40, 0x95F0, 0x8DD0, 0x88A0, 0x8670, 0x8590, 0x8540, + 0x8520, 0x8500, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x84F0, 0x8500, + 0x8510, 0x8520, 0x8550, 0x8580, 0x85E0, 0x8670, 0x8770, 0x8930, 0x8C40, 0x9130, 0x9580, 0x9A80, 0x9F60, 0xA3C0, 0xA8A0, 0xAD80, + 0xB240, 0xB710, 0xBB20, 0xBF10, 0xC200, 0xC510, 0xC820, 0xCAC0, 0xCD40, 0xCF80, 0xD160, 0xD380, 0xD520, 0xD7E0, 0xDA40, 0xDC50, + 0xE000, 0xE3F0, 0xE860, 0xECC0, 0xF230, 0xF780, 0xFC60, 0x0200, 0x07E0, 0x0DC0, 0x1480, 0x1A50, 0x20E0, 0x27F0, 0x2E90, 0x35F0, + 0x3CE0, 0x4450, 0x4BF0, 0x5300, 0x5A40, 0x6040, 0x6760, 0x6DF0, 0x7490, 0x7C00, 0x7ED0, 0x7F10, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F40, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x78A0, 0x6A30, 0x5AF0, 0x4C30, 0x3E40, 0x3090, 0x2380, 0x16B0, 0x0B20, 0x00E0, 0xF850, + 0xF230, 0xED70, 0xE8F0, 0xE450, 0xDE30, 0xD810, 0xD280, 0xCD40, 0xCA00, 0xC960, 0xCB50, 0xCFF0, 0xD580, 0xDC30, 0xE330, 0xE9E0, + 0xF000, 0xF410, 0xF620, 0xF510, 0xF230, 0xEC30, 0xE440, 0xDB30, 0xD080, 0xC4A0, 0xB880, 0xAAB0, 0x9D70, 0x90A0, 0x88E0, 0x8630, + 0x8560, 0x8520, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, + 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, 0x84C0, + 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x84D0, 0x8500, 0x84F0, 0x84F0, 0x84B0, 0x8520, 0x8540, 0x8580, 0x85E0, 0x86A0, 0x8800, 0x8AE0, + 0x8FD0, 0x96E0, 0x9D50, 0xA350, 0xA9F0, 0xB080, 0xB640, 0xBBF0, 0xC1D0, 0xC710, 0xCCB0, 0xD310, 0xD870, 0xDD90, 0xE2C0, 0xE740, + 0xEAF0, 0xED80, 0xEFE0, 0xF260, 0xF420, 0xF600, 0xF790, 0xF810, 0xF910, 0xF920, 0xF900, 0xF950, 0xF910, 0xF940, 0xFA40, 0xFB40, + 0xFC20, 0xFD20, 0xFD60, 0xFE10, 0xFF30, 0x0000, 0x00D0, 0x0190, 0x0360, 0x04E0, 0x0640, 0x07F0, 0x08B0, 0x0960, 0x0A00, 0x0A30, + 0x0B60, 0x0C50, 0x0D30, 0x0ED0, 0x1050, 0x12A0, 0x1440, 0x15F0, 0x1810, 0x1A70, 0x1CA0, 0x1F20, 0x22E0, 0x2710, 0x2BB0, 0x31B0, + 0x3760, 0x3D20, 0x4280, 0x4780, 0x4BF0, 0x4FF0, 0x5360, 0x5590, 0x5780, 0x5970, 0x5B70, 0x5DC0, 0x6010, 0x6280, 0x64A0, 0x65A0, + 0x6690, 0x6730, 0x66C0, 0x66D0, 0x6730, 0x6810, 0x68E0, 0x68B0, 0x68B0, 0x6740, 0x6660, 0x6480, 0x62C0, 0x6080, 0x5D10, 0x5A90, + 0x5730, 0x5360, 0x5010, 0x4C10, 0x4780, 0x4280, 0x3C60, 0x36C0, 0x3000, 0x2A50, 0x2420, 0x1D40, 0x1650, 0x0E10, 0x0600, 0xFE40, + 0xF680, 0xF000, 0xE940, 0xE300, 0xDDB0, 0xD790, 0xD1A0, 0xCC50, 0xC730, 0xC2E0, 0xBE60, 0xB9C0, 0xB540, 0xB100, 0xADA0, 0xAA70, + 0xA810, 0xA640, 0xA410, 0xA2D0, 0xA170, 0xA0A0, 0x9F40, 0x9D80, 0x9BA0, 0x9A00, 0x9890, 0x97B0, 0x9700, 0x9760, 0x9720, 0x96E0, + 0x96B0, 0x9570, 0x94B0, 0x9460, 0x94B0, 0x94A0, 0x9440, 0x93E0, 0x9350, 0x92B0, 0x9130, 0x9040, 0x8F00, 0x8DC0, 0x8CA0, 0x8C00, + 0x8B10, 0x8A70, 0x89C0, 0x8940, 0x88E0, 0x8840, 0x87F0, 0x8770, 0x8730, 0x86E0, 0x8660, 0x8640, 0x8620, 0x8600, 0x85E0, 0x85C0, + 0x85A0, 0x8590, 0x8570, 0x8560, 0x8540, 0x8530, 0x8530, 0x8520, 0x8520, 0x8560, 0x8520, 0x8510, 0x8510, 0x8510, 0x8500, 0x8500, + 0x8510, 0x8500, 0x8510, 0x8510, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8530, 0x8530, 0x8540, 0x8550, 0x8560, 0x8580, 0x85A0, + 0x85B0, 0x85D0, 0x85D0, 0x85E0, 0x8600, 0x85D0, 0x85E0, 0x85E0, 0x85F0, 0x8610, 0x8630, 0x8660, 0x8680, 0x8680, 0x8690, 0x86B0, + 0x86E0, 0x8710, 0x8760, 0x87D0, 0x8840, 0x88E0, 0x89A0, 0x8A40, 0x8A90, 0x8AB0, 0x8B10, 0x8B60, 0x8C30, 0x8D40, 0x8DB0, 0x8EF0, + 0x8FB0, 0x9010, 0x9090, 0x9120, 0x9230, 0x9350, 0x9410, 0x9560, 0x9680, 0x97A0, 0x9890, 0x9990, 0x9AF0, 0x9B90, 0x9C70, 0x9CD0, + 0x9D10, 0x9D30, 0x9E00, 0x9E40, 0x9D40, 0x9C90, 0x9CD0, 0x9CB0, 0x9C60, 0x9C20, 0x9C10, 0x9BC0, 0x9B70, 0x9B60, 0x9B50, 0x9B60, + 0x9B40, 0x9AD0, 0x9A30, 0x9A20, 0x99B0, 0x99E0, 0x99A0, 0x9930, 0x9810, 0x9720, 0x96C0, 0x9680, 0x96A0, 0x9700, 0x9690, 0x9630, + 0x95C0, 0x94F0, 0x94A0, 0x93A0, 0x9350, 0x9290, 0x91A0, 0x9090, 0x8F50, 0x8E40, 0x8D40, 0x8C90, 0x8C30, 0x8B90, 0x8B40, 0x8AA0, + 0x8A30, 0x89F0, 0x89B0, 0x8970, 0x8940, 0x8930, 0x8980, 0x89D0, 0x8AD0, 0x8BD0, 0x8CC0, 0x8DF0, 0x8EE0, 0x9010, 0x9140, 0x92C0, + 0x9530, 0x9720, 0x9970, 0x9B10, 0x9D20, 0x9F70, 0xA160, 0xA380, 0xA580, 0xA770, 0xA960, 0xAB60, 0xADC0, 0xAF70, 0xB190, 0xB3D0, + 0xB5F0, 0xB840, 0xBA60, 0xBCC0, 0xBF90, 0xC240, 0xC510, 0xC7A0, 0xC910, 0xCBA0, 0xCD70, 0xD060, 0xD2C0, 0xD4F0, 0xD750, 0xDA40, + 0xDCA0, 0xDF30, 0xE1B0, 0xE570, 0xE830, 0xEB90, 0xEF40, 0xF240, 0xF560, 0xF840, 0xFC40, 0xFF50, 0x0390, 0x0870, 0x0CE0, 0x1180, + 0x1630, 0x1A60, 0x1F60, 0x2340, 0x2700, 0x2B40, 0x2FC0, 0x34D0, 0x3960, 0x3D90, 0x41B0, 0x4470, 0x4840, 0x4AF0, 0x4DF0, 0x50E0, + 0x5320, 0x55B0, 0x57B0, 0x59B0, 0x5BC0, 0x5D50, 0x5F30, 0x60E0, 0x61F0, 0x6310, 0x6370, 0x6440, 0x6450, 0x63B0, 0x63C0, 0x6310, + 0x6390, 0x63B0, 0x63A0, 0x63F0, 0x62B0, 0x6220, 0x6140, 0x5FF0, 0x6000, 0x5F20, 0x5E80, 0x5DD0, 0x5C40, 0x5BC0, 0x5A10, 0x5930, + 0x5860, 0x5770, 0x57D0, 0x57A0, 0x5770, 0x5780, 0x56A0, 0x5690, 0x5690, 0x56B0, 0x5760, 0x57C0, 0x5880, 0x58E0, 0x5920, 0x58F0, + 0x57F0, 0x57A0, 0x56A0, 0x55D0, 0x5490, 0x5370, 0x5220, 0x5010, 0x4E70, 0x4D20, 0x4AD0, 0x4980, 0x4780, 0x4540, 0x43D0, 0x4200, + 0x4120, 0x3F10, 0x3D90, 0x3CB0, 0x3BC0, 0x3B40, 0x3A90, 0x3A10, 0x3A40, 0x3A10, 0x3A60, 0x3B20, 0x3B50, 0x3C90, 0x3DA0, 0x3FA0, + 0x40F0, 0x4250, 0x44F0, 0x4700, 0x49A0, 0x4C60, 0x4E10, 0x5170, 0x5460, 0x5860, 0x5C10, 0x5FB0, 0x63B0, 0x6720, 0x6A10, 0x6E30, + 0x71E0, 0x7560, 0x7890, 0x7B70, 0x7DC0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F20, 0x7EA0, + 0x7ED0, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7EC0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, + 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F50, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F00, + 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, 0x7EE0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7970, 0x6FC0, 0x6510, + 0x5AB0, 0x4F70, 0x43C0, 0x3850, 0x2BA0, 0x20D0, 0x1780, 0x0E90, 0x07E0, 0x0200, 0xFDD0, 0xFAF0, 0xF900, 0xF7D0, 0xF790, 0xF7E0, + 0xF7A0, 0xF680, 0xF450, 0xEFB0, 0xE9E0, 0xE250, 0xD820, 0xCE00, 0xC390, 0xB870, 0xAD60, 0xA230, 0x9690, 0x8D20, 0x87F0, 0x8620, + 0x8550, 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84B0, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, + 0x84F0, 0x8500, 0x8530, 0x8510, 0x8520, 0x8530, 0x8530, 0x8530, 0x8530, 0x8520, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x8500, + 0x8520, 0x8530, 0x8550, 0x8570, 0x8590, 0x85C0, 0x85E0, 0x8600, 0x8620, 0x8680, 0x8670, 0x8670, 0x8670, 0x8650, 0x8630, 0x8610, + 0x85F0, 0x85E0, 0x85C0, 0x85B0, 0x8590, 0x8580, 0x8570, 0x8560, 0x8560, 0x8560, 0x8560, 0x8570, 0x85C0, 0x85A0, 0x85C0, 0x8600, + 0x8640, 0x86D0, 0x87A0, 0x8920, 0x8B80, 0x8F30, 0x93D0, 0x98D0, 0x9D80, 0xA340, 0xA840, 0xAE00, 0xB330, 0xB820, 0xBCC0, 0xC140, + 0xC4D0, 0xC980, 0xCDD0, 0xD230, 0xD5B0, 0xD900, 0xDBC0, 0xDD40, 0xDED0, 0xE060, 0xE220, 0xE370, 0xE4E0, 0xE6C0, 0xE840, 0xE8E0, + 0xE9A0, 0xEAC0, 0xEAE0, 0xEB40, 0xEAD0, 0xEA30, 0xE9D0, 0xE920, 0xE9D0, 0xEA50, 0xEA20, 0xEA80, 0xEAC0, 0xEB10, 0xEB00, 0xE9F0, + 0xE9C0, 0xE930, 0xE980, 0xE9A0, 0xE9E0, 0xEB10, 0xEC20, 0xEC70, 0xEC50, 0xEC10, 0xEBA0, 0xEB10, 0xEB10, 0xEB50, 0xEBF0, 0xECB0, + 0xEE30, 0xEFF0, 0xF1A0, 0xF250, 0xF3B0, 0xF4D0, 0xF5C0, 0xF710, 0xF800, 0xFA40, 0xFBD0, 0xFD50, 0xFF70, 0x0160, 0x03D0, 0x0650, + 0x08C0, 0x0C00, 0x0DF0, 0x10D0, 0x1310, 0x1570, 0x1840, 0x1A90, 0x1E20, 0x2110, 0x24A0, 0x2890, 0x2C80, 0x3120, 0x3620, 0x3950, + 0x3D50, 0x40B0, 0x4420, 0x4690, 0x4860, 0x4B00, 0x4D80, 0x4F50, 0x5130, 0x5280, 0x5410, 0x54D0, 0x5560, 0x5540, 0x54D0, 0x5510, + 0x5570, 0x5540, 0x5590, 0x5530, 0x5600, 0x56D0, 0x57B0, 0x58E0, 0x5A30, 0x5B30, 0x5C60, 0x5D20, 0x5DD0, 0x5E80, 0x6040, 0x6240, + 0x63F0, 0x6630, 0x6760, 0x68C0, 0x6A00, 0x6AF0, 0x6C70, 0x6D10, 0x6E70, 0x6E70, 0x6F00, 0x6F90, 0x6F30, 0x7000, 0x6FE0, 0x6F80, + 0x6F20, 0x6E80, 0x6D90, 0x6CB0, 0x6C20, 0x6BC0, 0x6A20, 0x68D0, 0x6700, 0x64C0, 0x63B0, 0x6220, 0x6060, 0x5E10, 0x5B90, 0x58E0, + 0x5640, 0x5390, 0x5140, 0x4E90, 0x4CB0, 0x4A70, 0x48F0, 0x4750, 0x4630, 0x46C0, 0x4720, 0x47D0, 0x48B0, 0x48C0, 0x49A0, 0x49D0, + 0x4A70, 0x4B60, 0x4C90, 0x4F10, 0x5240, 0x55C0, 0x5A00, 0x5D70, 0x61E0, 0x6560, 0x6810, 0x6AB0, 0x6C00, 0x6B50, 0x68E0, 0x6340, + 0x5C40, 0x5290, 0x4880, 0x3E00, 0x3320, 0x29D0, 0x2020, 0x1880, 0x1140, 0x0AB0, 0x04E0, 0xFFC0, 0xFB50, 0xF730, 0xF2B0, 0xED00, + 0xE790, 0xE0E0, 0xDA30, 0xD240, 0xCA30, 0xC1C0, 0xB900, 0xB050, 0xA670, 0x89E0, 0x8700, 0x85C0, 0x8540, 0x84F0, 0x84F0, 0x84D0, + 0x84C0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x84C0, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8480, 0x8460, 0x8480, 0x8460, 0x8460, 0x8470, 0x8480, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, + 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8530, 0x8590, 0x8670, 0x88C0, 0x8EA0, 0x9800, 0xA180, 0xAB90, 0xB460, 0xBC90, 0xC3F0, + 0xCB70, 0xD220, 0xD870, 0xDED0, 0xE4B0, 0xEAB0, 0xEFB0, 0xF4E0, 0xF8E0, 0xFD10, 0x0040, 0x0270, 0x0540, 0x0690, 0x0860, 0x0A70, + 0x0C50, 0x0F30, 0x11B0, 0x1500, 0x1800, 0x1B10, 0x1F60, 0x2440, 0x2B60, 0x32A0, 0x3AA0, 0x4490, 0x4F30, 0x5AB0, 0x6640, 0x7140, + 0x7C00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x5BE0, + 0x2FC0, 0xFF50, 0xC750, 0x93A0, 0x84F0, 0x84A0, 0x8480, 0x8470, 0x8480, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8480, + 0x8480, 0x8490, 0x84B0, 0x84D0, 0x85A0, 0x9570, 0xBDD0, 0xE830, 0x12B0, 0x37C0, 0x5190, 0x5E30, 0x5D00, 0x4F90, 0x3BD0, 0x2670, + 0x1600, 0x08C0, 0x01D0, 0xFE90, 0xFD00, 0xFA90, 0xF400, 0xE960, 0xD910, 0xC430, 0xAA30, 0x8DC0, 0x8520, 0x84C0, 0x8490, 0x8480, + 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x84E0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, + 0x8470, 0x8410, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84F0, 0x84D0, 0x84D0, 0x84E0, 0x8500, 0x8510, 0x8530, 0x8590, + 0x8590, 0x85C0, 0x85F0, 0x8610, 0x8640, 0x8680, 0x86A0, 0x8700, 0x8780, 0x8870, 0x8AE0, 0x90A0, 0x9B30, 0xA890, 0xB860, 0xC950, + 0xDE10, 0xF080, 0x0260, 0x1240, 0x1F90, 0x2A90, 0x30B0, 0x31E0, 0x2C80, 0x1ED0, 0x0B70, 0xF220, 0xD580, 0xB9B0, 0xA110, 0x8F30, + 0x8810, 0x8610, 0x8580, 0x8540, 0x8510, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, + 0x84F0, 0x8520, 0x8550, 0x85B0, 0x8630, 0x86F0, 0x8840, 0x8A30, 0x8D20, 0x9080, 0x9380, 0x9690, 0x9960, 0x9CA0, 0x9FD0, 0xA3C0, + 0xA960, 0xB0D0, 0xBA10, 0xC520, 0xD140, 0xDD90, 0xEA90, 0xF760, 0x0420, 0x0F90, 0x1910, 0x2120, 0x29A0, 0x3110, 0x3990, 0x4330, + 0x4E60, 0x5A50, 0x66B0, 0x7200, 0x7AA0, 0x7ED0, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x79E0, 0x6D40, + 0x5870, 0x3B10, 0x1860, 0xF340, 0xCF80, 0xB010, 0x95F0, 0x8810, 0x8580, 0x8510, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, + 0x84A0, 0x84B0, 0x84B0, 0x84D0, 0x84F0, 0x8550, 0x8650, 0x8970, 0x9110, 0x9A50, 0xA030, 0xA380, 0xA390, 0xA100, 0x9B80, 0x9470, + 0x8D10, 0x8850, 0x8650, 0x8590, 0x8540, 0x8530, 0x8530, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8520, 0x8540, 0x8580, + 0x8600, 0x86E0, 0x88D0, 0x8CD0, 0x9340, 0x99C0, 0xA000, 0xA570, 0xAA50, 0xAF30, 0xB4D0, 0xBAF0, 0xC0E0, 0xC740, 0xCD60, 0xD350, + 0xD930, 0xDEB0, 0xE520, 0xEC20, 0xF3B0, 0xFBE0, 0x0430, 0x0B90, 0x11F0, 0x1800, 0x1D00, 0x2170, 0x2590, 0x2940, 0x2D50, 0x32C0, + 0x3860, 0x3DB0, 0x41E0, 0x4600, 0x49D0, 0x4C70, 0x4F60, 0x5180, 0x5480, 0x5710, 0x59B0, 0x5BD0, 0x5D40, 0x5D40, 0x5C10, 0x5A60, + 0x5760, 0x5360, 0x4E20, 0x4760, 0x4050, 0x3850, 0x2FB0, 0x2590, 0x1A70, 0x0E90, 0x01C0, 0xF610, 0xEB30, 0xE150, 0xD830, 0xD140, + 0xCB70, 0xC730, 0xC430, 0xC280, 0xC1E0, 0xC1C0, 0xC210, 0xC2F0, 0xC4F0, 0xC7D0, 0xCB20, 0xCF30, 0xD3E0, 0xD8A0, 0xDD50, 0xE1F0, + 0xE750, 0xECC0, 0xF270, 0xF8F0, 0xFF50, 0x0620, 0x0CC0, 0x1270, 0x1880, 0x1E40, 0x23C0, 0x28B0, 0x2DA0, 0x31F0, 0x3690, 0x3AE0, + 0x3DF0, 0x41F0, 0x4480, 0x47C0, 0x4A00, 0x4BF0, 0x4D90, 0x4E20, 0x4E10, 0x4E40, 0x4D30, 0x4CE0, 0x4B40, 0x4A10, 0x48A0, 0x4700, + 0x4480, 0x4210, 0x40A0, 0x3E80, 0x3C80, 0x3AF0, 0x3820, 0x35C0, 0x3340, 0x3070, 0x2F20, 0x2D50, 0x2BF0, 0x2AC0, 0x28E0, 0x26D0, + 0x2490, 0x2300, 0x2130, 0x1FB0, 0x1E70, 0x1D60, 0x1CF0, 0x1C20, 0x1B20, 0x1A80, 0x1830, 0x16E0, 0x1500, 0x1310, 0x11D0, 0x1070, + 0x0FA0, 0x0F10, 0x0D90, 0x0D10, 0x0C40, 0x0B90, 0x0AD0, 0x0A20, 0x0A00, 0x09D0, 0x0A20, 0x0BA0, 0x0BD0, 0x0CE0, 0x0DE0, 0x0F30, + 0x10D0, 0x1190, 0x13C0, 0x15F0, 0x1830, 0x1A90, 0x1CD0, 0x2050, 0x22B0, 0x2560, 0x2750, 0x28F0, 0x2BC0, 0x2DE0, 0x2FD0, 0x3220, + 0x33D0, 0x3670, 0x3870, 0x39F0, 0x3AF0, 0x3B10, 0x3C60, 0x3D40, 0x3DB0, 0x3F30, 0x4040, 0x4200, 0x4290, 0x4370, 0x4440, 0x4440, + 0x44F0, 0x45A0, 0x46C0, 0x4800, 0x4A00, 0x4BE0, 0x4E40, 0x4ED0, 0x50B0, 0x51B0, 0x52D0, 0x5430, 0x5520, 0x5700, 0x5890, 0x5A10, + 0x5B40, 0x5C40, 0x5E10, 0x5FA0, 0x6060, 0x6110, 0x6210, 0x62E0, 0x6340, 0x6390, 0x64B0, 0x65A0, 0x67B0, 0x68C0, 0x69D0, 0x6A30, + 0x6A30, 0x6A60, 0x6AF0, 0x6B30, 0x6CA0, 0x6D40, 0x6EC0, 0x7000, 0x70B0, 0x7240, 0x7290, 0x73F0, 0x7500, 0x75E0, 0x7750, 0x7800, + 0x7940, 0x7A40, 0x7AF0, 0x7C20, 0x7C80, 0x7D90, 0x7E50, 0x7EC0, 0x7F00, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, + 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, + 0x7EB0, 0x7EF0, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7EA0, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7EB0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, + 0x7EA0, 0x7F20, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7EE0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, + 0x7F90, 0x7F10, 0x7EE0, 0x7EE0, 0x7EE0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, 0x7E70, 0x7EF0, 0x7ED0, 0x7F30, + 0x7F00, 0x7E90, 0x7ED0, 0x7F00, 0x7F20, 0x7F10, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7F10, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, + 0x7EC0, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, + 0x7F80, 0x7F20, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F50, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F90, + 0x7F00, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F50, 0x7F10, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F30, 0x7EF0, + 0x7E90, 0x7ED0, 0x7EE0, 0x7F00, 0x7F10, 0x7EC0, 0x7EC0, 0x7EB0, 0x7F00, 0x7F00, 0x7E90, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, + 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F50, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F30, + 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, + 0x7EB0, 0x7DE0, 0x7360, 0x6840, 0x5C40, 0x4E10, 0x3F70, 0x2F20, 0x1F40, 0x10F0, 0x0310, 0xF700, 0xEC10, 0xE2B0, 0xDA80, 0xD240, + 0xCAD0, 0xC390, 0xBBD0, 0xB500, 0xAF30, 0xAC50, 0xAC00, 0xADB0, 0xB120, 0xB4B0, 0xB710, 0xB7E0, 0xB640, 0xB230, 0xAD70, 0xA8F0, + 0xA580, 0xA3E0, 0xA410, 0xA580, 0xA820, 0xA9D0, 0xAA10, 0xA890, 0xA4C0, 0x9EC0, 0x98C0, 0x9330, 0x8EA0, 0x8B20, 0x88E0, 0x8740, + 0x8660, 0x85C0, 0x8560, 0x8520, 0x8510, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x8520, 0x8540, 0x8580, 0x85D0, 0x8680, 0x8770, + 0x88E0, 0x8B60, 0x8EB0, 0x9310, 0x9810, 0x9DD0, 0xA3E0, 0xAA30, 0xB0B0, 0xB7C0, 0xBFB0, 0xC790, 0xCF20, 0xD740, 0xDEF0, 0xE650, + 0xEE00, 0xF500, 0xFC10, 0x0340, 0x0A10, 0x10D0, 0x16E0, 0x1D90, 0x2350, 0x2890, 0x2C70, 0x2FE0, 0x32B0, 0x33B0, 0x33A0, 0x32F0, + 0x30D0, 0x2E10, 0x2A40, 0x24F0, 0x1F10, 0x1740, 0x0F00, 0x0590, 0xFB70, 0xF170, 0xE6E0, 0xDCD0, 0xD2D0, 0xC960, 0xC080, 0xB980, + 0xB3C0, 0xAF00, 0xAAD0, 0xA7A0, 0xA470, 0xA230, 0xA110, 0xA090, 0xA130, 0xA200, 0xA3D0, 0xA5C0, 0xA840, 0xAAF0, 0xADB0, 0xB030, + 0xB330, 0xB5B0, 0xB870, 0xBB50, 0xBE50, 0xC0E0, 0xC3D0, 0xC6B0, 0xC9D0, 0xCC90, 0xCF50, 0xD230, 0xD4E0, 0xD7E0, 0xDA70, 0xDCE0, + 0xDF70, 0xE170, 0xE3E0, 0xE600, 0xE8A0, 0xEB30, 0xED90, 0xF080, 0xF330, 0xF630, 0xF8E0, 0xFB00, 0xFD10, 0xFE40, 0x0010, 0x0160, + 0x0320, 0x04B0, 0x0670, 0x07A0, 0x0910, 0x0A10, 0x0B10, 0x0C00, 0x0CF0, 0x0DA0, 0x0E10, 0x0ED0, 0x0F90, 0x1000, 0x1160, 0x1270, + 0x13B0, 0x14A0, 0x1560, 0x15F0, 0x16A0, 0x1750, 0x1790, 0x17B0, 0x17E0, 0x17F0, 0x1790, 0x1730, 0x1660, 0x1640, 0x1470, 0x12B0, + 0x1040, 0x0D60, 0x0A50, 0x0650, 0x0250, 0xFF10, 0xFB00, 0xF7A0, 0xF520, 0xF240, 0xEFB0, 0xED90, 0xEBA0, 0xEA20, 0xE8F0, 0xE780, + 0xE6F0, 0xE690, 0xE6B0, 0xE740, 0xE850, 0xE910, 0xE9B0, 0xEA80, 0xEB50, 0xEC00, 0xECB0, 0xED50, 0xEE70, 0xEF90, 0xF0D0, 0xF220, + 0xF440, 0xF5F0, 0xF750, 0xF9B0, 0xFB70, 0xFD60, 0xFF50, 0x0170, 0x0400, 0x06E0, 0x0960, 0x0BF0, 0x0EB0, 0x1140, 0x1390, 0x15B0, + 0x1750, 0x1940, 0x1B10, 0x1BB0, 0x1C40, 0x1C50, 0x1C80, 0x1C30, 0x1C60, 0x1C20, 0x1BB0, 0x1B70, 0x19E0, 0x18C0, 0x1730, 0x1630, + 0x1560, 0x1440, 0x1330, 0x1250, 0x11E0, 0x11B0, 0x1170, 0x10E0, 0x10B0, 0x10B0, 0x10D0, 0x11F0, 0x1310, 0x1490, 0x1720, 0x19C0, + 0x1C50, 0x1F70, 0x22B0, 0x2760, 0x2C50, 0x31B0, 0x3710, 0x3D40, 0x4280, 0x47B0, 0x4BA0, 0x4EC0, 0x5040, 0x4FB0, 0x4E60, 0x4C00, + 0x47D0, 0x4340, 0x3E60, 0x38F0, 0x3280, 0x2C40, 0x2560, 0x1E50, 0x16B0, 0x0DC0, 0x0540, 0xFC70, 0xF3C0, 0xEAC0, 0xE190, 0xD8D0, + 0xD130, 0xC960, 0xC1F0, 0xBCA0, 0xB7E0, 0xB4B0, 0xB2D0, 0xB1A0, 0xB200, 0xB2F0, 0xB520, 0xB890, 0xBBB0, 0xBF40, 0xC2A0, 0xC620, + 0xC9F0, 0xCDB0, 0xD1D0, 0xD520, 0xD8F0, 0xDCF0, 0xE030, 0xE3C0, 0xE680, 0xE950, 0xEB80, 0xEDE0, 0xF080, 0xF300, 0xF560, 0xF840, + 0xFA90, 0xFDE0, 0x0160, 0x0510, 0x09B0, 0x0DB0, 0x1290, 0x1680, 0x1AE0, 0x1F60, 0x2310, 0x2730, 0x2B40, 0x2F70, 0x32F0, 0x3640, + 0x3930, 0x3BD0, 0x3DC0, 0x4060, 0x4210, 0x4530, 0x4770, 0x4A70, 0x4DD0, 0x5030, 0x53A0, 0x5640, 0x58F0, 0x5C60, 0x5F20, 0x6340, + 0x6790, 0x6BE0, 0x7080, 0x7450, 0x7900, 0x7CE0, 0x7EE0, 0x7F10, 0x7EB0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7EE0, 0x7F10, 0x7F50, 0x7EF0, 0x7F20, + 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7ED0, 0x7F20, 0x7F00, 0x7F90, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7ED0, 0x7F10, + 0x7F20, 0x7F40, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F00, + 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7F00, 0x7F40, 0x7F40, 0x7F10, 0x7F70, 0x7EF0, 0x7EF0, + 0x7F10, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, + 0x7F00, 0x7F10, 0x7F10, 0x7E70, 0x7ED0, 0x7EB0, 0x7E30, 0x7D20, 0x7BC0, 0x7BD0, 0x7C40, 0x7CE0, 0x7E50, 0x7E80, 0x7ED0, 0x7F10, + 0x7F00, 0x7EF0, 0x7F00, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F40, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, + 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F60, 0x7F00, 0x7F70, 0x7EF0, + 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, 0x7F10, 0x7EE0, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7710, 0x5720, 0x3840, 0x1910, 0xFB70, 0xE0E0, 0xC9C0, 0xB780, + 0xA950, 0x9F70, 0x9920, 0x9560, 0x9300, 0x91F0, 0x9200, 0x92A0, 0x94E0, 0x9880, 0x9E90, 0xA540, 0xAD30, 0xB5C0, 0xBDB0, 0xC610, + 0xCEF0, 0xD820, 0xE0D0, 0xEB60, 0xF520, 0xFE90, 0x0890, 0x1180, 0x18F0, 0x1FF0, 0x2490, 0x28A0, 0x2B50, 0x2C30, 0x2C00, 0x2A60, + 0x2910, 0x26D0, 0x2300, 0x1F20, 0x1990, 0x12C0, 0x0B50, 0x03F0, 0xFCA0, 0xF450, 0xEC70, 0xE4A0, 0xDD00, 0xD5A0, 0xCDB0, 0xC5E0, + 0xBF10, 0xB7D0, 0xB0F0, 0xAA40, 0xA500, 0x9F90, 0x9A30, 0x9640, 0x92B0, 0x8FE0, 0x8D90, 0x8C00, 0x8B30, 0x8A80, 0x8A10, 0x8A60, + 0x8A90, 0x8B30, 0x8C00, 0x8D00, 0x8EB0, 0x9120, 0x9410, 0x9790, 0x9AF0, 0x9F90, 0xA3D0, 0xA930, 0xAE90, 0xB310, 0xB800, 0xBBB0, + 0xBFE0, 0xC3E0, 0xC740, 0xCBD0, 0xCF90, 0xD300, 0xD560, 0xD640, 0xD680, 0xD500, 0xD240, 0xCE70, 0xCA40, 0xC690, 0xC290, 0xBF30, + 0xBB40, 0xB750, 0xB2F0, 0xAE40, 0xA980, 0xA4D0, 0xA020, 0x91D0, 0x8FB0, 0x8E60, 0x8DB0, 0x8DD0, 0x8FB0, 0x92B0, 0x96F0, 0x9AF0, + 0x9ED0, 0xA2A0, 0xA560, 0xA710, 0xA7C0, 0xA7C0, 0xA7C0, 0xA830, 0xA910, 0xAA60, 0xABE0, 0xADA0, 0xAEC0, 0xAF60, 0xAFC0, 0xAF20, + 0xADC0, 0xAB00, 0xA840, 0xA410, 0x9F60, 0x99F0, 0x9390, 0x8D80, 0x88B0, 0x8650, 0x8560, 0x8510, 0x84E0, 0x84D0, 0x84C0, 0x84B0, + 0x84A0, 0x8490, 0x84C0, 0x8480, 0x8470, 0x8470, 0x8440, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x84A0, + 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8520, 0x8560, 0x85F0, 0x8710, 0x8990, 0x8ED0, 0x9510, 0x9B00, 0xA040, 0xA450, + 0xA820, 0xAB70, 0xAF30, 0xB2B0, 0xB5D0, 0xB8A0, 0xBB70, 0xBF10, 0xC200, 0xC4B0, 0xC890, 0xCC60, 0xD1A0, 0xD710, 0xDE00, 0xE530, + 0xED30, 0xF4E0, 0xFC50, 0x0350, 0x0A00, 0x0F60, 0x15D0, 0x1B50, 0x2080, 0x24A0, 0x27C0, 0x2AD0, 0x2C80, 0x2DF0, 0x2F70, 0x30B0, + 0x32B0, 0x33A0, 0x3430, 0x34B0, 0x3420, 0x3340, 0x3150, 0x2F30, 0x2D00, 0x2990, 0x2650, 0x2230, 0x1DF0, 0x19D0, 0x14D0, 0x10B0, + 0x0D70, 0x09F0, 0x07A0, 0x07C0, 0x0950, 0x0D10, 0x1250, 0x1960, 0x2310, 0x2F20, 0x3D40, 0x4E40, 0x5EF0, 0x6F20, 0x7C20, 0x7F20, + 0x7F40, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F50, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7E30, 0x77B0, 0x7570, 0x7780, 0x7D10, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F40, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x4170, 0xEA20, 0x8E40, 0x8490, 0x8460, 0x8440, + 0x8430, 0x8420, 0x8440, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, + 0x83F0, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x84A0, 0x8490, 0x8490, + 0x84C0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8530, 0x85F0, 0x87D0, 0x9130, 0x9F90, 0xAE10, 0xBCF0, 0xCAA0, 0xD7C0, 0xE3D0, + 0xEE30, 0xF750, 0xFED0, 0x0460, 0x0860, 0x0BB0, 0x0DD0, 0x0ED0, 0x0F20, 0x0E60, 0x0D30, 0x0C30, 0x0B30, 0x09F0, 0x0910, 0x0810, + 0x05A0, 0x0260, 0xFFE0, 0xFCF0, 0xF9B0, 0xF6F0, 0xF4A0, 0xF2A0, 0xF080, 0xEEB0, 0xEC90, 0xE9A0, 0xE620, 0xE180, 0xDC60, 0xD610, + 0xCE80, 0xC5B0, 0xBB10, 0xAEC0, 0xA020, 0x9180, 0x8760, 0x8530, 0x84D0, 0x84B0, 0x84A0, 0x84B0, 0x8480, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8490, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8460, 0x8440, 0x8440, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8490, 0x8470, 0x8480, 0x8480, 0x84C0, 0x8490, 0x84A0, 0x84B0, + 0x84D0, 0x8500, 0x8570, 0x8730, 0x9040, 0xA0D0, 0xB020, 0xBE70, 0xCC40, 0xD990, 0xE570, 0xF0B0, 0xFB60, 0x0530, 0x0F10, 0x18C0, + 0x2180, 0x2A50, 0x3320, 0x3A90, 0x4250, 0x4990, 0x5100, 0x5960, 0x6180, 0x6B10, 0x7400, 0x7CD0, 0x7F00, 0x7F20, 0x7F00, 0x7F10, + 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EB0, 0x7E70, 0x7EF0, 0x7EE0, 0x7EF0, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F10, + 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, + 0x7F60, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, 0x5160, 0x2380, 0xFD30, 0xDDA0, 0xCA30, 0xBD80, 0xB790, 0xB3E0, 0xB1E0, + 0xB190, 0xB190, 0xB300, 0xB5D0, 0xBA50, 0xBFA0, 0xC5A0, 0xCB00, 0xCF50, 0xD100, 0xD0A0, 0xCDA0, 0xC830, 0xC200, 0xBB90, 0xB060, + 0xB0E0, 0xB300, 0xB530, 0xBA10, 0xC090, 0xCA10, 0xD610, 0xE330, 0xF260, 0x0410, 0x1490, 0x24F0, 0x34C0, 0x4380, 0x5030, 0x5A60, + 0x62C0, 0x6850, 0x6C20, 0x6F00, 0x7050, 0x7200, 0x72B0, 0x72E0, 0x71F0, 0x7000, 0x6D20, 0x6950, 0x6560, 0x6170, 0x5DC0, 0x5A90, + 0x57B0, 0x55B0, 0x5370, 0x5110, 0x4F70, 0x4DD0, 0x4D00, 0x4CC0, 0x4CD0, 0x4D10, 0x4CB0, 0x4BE0, 0x4B10, 0x4990, 0x48D0, 0x46E0, + 0x4460, 0x42C0, 0x4050, 0x3E70, 0x3C60, 0x3A50, 0x3950, 0x3800, 0x36E0, 0x3650, 0x3530, 0x35A0, 0x35C0, 0x3600, 0x3780, 0x3860, + 0x3A50, 0x3B80, 0x3D20, 0x3E80, 0x3FD0, 0x4290, 0x4520, 0x48A0, 0x4CA0, 0x5060, 0x5510, 0x5950, 0x5E20, 0x6260, 0x6650, 0x6A30, + 0x6D60, 0x6F80, 0x7190, 0x7290, 0x73A0, 0x73A0, 0x72F0, 0x7230, 0x6FE0, 0x6DC0, 0x6A10, 0x6660, 0x61D0, 0x5BD0, 0x5670, 0x5040, + 0x4A10, 0x4490, 0x3EE0, 0x39C0, 0x33F0, 0x2E30, 0x2940, 0x2400, 0x2010, 0x1BB0, 0x17E0, 0x1540, 0x1290, 0x10B0, 0x0EF0, 0x0D90, + 0x0CB0, 0x0BC0, 0x0B80, 0x0B90, 0x0B60, 0x0B80, 0x0B20, 0x0B40, 0x0A50, 0x0A10, 0x0A80, 0x0A60, 0x0AF0, 0x0B10, 0x0B00, 0x0B20, + 0x0A70, 0x0A70, 0x0A50, 0x0A60, 0x0AE0, 0x0BD0, 0x0D50, 0x0ED0, 0x1110, 0x1380, 0x1600, 0x1890, 0x1B80, 0x1E00, 0x20E0, 0x23C0, + 0x2630, 0x29C0, 0x2C60, 0x3010, 0x3370, 0x35F0, 0x3940, 0x3B90, 0x3EB0, 0x40F0, 0x4350, 0x46F0, 0x49C0, 0x4D90, 0x51F0, 0x55A0, + 0x5A40, 0x5E40, 0x6260, 0x6610, 0x6910, 0x6D00, 0x6FC0, 0x72F0, 0x75B0, 0x77A0, 0x79A0, 0x7B40, 0x7CC0, 0x7D80, 0x7E20, 0x7EC0, + 0x7ED0, 0x7F30, 0x7EE0, 0x7EE0, 0x7EF0, 0x7EE0, 0x7F40, 0x7ED0, 0x7E50, 0x7DA0, 0x7CA0, 0x7AD0, 0x78D0, 0x75C0, 0x7310, 0x7030, + 0x6CF0, 0x69E0, 0x65C0, 0x6230, 0x5D80, 0x57C0, 0x5220, 0x4B40, 0x4610, 0x4090, 0x3AA0, 0x3540, 0x2E40, 0x2800, 0x2130, 0x19A0, + 0x13F0, 0x0E40, 0x09C0, 0x0620, 0x0210, 0xFF10, 0xF510, 0xF340, 0xF190, 0xF070, 0xEFC0, 0xEF00, 0xEE80, 0xEDA0, 0xEC70, 0xEB70, + 0xE9D0, 0xE8A0, 0xE760, 0xE5C0, 0xE4C0, 0xE3B0, 0xE2E0, 0xE240, 0xE130, 0xE060, 0xDEF0, 0xDD50, 0xDC80, 0xDBD0, 0xDB60, 0xDA80, + 0xD9F0, 0xD9E0, 0xD960, 0xD8E0, 0xD870, 0xD7F0, 0xD790, 0xD700, 0xD6D0, 0xD730, 0xD6A0, 0xD770, 0xD790, 0xD7E0, 0xD750, 0xD6D0, + 0xD6D0, 0xD6A0, 0xD6D0, 0xD6D0, 0xD670, 0xD700, 0xD730, 0xD780, 0xD800, 0xD770, 0xD7E0, 0xD800, 0xD820, 0xD8B0, 0xD8B0, 0xD960, + 0xD950, 0xD930, 0xD8F0, 0xD870, 0xD870, 0xD810, 0xD7B0, 0xD770, 0xD730, 0xD750, 0xD720, 0xD700, 0xD6B0, 0xD6B0, 0xD6D0, 0xD6C0, + 0xD6A0, 0xD5D0, 0xD550, 0xD560, 0xD560, 0xD630, 0xD730, 0xD6F0, 0xD790, 0xD720, 0xD740, 0xD770, 0xD7A0, 0xD810, 0xD8D0, 0xD990, + 0xDA30, 0xDB00, 0xDBB0, 0xDC20, 0xDCB0, 0xDD20, 0xDE40, 0xDE90, 0xDFB0, 0xE1E0, 0xE380, 0xE4D0, 0xE690, 0xE900, 0xEAE0, 0xED10, + 0xEF40, 0xF0E0, 0xF320, 0xF4F0, 0xF740, 0xF9A0, 0xFC90, 0xFF50, 0x0240, 0x0570, 0x0870, 0x0C60, 0x1020, 0x1390, 0x16E0, 0x1A30, + 0x1D80, 0x2040, 0x2330, 0x25C0, 0x28C0, 0x2B20, 0x2DC0, 0x3000, 0x3230, 0x3470, 0x3640, 0x3890, 0x39F0, 0x3C00, 0x3D60, 0x3EF0, + 0x40D0, 0x42B0, 0x4480, 0x4640, 0x4870, 0x4A70, 0x4CE0, 0x4F10, 0x5130, 0x5360, 0x55E0, 0x5850, 0x5A90, 0x5D00, 0x5FE0, 0x62F0, + 0x65B0, 0x68B0, 0x6BC0, 0x6E50, 0x70D0, 0x73A0, 0x76C0, 0x7A50, 0x7DC0, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F00, + 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F50, 0x7F20, 0x7F90, 0x7F30, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F30, + 0x7E70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F00, 0x7F00, 0x7F30, 0x7F00, 0x7E70, 0x7ED0, 0x7ED0, 0x7F10, 0x7F00, 0x7E90, + 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EA0, 0x7F20, 0x7F00, 0x7F10, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7EE0, 0x7EC0, 0x7F10, + 0x7F20, 0x70C0, 0x5B90, 0x4510, 0x30B0, 0x1DF0, 0x0B70, 0xFC20, 0xED20, 0xDDC0, 0xCCC0, 0xBAD0, 0xA840, 0x9690, 0x8A40, 0x8600, + 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8540, 0x8580, 0x85E0, + 0x86B0, 0x87C0, 0x8980, 0x8C00, 0x8ED0, 0x9260, 0x9540, 0x9800, 0x9A10, 0x9AF0, 0x9C30, 0x9D00, 0x9DD0, 0x9E40, 0x9E80, 0x9EF0, + 0x9EA0, 0x9EF0, 0x9E50, 0x9DC0, 0x9D50, 0x9C30, 0x9BB0, 0x9AE0, 0x9A10, 0x99E0, 0x9900, 0x98A0, 0x97E0, 0x9760, 0x96F0, 0x96A0, + 0x9650, 0x9630, 0x96C0, 0x9720, 0x9750, 0x97C0, 0x98E0, 0x9A40, 0x9B90, 0x9C90, 0x9DC0, 0x9EE0, 0x9FF0, 0xA1E0, 0xA3C0, 0xA650, + 0xA8C0, 0xAA70, 0xAC40, 0xAE40, 0xB050, 0xB2E0, 0xB560, 0xB890, 0xBAD0, 0xBD20, 0xC000, 0xC1E0, 0xC430, 0xC620, 0xC910, 0xCB00, + 0xCD10, 0xCF40, 0xD190, 0xD3F0, 0xD5A0, 0xD710, 0xD940, 0xDAE0, 0xDC70, 0xDF20, 0xE0B0, 0xE2D0, 0xE480, 0xE5F0, 0xE770, 0xE8A0, + 0xEA20, 0xEB40, 0xEC50, 0xEE20, 0xEED0, 0xF090, 0xF180, 0xF1E0, 0xF290, 0xF2B0, 0xF2F0, 0xF2E0, 0xF2C0, 0xF370, 0xF340, 0xF330, + 0xF350, 0xF2A0, 0xF280, 0xF2D0, 0xF250, 0xF290, 0xF2B0, 0xF390, 0xF420, 0xF480, 0xF5A0, 0xF650, 0xF870, 0xFA00, 0xFBD0, 0xFE70, + 0x00C0, 0x0E10, 0x1200, 0x16B0, 0x1AC0, 0x1F80, 0x2510, 0x2AF0, 0x3170, 0x3750, 0x3D50, 0x4300, 0x4840, 0x4DF0, 0x5340, 0x5820, + 0x5D40, 0x6130, 0x6670, 0x6AC0, 0x6E90, 0x7270, 0x74E0, 0x7780, 0x7980, 0x7AE0, 0x7BE0, 0x7BF0, 0x7C90, 0x7CE0, 0x7C90, 0x7C30, + 0x7AE0, 0x79E0, 0x77D0, 0x7530, 0x73B0, 0x7160, 0x6F90, 0x6E00, 0x6C90, 0x6BE0, 0x6A70, 0x6A10, 0x6910, 0x6860, 0x6870, 0x6900, + 0x6A50, 0x6C30, 0x6D20, 0x6EE0, 0x6F00, 0x7030, 0x7180, 0x7240, 0x7350, 0x7460, 0x7580, 0x76B0, 0x77B0, 0x7940, 0x7A50, 0x7B70, + 0x7C00, 0x7C60, 0x7C50, 0x7C10, 0x7AB0, 0x77C0, 0x7390, 0x6F00, 0x6900, 0x61E0, 0x5B10, 0x53E0, 0x4D60, 0x4690, 0x3FB0, 0x3820, + 0x2F40, 0x2690, 0x1D70, 0x1350, 0x09B0, 0x0050, 0xF800, 0xEF70, 0xE770, 0xE090, 0xD8E0, 0xD180, 0xC960, 0xC150, 0xBA60, 0xB350, + 0xACB0, 0xA630, 0xA080, 0x9AE0, 0x9610, 0x91B0, 0x8E00, 0x8B70, 0x8A00, 0x88F0, 0x8840, 0x87E0, 0x87A0, 0x8790, 0x8780, 0x87A0, + 0x87D0, 0x8820, 0x88D0, 0x89F0, 0x8BD0, 0x8ED0, 0x9250, 0x96D0, 0x9BA0, 0xA090, 0xA630, 0xAC50, 0xB3B0, 0xBA40, 0xC040, 0xC610, + 0xCBB0, 0xD1F0, 0xD640, 0xDB50, 0xE0B0, 0xE550, 0xEA40, 0xEE00, 0xF190, 0xF540, 0xF830, 0xFA70, 0xFBE0, 0xFCF0, 0xFE70, 0xFF60, + 0x0050, 0x0150, 0x01F0, 0x02C0, 0x03A0, 0x0510, 0x0680, 0x0740, 0x0910, 0x09F0, 0x0B90, 0x0C60, 0x0C90, 0x0D60, 0x0D80, 0x0CF0, + 0x0BD0, 0x0A50, 0x0870, 0x05E0, 0x0280, 0xFFC0, 0xFB90, 0xF770, 0xF2A0, 0xEDE0, 0xE900, 0xE410, 0xE030, 0xDC60, 0xD830, 0xD400, + 0xCFF0, 0xCCA0, 0xC8E0, 0xC610, 0xC410, 0xC270, 0xC0F0, 0xBF10, 0xBD10, 0xBB20, 0xB8E0, 0xB5F0, 0xB360, 0xB090, 0xADD0, 0xAA80, + 0xA6B0, 0xA2F0, 0x9EA0, 0x9AD0, 0x96F0, 0x9350, 0x8FF0, 0x8D30, 0x8AF0, 0x8940, 0x8840, 0x8780, 0x86E0, 0x86A0, 0x86A0, 0x8640, + 0x8630, 0x8600, 0x85F0, 0x85F0, 0x85E0, 0x85C0, 0x85D0, 0x85C0, 0x85C0, 0x85B0, 0x85D0, 0x85D0, 0x85F0, 0x85F0, 0x8600, 0x8630, + 0x8660, 0x8670, 0x86B0, 0x8700, 0x8770, 0x87E0, 0x8870, 0x8900, 0x89B0, 0x8AE0, 0x8C30, 0x8DC0, 0x8FD0, 0x91E0, 0x93D0, 0x9610, + 0x98C0, 0x9AB0, 0x9DA0, 0xA050, 0xA380, 0xA5C0, 0xA8E0, 0xAB10, 0xAD60, 0xAF50, 0xB100, 0xB300, 0xB4A0, 0xB680, 0xB7F0, 0xB9C0, + 0xBAD0, 0xBBF0, 0xBD80, 0xBE60, 0xBFD0, 0xC130, 0xC270, 0xC440, 0xC5C0, 0xC760, 0xC890, 0xC990, 0xCAB0, 0xCBE0, 0xCCD0, 0xCDD0, + 0xCED0, 0xD060, 0xD190, 0xD250, 0xD330, 0xD350, 0xD380, 0xD350, 0xD240, 0xD0F0, 0xCF70, 0xCE80, 0xCDD0, 0xCCF0, 0xCBD0, 0xCA90, + 0xC8F0, 0xC7A0, 0xC5C0, 0xC3F0, 0xC260, 0xBBE0, 0xBA30, 0xB7D0, 0xB5F0, 0xB400, 0xB180, 0xAF50, 0xAD20, 0xAB00, 0xA8E0, 0xA6D0, + 0xA520, 0xA340, 0xA140, 0x9FA0, 0x9E80, 0x9DE0, 0x9D20, 0x9BF0, 0x9B30, 0x9A50, 0x9A00, 0x99A0, 0x98F0, 0x9910, 0x9890, 0x98B0, + 0x9870, 0x9960, 0x99D0, 0x9A50, 0x9AE0, 0x9BA0, 0x9B60, 0x9C00, 0x9CB0, 0x9D70, 0x9D70, 0x9DB0, 0x9DE0, 0x9E40, 0x9E80, 0x9F70, + 0xA000, 0xA000, 0x9F80, 0x9F00, 0x9E50, 0x9DB0, 0x9D20, 0x9C60, 0x9CB0, 0x9CD0, 0x9D00, 0x9CC0, 0x9CF0, 0x9CE0, 0x9D10, 0x9C50, + 0x9BA0, 0x9B60, 0x9B60, 0x9BB0, 0x9BB0, 0x9BE0, 0x9C80, 0x9CA0, 0x9CE0, 0x9CD0, 0x9CD0, 0x9DB0, 0x9F00, 0xA0A0, 0xA300, 0xA570, + 0xA870, 0xAB40, 0xADF0, 0xB0D0, 0xB480, 0xB800, 0xBBF0, 0xBFF0, 0xC450, 0xC850, 0xCD10, 0xD1B0, 0xD5F0, 0xDA10, 0xDE90, 0xE340, + 0xE8B0, 0xEE10, 0xF390, 0xF8C0, 0xFE30, 0x02A0, 0x0700, 0x0B90, 0x0FD0, 0x1430, 0x1840, 0x1C70, 0x2070, 0x24D0, 0x2920, 0x2D80, + 0x31B0, 0x3550, 0x3940, 0x3CE0, 0x4050, 0x4350, 0x45F0, 0x4850, 0x4B30, 0x4DA0, 0x4FA0, 0x51D0, 0x5370, 0x5400, 0x53A0, 0x5230, + 0x50F0, 0x4FB0, 0x4E20, 0x4C10, 0x4A90, 0x4830, 0x4500, 0x41D0, 0x3DA0, 0x3970, 0x3540, 0x3130, 0x2D20, 0x28C0, 0x24C0, 0x2100, + 0x1D70, 0x19C0, 0x16A0, 0x13D0, 0x1100, 0x0E10, 0x0B60, 0x0910, 0x0780, 0x0570, 0x03D0, 0x0230, 0x0120, 0x0010, 0xFFD0, 0xFFF0, + 0x0020, 0x00C0, 0x00E0, 0x0170, 0x0140, 0x0190, 0x0230, 0x0370, 0x0500, 0x06D0, 0x0890, 0x09D0, 0x0B40, 0x0C90, 0x0DB0, 0x0F60, + 0x10C0, 0x1290, 0x1530, 0x1750, 0x18F0, 0x19A0, 0x1A80, 0x1A80, 0x1B10, 0x1B00, 0x1A60, 0x1B10, 0x1B10, 0x1AE0, 0x1A10, 0x1930, + 0x17E0, 0x1620, 0x1440, 0x1230, 0x0F90, 0x0D40, 0x0AA0, 0x0830, 0x0680, 0x0440, 0x0190, 0xFF00, 0xFC40, 0xFA20, 0xF7A0, 0xF590, + 0xF420, 0xF2F0, 0xF230, 0xF150, 0xF160, 0xF0F0, 0xF070, 0xF070, 0xF0F0, 0xF170, 0xF260, 0xF340, 0xF500, 0xF610, 0xF810, 0xF960, + 0xFA50, 0xFBA0, 0xFC10, 0xFCA0, 0xFCC0, 0xFC50, 0xFCF0, 0xFD20, 0xFE60, 0xFF50, 0x0100, 0x0220, 0x0290, 0x0350, 0x0370, 0x02C0, + 0x0360, 0x0350, 0x03F0, 0x0520, 0x0670, 0x0790, 0x0860, 0x0920, 0x09B0, 0x09A0, 0x0A60, 0x0AE0, 0x0B90, 0x0C70, 0x0D00, 0x0ED0, + 0x10B0, 0x12A0, 0x1420, 0x1560, 0x1730, 0x1930, 0x1C30, 0x1EB0, 0x2160, 0x2490, 0x2810, 0x2AB0, 0x2DA0, 0x2F60, 0x3200, 0x3320, + 0x34E0, 0x3640, 0x3770, 0x3A00, 0x3BE0, 0x3CF0, 0x3E70, 0x3F40, 0x4050, 0x40F0, 0x4110, 0x4200, 0x4110, 0x4150, 0x4100, 0x3FC0, + 0x3EF0, 0x3DA0, 0x3CA0, 0x3B50, 0x3A00, 0x3940, 0x3800, 0x3680, 0x35B0, 0x34B0, 0x3480, 0x33D0, 0x33A0, 0x33A0, 0x32C0, 0x31F0, + 0x3110, 0x2F40, 0x2E10, 0x2CA0, 0x2BD0, 0x2AF0, 0x29A0, 0x2770, 0x2390, 0x1F20, 0x1830, 0x0FE0, 0x0580, 0xFB50, 0xF180, 0xE880, + 0xE090, 0xD9D0, 0xD3A0, 0xCE60, 0xC8C0, 0xC270, 0xBC20, 0xB540, 0xAF00, 0xA870, 0xA290, 0x9D40, 0x9870, 0x9430, 0x9150, 0x8F80, + 0x8F00, 0x8E60, 0x8DC0, 0x8CE0, 0x8B20, 0x8970, 0x87A0, 0x8640, 0x8590, 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, + 0x84B0, 0x8450, 0x84B0, 0x84A0, 0x84A0, 0x84D0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, + 0x8510, 0x8530, 0x8570, 0x85F0, 0x8B00, 0x8BC0, 0x8B80, 0x8A60, 0x8930, 0x8830, 0x8790, 0x8720, 0x86E0, 0x86D0, 0x86C0, 0x86A0, + 0x86A0, 0x8680, 0x8690, 0x8680, 0x8690, 0x8690, 0x86A0, 0x86B0, 0x8700, 0x8720, 0x8700, 0x86C0, 0x8660, 0x85E0, 0x8560, 0x8510, + 0x84F0, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84C0, + 0x8500, 0x85C0, 0x8B80, 0xA2E0, 0xB7D0, 0xCC30, 0xDEF0, 0xEFA0, 0xFDD0, 0x0970, 0x1260, 0x1880, 0x1D50, 0x20A0, 0x2340, 0x2650, + 0x28B0, 0x2AB0, 0x2C40, 0x2C30, 0x2BF0, 0x28E0, 0x2490, 0x1FF0, 0x1960, 0x1300, 0x0B50, 0x0230, 0xF770, 0xE9C0, 0xD730, 0xC270, + 0xAAA0, 0x9290, 0x8690, 0x8500, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8450, 0x84D0, 0x8550, + 0x8900, 0x9280, 0x9360, 0x8D00, 0x8700, 0x8520, 0x8500, 0x84B0, 0x84A0, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8420, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8470, 0x8450, 0x8450, + 0x8400, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, + 0x8500, 0x8510, 0x8510, 0x8510, 0x8510, 0x8510, 0x8500, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8500, + 0x8500, 0x8510, 0x8520, 0x8530, 0x8550, 0x85B0, 0x8650, 0x87E0, 0x8BD0, 0x9350, 0x9C70, 0xA4F0, 0xADD0, 0xB6D0, 0xC030, 0xC890, + 0xD120, 0xD940, 0xE140, 0xE990, 0xF090, 0xF6B0, 0xFC80, 0x0180, 0x0590, 0x08B0, 0x09E0, 0x0B40, 0x0B50, 0x0AB0, 0x0A40, 0x0920, + 0x07F0, 0x06E0, 0x05A0, 0x04D0, 0x03B0, 0x0360, 0x0370, 0x03F0, 0x05B0, 0x0830, 0x0C80, 0x1170, 0x1880, 0x2210, 0x2D30, 0x3A40, + 0x4650, 0x50F0, 0x5A00, 0x5EE0, 0x61C0, 0x63D0, 0x66F0, 0x6BC0, 0x7150, 0x7850, 0x7DB0, 0x7F30, 0x7F10, 0x7EA0, 0x7EC0, 0x7EF0, + 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7F20, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7C00, 0x79E0, 0x7A70, 0x7DA0, 0x7EF0, + 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x6630, 0x4A70, 0x32C0, 0x2300, 0x1C90, 0x1ED0, 0x26C0, 0x3250, 0x3D50, 0x4610, + 0x4B50, 0x4CC0, 0x4BC0, 0x4A60, 0x48B0, 0x4840, 0x4880, 0x47F0, 0x46C0, 0x44D0, 0x42B0, 0x40D0, 0x3F40, 0x3F80, 0x4030, 0x4260, + 0x4500, 0x4850, 0x4AF0, 0x4C10, 0x4CD0, 0x4C90, 0x4BF0, 0x4A10, 0x48E0, 0x4750, 0x4680, 0x4600, 0x45D0, 0x4600, 0x46E0, 0x4760, + 0x47D0, 0x4830, 0x48E0, 0x4A00, 0x4B90, 0x4DE0, 0x4F70, 0x5180, 0x5350, 0x5530, 0x57E0, 0x5A40, 0x5CF0, 0x6000, 0x62A0, 0x6600, + 0x6880, 0x6B70, 0x6DA0, 0x6F80, 0x7340, 0x7370, 0x7370, 0x7320, 0x72B0, 0x71D0, 0x70C0, 0x7000, 0x6EB0, 0x6DB0, 0x6CC0, 0x6B80, + 0x69D0, 0x6900, 0x6840, 0x68C0, 0x69B0, 0x6AB0, 0x6D00, 0x6E90, 0x7040, 0x7190, 0x7230, 0x71F0, 0x70C0, 0x6EB0, 0x6BF0, 0x68B0, + 0x6460, 0x5F50, 0x5AA0, 0x5570, 0x5070, 0x4B70, 0x4660, 0x4120, 0x3C40, 0x36D0, 0x3120, 0x2B40, 0x2590, 0x1FD0, 0x1A60, 0x1510, + 0x0FD0, 0x0A90, 0x0500, 0xFE80, 0xF8A0, 0xF2E0, 0xEDE0, 0xE910, 0xE4A0, 0xE0C0, 0xDD10, 0xDAD0, 0xD880, 0xD660, 0xD4C0, 0xD3D0, + 0xD290, 0xD220, 0xD140, 0xD0C0, 0xD080, 0xD000, 0xCF60, 0xCEB0, 0xCDB0, 0xCCE0, 0xCCA0, 0xCCD0, 0xCD50, 0xCE40, 0xCEC0, 0xCEF0, + 0xCFA0, 0xCF30, 0xCD70, 0xCAC0, 0xC710, 0xC270, 0xBE00, 0xB910, 0xB4F0, 0xB1C0, 0xAE90, 0xAC40, 0xAB00, 0xA930, 0xA880, 0xA900, + 0xAA70, 0xAD80, 0xB030, 0xB270, 0xB270, 0xAEC0, 0xA740, 0x9B30, 0x8D50, 0x8630, 0x8500, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8480, + 0x8480, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, + 0x8500, 0x8530, 0x8590, 0x8620, 0x8780, 0x89C0, 0x8D30, 0x9110, 0x9440, 0x9820, 0x9AE0, 0x9DC0, 0xA0B0, 0xA460, 0xA9B0, 0xAF60, + 0xB5F0, 0xBDB0, 0xC6E0, 0xD160, 0xDD40, 0xEA10, 0xF9A0, 0x08C0, 0x1930, 0x2A00, 0x3B20, 0x4BF0, 0x5B90, 0x6AA0, 0x76E0, 0x7EF0, + 0x7F00, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7EE0, 0x7F10, 0x7F20, + 0x7EC0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, + 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7F20, 0x7F10, 0x7F10, 0x7F30, + 0x7EE0, 0x7ED0, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7ED0, + 0x7E90, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F10, + 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F70, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, + 0x7EF0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F70, 0x7F00, 0x7ED0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, + 0x7EA0, 0x7EE0, 0x7F10, 0x7F10, 0x7F20, 0x7E90, 0x7EF0, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F00, + 0x7F40, 0x7C50, 0x77F0, 0x7470, 0x7140, 0x6DF0, 0x6500, 0x63D0, 0x6230, 0x6070, 0x5F60, 0x5D00, 0x5B60, 0x5990, 0x57F0, 0x5740, + 0x5640, 0x5590, 0x55B0, 0x5570, 0x56C0, 0x5780, 0x5890, 0x59E0, 0x5B40, 0x5D90, 0x5F90, 0x6130, 0x63A0, 0x6530, 0x66A0, 0x6780, + 0x6890, 0x69B0, 0x6AA0, 0x6C80, 0x6ED0, 0x70B0, 0x7360, 0x75D0, 0x7910, 0x7C00, 0x7E60, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F30, + 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F80, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F80, 0x7F10, 0x7F10, 0x7EF0, + 0x7EE0, 0x7F70, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EE0, 0x7ED0, 0x7EF0, + 0x7F60, 0x7F20, 0x7E90, 0x7EF0, 0x7F00, 0x7F30, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7ED0, 0x7F10, 0x7F20, + 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7F10, + 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, + 0x7F70, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7F00, 0x7F20, 0x7ED0, 0x7EB0, 0x7F10, 0x7F20, 0x7F10, + 0x7F10, 0x7EB0, 0x7F00, 0x7C40, 0x6E50, 0x6130, 0x5440, 0x4620, 0x38D0, 0x2B00, 0x1DF0, 0x0EC0, 0x01C0, 0xF440, 0xE7B0, 0xDCA0, + 0xD270, 0xCA50, 0xC370, 0xBEA0, 0xBB20, 0xB8D0, 0xB7C0, 0xB7E0, 0xB860, 0xBAB0, 0xBD70, 0xC190, 0xC610, 0xCA50, 0xCE20, 0xD060, + 0xD0C0, 0xD0D0, 0xCF90, 0xCD80, 0xCA70, 0xC6D0, 0xC300, 0xBE10, 0xB9B0, 0xB4B0, 0xAE80, 0xA8A0, 0xA130, 0x9A20, 0x92D0, 0x8C00, + 0x8870, 0x8680, 0x85A0, 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8440, 0x8490, 0x8480, 0x8480, 0x8410, + 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, + 0x84D0, 0x84E0, 0x84E0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84C0, 0x8490, 0x8490, 0x84A0, + 0x84C0, 0x84E0, 0x8520, 0x8570, 0x8540, 0x84E0, 0x84B0, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84C0, 0x8510, 0x8850, 0xA6D0, + 0xCB80, 0xF420, 0x20E0, 0x4FD0, 0x79B0, 0x7F00, 0x7F80, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7F00, 0x7EE0, 0x7EF0, 0x7EF0, + 0x7F60, 0x7EF0, 0x7ED0, 0x62B0, 0x4260, 0x20D0, 0xFFD0, 0xDE30, 0xBDE0, 0x9D10, 0x88E0, 0x8540, 0x84E0, 0x84D0, 0x84C0, 0x84C0, + 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x8520, 0x8560, 0x8600, 0x87C0, 0x8BE0, 0x9360, 0x9B00, 0xA240, 0xA920, 0xAFA0, 0xB660, + 0xBDB0, 0xC670, 0xCF70, 0xD990, 0xE450, 0xEEE0, 0xF9C0, 0x0310, 0x0BD0, 0x1340, 0x19D0, 0x1E30, 0x21C0, 0x23C0, 0x23F0, 0x2270, + 0x1F70, 0x1AE0, 0x1450, 0x0C10, 0x0360, 0xFA60, 0xF1B0, 0xE910, 0xE1C0, 0xDB20, 0xD610, 0xD200, 0xCF10, 0xCDC0, 0xCDF0, 0xCF60, + 0xD230, 0xD750, 0xDDB0, 0xE600, 0xF0E0, 0xFCB0, 0x0850, 0x1460, 0x1F40, 0x2930, 0x3180, 0x3800, 0x3D00, 0x40C0, 0x43C0, 0x4580, + 0x4680, 0x46F0, 0x4720, 0x4670, 0x4440, 0x3FF0, 0x3B30, 0x3550, 0x3000, 0x2BA0, 0x2840, 0x25E0, 0x2370, 0x2010, 0x1B80, 0x15C0, + 0x0E80, 0x0860, 0x0370, 0x0070, 0x0000, 0x0220, 0x06B0, 0x0D80, 0x15B0, 0x1FC0, 0x28B0, 0x3170, 0x3960, 0x3FF0, 0x4580, 0x49A0, + 0x4CC0, 0x4ED0, 0x4F70, 0x4F90, 0x4EC0, 0x4D50, 0x4B80, 0x4990, 0x4600, 0x42D0, 0x3EC0, 0x39C0, 0x34E0, 0x2F90, 0x2A10, 0x24A0, + 0x1F50, 0x1A50, 0x15B0, 0x1160, 0x0DB0, 0x0A70, 0x08A0, 0x0760, 0x06C0, 0x06D0, 0x06D0, 0x06E0, 0x0740, 0x07F0, 0x08C0, 0x0A30, + 0x0BD0, 0x0E30, 0x1160, 0x14E0, 0x1950, 0x1D00, 0x2110, 0x2430, 0x2760, 0x2AA0, 0x2DB0, 0x30B0, 0x33C0, 0x3660, 0x38D0, 0x3B30, + 0x3D00, 0x3E20, 0x3E90, 0x3E90, 0x3D00, 0x3B90, 0x3950, 0x3630, 0x3300, 0x3000, 0x2C90, 0x2920, 0x2630, 0x2350, 0x1FF0, 0x1DB0, + 0x1B40, 0x1910, 0x1630, 0x0B10, 0x0820, 0x06C0, 0x05F0, 0x05F0, 0x0740, 0x09C0, 0x0E50, 0x1370, 0x19D0, 0x20B0, 0x2960, 0x3140, + 0x39B0, 0x4230, 0x49F0, 0x5230, 0x58C0, 0x5F80, 0x6550, 0x6A10, 0x6F70, 0x7340, 0x76D0, 0x7A80, 0x7D40, 0x7ED0, 0x7EA0, 0x7EC0, + 0x7F10, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7EE0, 0x7EF0, 0x7D50, 0x7880, 0x7280, 0x6B80, 0x62F0, 0x59F0, 0x4F00, 0x4200, 0x3550, + 0x2810, 0x1B20, 0x0E00, 0x0140, 0xF4F0, 0xE9E0, 0xE100, 0xD860, 0xD1F0, 0xCD70, 0xCA70, 0xC9E0, 0xCA20, 0xCC30, 0xCFE0, 0xD560, + 0xDD40, 0xE540, 0xEEB0, 0xF970, 0x0440, 0x0F90, 0x1A10, 0x2370, 0x2C70, 0x3530, 0x3D60, 0x4540, 0x4C30, 0x53D0, 0x5A60, 0x60A0, + 0x6550, 0x6890, 0x6BC0, 0x6CD0, 0x6EB0, 0x6FE0, 0x7060, 0x7190, 0x7200, 0x72B0, 0x72C0, 0x71B0, 0x7160, 0x6FC0, 0x6E10, 0x6B90, + 0x6830, 0x65C0, 0x61D0, 0x5E50, 0x5A80, 0x56D0, 0x5440, 0x5210, 0x5040, 0x4F90, 0x4F60, 0x5050, 0x5150, 0x5330, 0x5560, 0x57C0, + 0x5B50, 0x6080, 0x66A0, 0x6EC0, 0x7790, 0x7E90, 0x7F00, 0x7F50, 0x7F10, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, + 0x7EE0, 0x7F20, 0x7F20, 0x7EB0, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7E90, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7E10, 0x77F0, 0x7060, + 0x6790, 0x5E50, 0x5520, 0x4C00, 0x4350, 0x3A00, 0x31A0, 0x28C0, 0x1F10, 0x1510, 0x09A0, 0xFFD0, 0xF600, 0xECD0, 0xE440, 0xDBD0, + 0xD450, 0xCD30, 0xC620, 0xC030, 0xBAF0, 0xB6D0, 0xB300, 0xAFB0, 0xADB0, 0xABB0, 0xAAB0, 0xAA10, 0xA960, 0xAA10, 0xAA30, 0xAB00, + 0xAB80, 0xABB0, 0xAC90, 0xAD80, 0xAFC0, 0xB270, 0xB650, 0xBC20, 0xC300, 0xCB30, 0xD420, 0xDE00, 0xE7F0, 0xF120, 0xFA80, 0x0290, + 0x0910, 0x0F30, 0x1460, 0x19C0, 0x1E30, 0x21B0, 0x24E0, 0x2620, 0x25E0, 0x2400, 0x2050, 0x1AB0, 0x1360, 0x0940, 0xFD10, 0xEE20, + 0xDC40, 0xC950, 0xB590, 0xA1D0, 0x8F10, 0x86B0, 0x8520, 0x84E0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, + 0x84D0, 0x84F0, 0x8510, 0x8570, 0x8650, 0x88C0, 0x8EF0, 0x9760, 0x9D60, 0xA220, 0xA450, 0xA510, 0xA310, 0x9FD0, 0x9C50, 0x98D0, + 0x96F0, 0x9710, 0x9A50, 0xA030, 0xA910, 0xB410, 0xC0B0, 0xCCF0, 0xD990, 0xE610, 0xF170, 0xFC20, 0x0500, 0x0E30, 0x1590, 0x1AE0, + 0x1D80, 0x1D90, 0x1CF0, 0x1A30, 0x1660, 0x12E0, 0x0FD0, 0x0F00, 0x0FC0, 0x1220, 0x14F0, 0x18C0, 0x1C50, 0x1F20, 0x1FF0, 0x1FC0, + 0x1DD0, 0x1B30, 0x16A0, 0x0FF0, 0x0880, 0xFF10, 0xF4E0, 0xE990, 0xDCB0, 0xCFA0, 0xC200, 0xB620, 0xAB30, 0xA280, 0x9EC0, 0x9D90, + 0x9DE0, 0x9E70, 0x9EF0, 0x9F40, 0x9E60, 0x9CA0, 0x9A30, 0x9700, 0x94B0, 0x91B0, 0x8F60, 0x8D90, 0x8C70, 0x8CA0, 0x8DF0, 0x91C0, + 0x97B0, 0x9E90, 0xA660, 0xADB0, 0xB440, 0xB9F0, 0xBF70, 0xC510, 0xCAB0, 0xCFF0, 0xD590, 0xD9B0, 0xDD70, 0xDF10, 0xDF30, 0xDEF0, + 0xDD90, 0xDD40, 0xDDD0, 0xDEB0, 0xE1C0, 0xE570, 0xEA90, 0xF120, 0xF870, 0x0110, 0x0C00, 0x1860, 0x2620, 0x3550, 0x44F0, 0x52A0, + 0x5E20, 0x6690, 0x6C50, 0x7060, 0x7140, 0x7150, 0x6FB0, 0x6C60, 0x67D0, 0x60C0, 0x57B0, 0x4C40, 0x3E10, 0x30B0, 0x2320, 0x1750, + 0x0C10, 0x0290, 0xFAC0, 0xF3D0, 0xEE30, 0xEA20, 0xE900, 0xEAB0, 0xEEF0, 0xF560, 0xFDC0, 0x06F0, 0x10B0, 0x18E0, 0x1FD0, 0x24B0, + 0x27A0, 0x2980, 0x2980, 0x28B0, 0x27C0, 0x2670, 0x25B0, 0x25A0, 0x2570, 0x2590, 0x2550, 0x2500, 0x2460, 0x2350, 0x2260, 0x20A0, + 0x1F10, 0x1C10, 0x17E0, 0x1370, 0x0D50, 0x06B0, 0xFF00, 0xF5C0, 0xEB50, 0xDE00, 0xCF70, 0xBE90, 0xA990, 0x9230, 0x8620, 0x84E0, + 0x84B0, 0x84B0, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8470, + 0x8470, 0x8440, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84B0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x8490, 0x8490, 0x84A0, 0x8490, 0x84A0, 0x8490, 0x84A0, + 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, 0x8500, + 0x8520, 0x8540, 0x8580, 0x85E0, 0x8670, 0x8790, 0x88D0, 0x8B70, 0x8F70, 0x9420, 0x98C0, 0x9D70, 0xA270, 0xA710, 0xAC90, 0xB150, + 0xB5F0, 0xBAE0, 0xBFF0, 0xC510, 0xCA50, 0xCFA0, 0xD4F0, 0xDAB0, 0xE000, 0xE590, 0xEB30, 0xF0E0, 0xF6E0, 0xFD40, 0x0380, 0x0A50, + 0x1120, 0x1740, 0x1D50, 0x2370, 0x2910, 0x2E40, 0x3390, 0x37A0, 0x3BF0, 0x4020, 0x43F0, 0x4740, 0x4A20, 0x4CF0, 0x4FD0, 0x51B0, + 0x5360, 0x54D0, 0x5610, 0x5720, 0x5840, 0x5940, 0x5A30, 0x5BA0, 0x5CC0, 0x5E10, 0x5E50, 0x5EC0, 0x5ED0, 0x5EE0, 0x5E70, 0x5DC0, + 0x5D50, 0x5C30, 0x5B30, 0x59C0, 0x5810, 0x5610, 0x5460, 0x52A0, 0x4FD0, 0x4D30, 0x4B70, 0x49C0, 0x4880, 0x4720, 0x45E0, 0x4410, + 0x4230, 0x4090, 0x3F20, 0x3E00, 0x3CB0, 0x3C70, 0x3BF0, 0x3C10, 0x3C20, 0x3C60, 0x3C60, 0x3C80, 0x3C90, 0x3CE0, 0x3DA0, 0x3E60, + 0x3FE0, 0x4140, 0x4310, 0x44D0, 0x4630, 0x4780, 0x48C0, 0x4990, 0x4AF0, 0x4C30, 0x4DA0, 0x4F20, 0x5140, 0x52B0, 0x54D0, 0x5680, + 0x5910, 0x5AF0, 0x5DE0, 0x60E0, 0x6450, 0x67D0, 0x6B80, 0x6F20, 0x7240, 0x75B0, 0x78A0, 0x7B00, 0x7CD0, 0x7E50, 0x7F00, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x7EF0, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7ED0, 0x7EF0, 0x7F20, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, + 0x7F20, 0x7F40, 0x7EF0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7EA0, 0x7F20, 0x7EF0, + 0x7EF0, 0x7F10, 0x7EC0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7F10, 0x7230, 0x6260, 0x5570, 0x4AB0, + 0x43B0, 0x4020, 0x3F10, 0x4050, 0x4260, 0x4490, 0x4510, 0x45A0, 0x4740, 0x4B40, 0x5450, 0x61B0, 0x72F0, 0x7F10, 0x7F00, 0x7F00, + 0x7EF0, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, + 0x7F70, 0x7EB0, 0x48A0, 0x1010, 0xD570, 0x9B30, 0x8500, 0x84A0, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8420, 0x8430, + 0x8430, 0x8430, 0x8440, 0x8450, 0x8450, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84E0, 0x84E0, 0x8510, 0x8570, 0x8690, + 0x8980, 0x8EB0, 0x9480, 0x98D0, 0x9C20, 0x9E70, 0x9F80, 0x9FD0, 0x9ED0, 0x9E30, 0x9C30, 0x9960, 0x95D0, 0x9270, 0x8EF0, 0x8BF0, + 0x8990, 0x87F0, 0x86C0, 0x8600, 0x8580, 0x8530, 0x8510, 0x84F0, 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84A0, 0x84D0, 0x84A0, + 0x8490, 0x8490, 0x84B0, 0x84A0, 0x8480, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, + 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8530, 0x8550, 0x85A0, 0x8610, 0x8710, 0x88B0, 0x8BD0, 0x9080, 0x95B0, + 0x9B00, 0xA0E0, 0xA690, 0xAD90, 0xB4B0, 0xBC90, 0xC470, 0xCBE0, 0xD310, 0xDA30, 0xF230, 0xF630, 0xF9B0, 0xFC40, 0xFE50, 0xFFB0, + 0x0140, 0x0340, 0x0580, 0x07E0, 0x0A70, 0x0D40, 0x1090, 0x1350, 0x15C0, 0x1720, 0x1750, 0x16E0, 0x14D0, 0x1190, 0x0D20, 0x0770, + 0x0140, 0xFA50, 0xF3A0, 0xED90, 0xE810, 0xE3C0, 0xDFE0, 0xDC90, 0xD9B0, 0xD7B0, 0xD680, 0xD650, 0xD6B0, 0xD890, 0xDB90, 0xE060, + 0xE690, 0xEEF0, 0xFA00, 0x0610, 0x1320, 0x20A0, 0x2F10, 0x3CB0, 0x48C0, 0x5430, 0x5EB0, 0x6740, 0x6FA0, 0x7600, 0x7B10, 0x7E40, + 0x7ED0, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F20, + 0x7F20, 0x7EF0, 0x7F50, 0x7F10, 0x7DA0, 0x6440, 0x4690, 0x24F0, 0x01A0, 0xDD00, 0xB6E0, 0x9590, 0x8640, 0x8530, 0x84B0, 0x84A0, + 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, + 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, + 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, + 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8500, 0x8540, 0x85D0, 0x86C0, 0x8810, + 0x89D0, 0x8B60, 0x8C60, 0x8CA0, 0x8D00, 0x8CA0, 0x8C60, 0x8C10, 0x8BF0, 0x8C50, 0x8D10, 0x8F10, 0x9080, 0x91D0, 0x9310, 0x94E0, + 0x9680, 0x9800, 0x9970, 0x9B40, 0x9CD0, 0x9E60, 0x9EF0, 0x9ED0, 0x9DD0, 0x9BF0, 0x98D0, 0x9500, 0x9160, 0x8EE0, 0x8CD0, 0x8BF0, + 0x8BA0, 0x8C00, 0x8DB0, 0x9040, 0x9510, 0x9AA0, 0xA220, 0xAA70, 0xB310, 0xBD20, 0xC6A0, 0xD000, 0xD9F0, 0xE300, 0xEB20, 0xF2A0, + 0xF850, 0xFE30, 0x0280, 0x0620, 0x0850, 0x08B0, 0x08E0, 0x07C0, 0x05F0, 0x0380, 0x0080, 0xFE50, 0xFBD0, 0xFA60, 0xFA10, 0xFA70, + 0xFB10, 0xFBC0, 0xFC30, 0xFE00, 0xFFA0, 0x01E0, 0x04D0, 0x0770, 0x0AE0, 0x0D70, 0x1020, 0x1260, 0x13D0, 0x1590, 0x1640, 0x1760, + 0x1790, 0x17B0, 0x1870, 0x1890, 0x19A0, 0x1AD0, 0x1B70, 0x1D50, 0x1F00, 0x2140, 0x2330, 0x2510, 0x2800, 0x2A50, 0x2D50, 0x30B0, + 0x3420, 0x37C0, 0x3B00, 0x3EB0, 0x4240, 0x45D0, 0x4A60, 0x4DC0, 0x5190, 0x5510, 0x5860, 0x5BA0, 0x5F10, 0x6250, 0x65B0, 0x68E0, + 0x6C50, 0x6F80, 0x7270, 0x7520, 0x7750, 0x7A00, 0x7BB0, 0x7D30, 0x7E00, 0x7E70, 0x7ED0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, + 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, + 0x7EF0, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F40, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x76A0, 0x6AF0, 0x5D50, 0x4ED0, 0x3EB0, 0x2D40, + 0x1970, 0x02F0, 0xE9F0, 0xCC70, 0xAE00, 0x8FB0, 0x8570, 0x84C0, 0x84A0, 0x8480, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, + 0x8440, 0x8440, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84E0, 0x84C0, 0x84E0, + 0x8510, 0x8580, 0x86B0, 0x89F0, 0x9090, 0x9890, 0x9F50, 0xA4E0, 0xA880, 0xAA80, 0xAB40, 0xABD0, 0xAC70, 0xAE50, 0xB110, 0xB500, + 0xB8D0, 0xB870, 0xB0B0, 0x9FB0, 0x8AE0, 0x8530, 0x84D0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x8570, 0x8610, 0x86B0, + 0x8790, 0x8940, 0x8D60, 0x93D0, 0x9C00, 0xA420, 0xAA60, 0xAFC0, 0xB3C0, 0xB770, 0xBA60, 0xBD50, 0xC030, 0xC3A0, 0xC6B0, 0xC9C0, + 0xCC30, 0xCD80, 0xCD90, 0xCCD0, 0xCB00, 0xC8E0, 0xC8B0, 0xC9C0, 0xCC60, 0xD150, 0xD710, 0xDDF0, 0xE640, 0xF1D0, 0xFD10, 0x0920, + 0x1500, 0x2050, 0x2A90, 0x32E0, 0x39C0, 0x3EF0, 0x4320, 0x4530, 0x4610, 0x4530, 0x42F0, 0x3EF0, 0x3990, 0x3320, 0x2AC0, 0x2050, + 0x1560, 0x0920, 0xFC40, 0xEF00, 0xE1F0, 0xD6B0, 0xCD20, 0xC690, 0xC160, 0xBE40, 0xBBD0, 0xB880, 0xB550, 0xB0C0, 0xAC80, 0xA820, + 0xA470, 0xA170, 0x9FC0, 0x9F40, 0x9FC0, 0xA160, 0xA2F0, 0xA510, 0xA6A0, 0xA770, 0xA770, 0xA650, 0xA4E0, 0xA2B0, 0x9F70, 0x9C20, + 0x9820, 0x93C0, 0x8F90, 0x8B40, 0x8900, 0x8770, 0x8680, 0x8600, 0x85A0, 0x8570, 0x8550, 0x8540, 0x8540, 0x8540, 0x8550, 0x8580, + 0x85C0, 0x8660, 0x8820, 0x8CB0, 0x9670, 0xA170, 0xAB60, 0xB470, 0xBC60, 0xC3C0, 0xCA40, 0xD060, 0xD660, 0xDCC0, 0xE350, 0xE980, + 0xEFB0, 0xF510, 0xF990, 0xFCF0, 0xFF70, 0x02A0, 0x05B0, 0x0A20, 0x0EF0, 0x1590, 0x1DE0, 0x2740, 0x3290, 0x3E30, 0x49B0, 0x56C0, + 0x6410, 0x7210, 0x7D70, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7F00, 0x7F30, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, + 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, + 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7F30, 0x7EF0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F30, 0x7ED0, 0x7090, 0x5E00, 0x4460, 0x2710, 0x0830, + 0xE800, 0xC880, 0xAA80, 0x8FE0, 0x85F0, 0x84E0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8500, 0x8520, 0x8580, 0x8630, + 0x8810, 0xA710, 0xB130, 0xBA00, 0xC250, 0xCB60, 0xD450, 0xDD00, 0xE510, 0xEC70, 0xF330, 0xF930, 0xFE30, 0x0220, 0x03C0, 0x0410, + 0x01E0, 0xFDD0, 0xF7B0, 0xF010, 0xE700, 0xDDA0, 0xD590, 0xCEB0, 0xC930, 0xC5C0, 0xC410, 0xC560, 0xC890, 0xCEA0, 0xD6B0, 0xDF00, + 0xE7B0, 0xF060, 0xF7E0, 0xFFC0, 0x06C0, 0x0D00, 0x12E0, 0x1700, 0x1BB0, 0x1F30, 0x2280, 0x2560, 0x2780, 0x2AB0, 0x2D00, 0x2EB0, + 0x3060, 0x3180, 0x3290, 0x33B0, 0x3460, 0x3480, 0x33F0, 0x33B0, 0x3360, 0x3260, 0x3130, 0x2EF0, 0x22F0, 0x1FF0, 0x1D60, 0x1B10, + 0x1A30, 0x1970, 0x18C0, 0x1980, 0x1AF0, 0x1C30, 0x1F50, 0x22B0, 0x2670, 0x2A70, 0x2E10, 0x31B0, 0x34A0, 0x3790, 0x3950, 0x3AA0, + 0x3B60, 0x3A50, 0x39D0, 0x3770, 0x34A0, 0x31C0, 0x2D40, 0x28C0, 0x2390, 0x1F90, 0x1CA0, 0x1A00, 0x18F0, 0x19B0, 0x1B70, 0x1EE0, + 0x2150, 0x2200, 0x1F00, 0x17C0, 0x0DA0, 0xFF00, 0xED40, 0xD9F0, 0xC400, 0xACB0, 0x9250, 0x8640, 0x84E0, 0x84B0, 0x8490, 0x8480, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8460, 0x84B0, 0x8500, 0x8590, 0x8E30, 0xA810, 0xB9E0, 0xBF20, 0xB600, 0x9BF0, + 0x8590, 0x8490, 0x8460, 0x8440, 0x8410, 0x8400, 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8410, 0x8430, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8470, 0x8450, 0x8440, 0x8440, 0x8470, 0x8440, 0x8440, + 0x8440, 0x8460, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, + 0x8480, 0x8480, 0x8490, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8510, 0x8580, 0x86C0, 0x8AE0, 0x94E0, 0x9FD0, + 0xAA20, 0xB3F0, 0xBE10, 0xCA30, 0xD7E0, 0xE770, 0xF9E0, 0x0AB0, 0x1B50, 0x29D0, 0x3630, 0x4100, 0x4990, 0x5250, 0x5A30, 0x61D0, + 0x6950, 0x7000, 0x76E0, 0x7C40, 0x7ED0, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7EB0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, + 0x7F20, 0x7F10, 0x7F20, 0x7F40, 0x7E50, 0x76B0, 0x6D20, 0x6150, 0x5210, 0x41B0, 0x2E60, 0x1CB0, 0x0BB0, 0xFD10, 0xF1E0, 0xE980, + 0xE450, 0xE100, 0xDF10, 0xDE00, 0xDD30, 0xDBE0, 0xDB00, 0xD970, 0xD900, 0xD860, 0xD940, 0xD980, 0xDA10, 0xDB20, 0xDBB0, 0xDC90, + 0xDDA0, 0xDE40, 0xDFA0, 0xE0F0, 0xE2C0, 0xE580, 0xE830, 0xEC20, 0xF0D0, 0xF630, 0xFCB0, 0x0380, 0x0AC0, 0x11B0, 0x1870, 0x1DE0, + 0x21C0, 0x2480, 0x2640, 0x2680, 0x2730, 0x2710, 0x26E0, 0x2640, 0x2510, 0x2460, 0x22F0, 0x21D0, 0x2110, 0x1FE0, 0x1F00, 0x1E50, + 0x1CE0, 0x1B60, 0x1950, 0x1870, 0x1660, 0x1420, 0x11F0, 0x0E90, 0x0B00, 0x05E0, 0x0030, 0xF9D0, 0xF270, 0xEB90, 0xE4F0, 0xDF30, + 0xDBD0, 0xD8C0, 0xD7A0, 0xD740, 0xD7B0, 0xD870, 0xD920, 0xD890, 0xD5B0, 0xD090, 0xCA40, 0xC110, 0xB890, 0xAF50, 0xA770, 0xA110, + 0x9D80, 0x9C80, 0x9DC0, 0xA1D0, 0xA900, 0xAE70, 0xB320, 0xB610, 0xB760, 0xB790, 0xB7B0, 0xB7F0, 0xB930, 0xBBF0, 0xC020, 0xC620, + 0xCDF0, 0xD6B0, 0xE070, 0xEA50, 0xF5B0, 0xFFD0, 0x0A60, 0x1560, 0x2040, 0x2B50, 0x36B0, 0x41C0, 0x4C40, 0x5730, 0x6000, 0x68C0, + 0x7110, 0x78A0, 0x7E60, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F50, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7EF0, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F70, 0x7F10, 0x7EE0, 0x7F20, 0x7F20, 0x7F30, 0x7F40, + 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7EE0, 0x7E50, 0x7ED0, 0x7F00, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F10, 0x7EA0, + 0x7F40, 0x7EE0, 0x7EF0, 0x7F30, 0x7EA0, 0x7F40, 0x7F00, 0x7290, 0x6410, 0x55E0, 0x46C0, 0x3A30, 0x2EE0, 0x2660, 0x1ED0, 0x1910, + 0x14C0, 0x10C0, 0x0CD0, 0x0700, 0xFFC0, 0xF6B0, 0xEB30, 0xDDC0, 0xCDC0, 0xBCD0, 0xAA30, 0x97C0, 0x8980, 0x8590, 0x8500, 0x84D0, + 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8480, 0x8450, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, + 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8530, 0x8580, 0x8640, 0x8850, 0x8D00, 0x9690, 0xA180, + 0xAC50, 0xB890, 0xC530, 0xD200, 0xDF00, 0xEA90, 0xF5C0, 0x0010, 0x0B10, 0x1540, 0x1DE0, 0x25F0, 0x2BD0, 0x30C0, 0x3340, 0x3480, + 0x3330, 0x2DE0, 0x2650, 0x1A50, 0x0990, 0xF460, 0xD9B0, 0xBF60, 0xA520, 0x8DF0, 0x8600, 0x8500, 0x8480, 0x84B0, 0x8490, 0x8490, + 0x8480, 0x8470, 0x8470, 0x84B0, 0x8460, 0x8450, 0x8450, 0x8490, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, + 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8470, 0x8450, 0x8450, + 0x8460, 0x8470, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x8500, 0x8550, 0x86F0, 0x9110, + 0xA350, 0xEC50, 0xFD60, 0x0F90, 0x2130, 0x3370, 0x4520, 0x55F0, 0x6530, 0x71F0, 0x7AE0, 0x7ED0, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, + 0x5FF0, 0x57F0, 0x5240, 0x4D90, 0x4B10, 0x4A00, 0x4A20, 0x4C90, 0x4FA0, 0x53F0, 0x5A00, 0x6030, 0x6720, 0x6DC0, 0x72B0, 0x77A0, + 0x7AD0, 0x7D90, 0x7EB0, 0x7EF0, 0x7F10, 0x7EC0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F00, + 0x7F30, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, + 0x7F20, 0x7EC0, 0x7E60, 0x7E20, 0x7DF0, 0x7E10, 0x7E30, 0x7EA0, 0x7EC0, 0x7EF0, 0x7F00, 0x7EA0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F20, + 0x7E90, 0x7EB0, 0x7F00, 0x7F10, 0x7F00, 0x7EA0, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F40, + 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F70, 0x7ED0, 0x7EA0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7F00, + 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7F40, 0x7ED0, 0x7F00, 0x7F20, 0x7EF0, 0x7F70, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, + 0x7EF0, 0x7EF0, 0x7F00, 0x7EE0, 0x7F70, 0x7F00, 0x7ED0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EC0, 0x7EC0, 0x7F30, 0x7F20, + 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7EC0, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, + 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, + 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F80, 0x7F10, 0x7690, 0x68E0, 0x5940, 0x48B0, 0x3710, 0x25A0, 0x1540, 0x04D0, 0xF490, 0xE3F0, + 0xD1A0, 0xBD30, 0xA6F0, 0x8F00, 0x8610, 0x84F0, 0x84C0, 0x84B0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, + 0x84E0, 0x8500, 0x8560, 0x8660, 0x8960, 0x91B0, 0x9C00, 0xA5D0, 0xAF90, 0xB830, 0xBFE0, 0xC5D0, 0xCAF0, 0xCE90, 0xD0E0, 0xD310, + 0xD3E0, 0xD560, 0xD600, 0xD690, 0xD750, 0xD6F0, 0xD630, 0xD440, 0xD240, 0xCFB0, 0xCD20, 0xCA60, 0xC7C0, 0xC5D0, 0xC420, 0xC2D0, + 0xC100, 0xBF10, 0xBDC0, 0xBC00, 0xB9F0, 0xB760, 0xB450, 0xB080, 0xAC20, 0xA7A0, 0xA290, 0x9E60, 0x9830, 0x9330, 0x8E10, 0x8A40, + 0x8790, 0x8630, 0x8580, 0x8540, 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, + 0x84F0, 0x8500, 0x8520, 0x8530, 0x8570, 0x85B0, 0x8620, 0x86E0, 0x8800, 0x89C0, 0x8C70, 0x8F80, 0x9230, 0x9640, 0x9A20, 0x9DF0, + 0xA1F0, 0xA490, 0xA790, 0xAA10, 0xAD60, 0xB010, 0xB490, 0xB870, 0xBC30, 0xBF80, 0xC200, 0xC3D0, 0xC610, 0xC870, 0xCB00, 0xCE90, + 0xD160, 0xD4A0, 0xD6C0, 0xD910, 0xDB70, 0xDE80, 0xE1F0, 0xE530, 0xE830, 0xEB20, 0xEE10, 0xF010, 0xF2C0, 0xF560, 0xF880, 0xFAF0, + 0xFED0, 0x02C0, 0x05D0, 0x0920, 0x0C60, 0x0F50, 0x1240, 0x15B0, 0x1920, 0x1CA0, 0x1FD0, 0x22F0, 0x2640, 0x2990, 0x2CB0, 0x3030, + 0x3320, 0x3660, 0x3950, 0x3BB0, 0x3E40, 0x40B0, 0x4260, 0x4400, 0x4640, 0x4850, 0x49D0, 0x4A60, 0x49D0, 0x48F0, 0x47B0, 0x46E0, + 0x4590, 0x44B0, 0x43B0, 0x4300, 0x42E0, 0x4200, 0x40C0, 0x3F10, 0x3DF0, 0x3C90, 0x3B70, 0x3A40, 0x3970, 0x38B0, 0x3880, 0x3800, + 0x37F0, 0x3770, 0x3760, 0x3770, 0x3810, 0x3910, 0x39E0, 0x3A90, 0x3BB0, 0x3D20, 0x3EA0, 0x4040, 0x41F0, 0x42D0, 0x4400, 0x4540, + 0x4610, 0x46B0, 0x4830, 0x49E0, 0x4B10, 0x4CC0, 0x4E00, 0x4FA0, 0x50E0, 0x5210, 0x5370, 0x54A0, 0x5540, 0x55C0, 0x5610, 0x56A0, + 0x5740, 0x58F0, 0x5A90, 0x5C40, 0x5DF0, 0x5F70, 0x6110, 0x6320, 0x66E0, 0x6BD0, 0x7170, 0x7780, 0x7D10, 0x7F10, 0x7F30, 0x7EE0, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F40, 0x7DF0, 0x7780, 0x6EE0, 0x62E0, 0x52D0, 0x3EB0, 0x23E0, 0x0270, 0xDAD0, 0xA990, 0x8740, 0x84C0, + 0x8490, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8490, 0x8480, 0x8480, 0x8480, 0x8490, + 0x8480, 0x8470, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8490, 0x8460, 0x8450, 0x8470, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, + 0x8430, 0x8430, 0x8440, 0x8430, 0x8440, 0x8430, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x84A0, 0x84C0, 0x8510, + 0x8690, 0x9230, 0xA460, 0xB260, 0xBDD0, 0xC7E0, 0xCF80, 0xD6B0, 0xDC90, 0xE320, 0xE8E0, 0xEE00, 0xF290, 0xF5F0, 0xF950, 0xFBC0, + 0xFD90, 0xFF10, 0x00B0, 0x0260, 0x0420, 0x05D0, 0x08B0, 0x0B90, 0x0DF0, 0x1150, 0x1490, 0x18F0, 0x1D60, 0x21F0, 0x2770, 0x2CE0, + 0x32D0, 0x38B0, 0x3F60, 0x4660, 0x4D50, 0x5590, 0x5CF0, 0x6460, 0x6C50, 0x73E0, 0x7AC0, 0x7E80, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, + 0x7F10, 0x7F00, 0x7F10, 0x7EB0, 0x7EE0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F00, + 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7F10, + 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F50, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F00, + 0x7F00, 0x7EF0, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7EF0, + 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7EA0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, + 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7F80, 0x7DA0, 0x75E0, 0x6FA0, 0x6A20, 0x65E0, 0x6350, 0x6270, 0x6430, 0x67C0, 0x6CC0, 0x7330, + 0x7920, 0x7DF0, 0x7EF0, 0x7F70, 0x7F20, 0x7ED0, 0x7ED0, 0x7EB0, 0x7F20, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F30, 0x7F20, 0x7EA0, + 0x7DD0, 0x7C50, 0x7A50, 0x79B0, 0x78B0, 0x78C0, 0x7890, 0x77D0, 0x7760, 0x7580, 0x7380, 0x7050, 0x6B10, 0x6500, 0x5C00, 0x5140, + 0x4400, 0x3400, 0x2390, 0x1110, 0xFDF0, 0xEB90, 0xDB90, 0xCF00, 0xC710, 0xC540, 0xCA70, 0xD670, 0xE840, 0xFE90, 0x1530, 0x2B60, + 0x4090, 0x5310, 0x6250, 0x6E60, 0x76C0, 0x7B10, 0x7D60, 0x7D50, 0x7BB0, 0x78B0, 0x75F0, 0x75F0, 0x7810, 0x7C30, 0x7EE0, 0x7EF0, + 0x7ED0, 0x7EB0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7ED0, 0x72F0, 0x3E90, 0x0520, 0xC380, 0x87B0, + 0x84A0, 0x8470, 0x8440, 0x8440, 0x8430, 0x8430, 0x8450, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8410, + 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8440, 0x8420, 0x8430, 0x8430, + 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8440, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8500, 0x8540, 0x85E0, 0x8720, 0x8890, 0x8980, + 0x8930, 0x8800, 0x8730, 0x86D0, 0x8700, 0x87B0, 0x8A30, 0x8F70, 0x9810, 0xA0F0, 0xAA90, 0xB270, 0xB900, 0xBFA0, 0xC600, 0xCBC0, + 0xD250, 0xD9D0, 0xE1A0, 0xEA50, 0xF300, 0xFC20, 0x0540, 0x0F70, 0x1BE0, 0x2900, 0x3750, 0x4550, 0x5250, 0x5DD0, 0x65B0, 0x6C20, + 0x7080, 0x7210, 0x7310, 0x7180, 0x6E80, 0x6A00, 0x63E0, 0x5EA0, 0x5800, 0x51B0, 0x4C20, 0x45C0, 0x40D0, 0x3B90, 0x3690, 0x32B0, + 0x2FA0, 0x2E90, 0x2E50, 0x3030, 0x32F0, 0x3740, 0x3E10, 0x4730, 0x5270, 0x5EC0, 0x6B80, 0x77B0, 0x7EE0, 0x7F80, 0x7EF0, 0x7EB0, + 0x7F10, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EB0, 0x7F00, 0x7F40, 0x7F40, 0x7ED0, 0x7EA0, 0x7EE0, + 0x7EF0, 0x7F10, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7EF0, + 0x7F30, 0x7F20, 0x7F10, 0x7F90, 0x7B20, 0x6EC0, 0x6390, 0x57F0, 0x4C20, 0x3F10, 0x35D0, 0x2E20, 0x2780, 0x2290, 0x1EB0, 0x1C00, + 0x1A50, 0x1AF0, 0x1D20, 0x2080, 0x25B0, 0x2A90, 0x2FE0, 0x3540, 0x3A70, 0x3F90, 0x4430, 0x48A0, 0x4CF0, 0x5210, 0x56E0, 0x5BF0, + 0x60D0, 0x65A0, 0x6AE0, 0x6F90, 0x73B0, 0x7750, 0x7A50, 0x7C30, 0x7D30, 0x7DA0, 0x7D00, 0x7B50, 0x7890, 0x7400, 0x6E40, 0x6620, + 0x5D80, 0x5290, 0x4530, 0x3680, 0x25E0, 0x1370, 0xFEE0, 0xE860, 0xCE90, 0xB510, 0x9A50, 0x87E0, 0x8500, 0x84C0, 0x84A0, 0x8490, + 0x84B0, 0x8470, 0x8470, 0x8440, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, + 0x84A0, 0x84F0, 0x8540, 0x9180, 0xB7B0, 0xD9F0, 0xF900, 0x13C0, 0x2B90, 0x41D0, 0x54E0, 0x63F0, 0x6FB0, 0x76A0, 0x7A80, 0x7BF0, + 0x7B30, 0x7820, 0x72C0, 0x6A10, 0x5ED0, 0x5070, 0x4180, 0x3310, 0x24F0, 0x1680, 0x06C0, 0xF2A0, 0xDAD0, 0xBF60, 0x9F10, 0x8880, + 0x8500, 0x84C0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8540, 0x8740, + 0x9930, 0xAE50, 0xC1F0, 0xD1C0, 0xDD50, 0xE4C0, 0xE930, 0xEC20, 0xF070, 0xF790, 0x01B0, 0x0EF0, 0x1EA0, 0x3030, 0x41B0, 0x5270, + 0x6150, 0x6E70, 0x7A60, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7390, 0x6770, 0x5B60, + 0x4E60, 0x4150, 0x3460, 0x2740, 0x1A80, 0x0F50, 0x0550, 0xFCA0, 0xF520, 0xECB0, 0xE270, 0xD570, 0xC6A0, 0xB690, 0xA5D0, 0x95D0, + 0x8AF0, 0x86C0, 0x8580, 0x8530, 0x8500, 0x84F0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8520, 0x8530, 0x8540, + 0x8550, 0x8540, 0x8560, 0x8570, 0x8580, 0x85A0, 0x85B0, 0x85D0, 0x85C0, 0x85B0, 0x85C0, 0x85A0, 0x8590, 0x8580, 0x8570, 0x8560, + 0x8550, 0x8540, 0x8550, 0x8560, 0x8580, 0x85A0, 0x85F0, 0x8670, 0x8700, 0x87B0, 0x8890, 0x8970, 0x8A70, 0x8AF0, 0x8BB0, 0x8CB0, + 0x8DD0, 0x8F70, 0x9100, 0x9280, 0x93F0, 0x94F0, 0x9580, 0x9510, 0x9400, 0x9290, 0x90F0, 0x8F90, 0x8DE0, 0x8BC0, 0x89A0, 0x87C0, + 0x8650, 0x8580, 0x8530, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84F0, 0x8500, 0x8500, 0x8510, 0x8510, 0x8510, + 0x8520, 0x8530, 0x8540, 0x8540, 0x8530, 0x8520, 0x84F0, 0x84E0, 0x84C0, 0x84A0, 0x8490, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8450, 0x8430, + 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8430, 0x8450, 0x8450, 0x8460, 0x8470, 0x8490, + 0x84B0, 0x84D0, 0x84F0, 0x8500, 0x84F0, 0x84D0, 0x84C0, 0x8480, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x8510, 0x8520, 0x8590, 0x8660, + 0x87B0, 0x8890, 0x87D0, 0x8600, 0x8500, 0x84C0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8410, + 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8470, 0x84D0, 0x84F0, 0x8510, 0x8550, 0x85E0, 0x8700, 0x8960, 0x8E10, 0x9390, 0x9890, + 0x9C00, 0x9F40, 0xA210, 0xA4E0, 0xA810, 0xAC50, 0xB170, 0xB650, 0xBB00, 0xBEF0, 0xC1F0, 0xC4E0, 0xC6C0, 0xC800, 0xCA90, 0xCD20, + 0xCFF0, 0xD290, 0xD510, 0xD760, 0xD910, 0xD9F0, 0xDBA0, 0xDDD0, 0xDFB0, 0xE210, 0xE420, 0xE650, 0xE890, 0xEB20, 0xEDA0, 0xEFC0, + 0xF2F0, 0xF500, 0xF6C0, 0xF910, 0xFB80, 0xFEB0, 0x0240, 0x06F0, 0x0BE0, 0x1120, 0x1750, 0x1D90, 0x23F0, 0x2B60, 0x33C0, 0x3DD0, + 0x4800, 0x5270, 0x5D90, 0x67A0, 0x7160, 0x7940, 0x7E50, 0x7F20, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7E90, 0x7E80, 0x7F00, + 0x7EF0, 0x7F00, 0x7E90, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7EF0, 0x7F30, + 0x7F20, 0x7F00, 0x7F50, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7A20, 0x5900, 0x3D50, 0x2480, 0x0F80, + 0xFC00, 0xE7C0, 0xD150, 0xB790, 0x9BC0, 0x8730, 0x84F0, 0x84C0, 0x84A0, 0x8490, 0x8440, 0x8480, 0x8470, 0x8470, 0x8470, 0x8450, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x84F0, 0x8540, 0x86D0, 0x8F70, 0x9FC0, + 0xAE40, 0xB990, 0xC400, 0xCD60, 0xD6C0, 0xE010, 0xE8F0, 0xF190, 0xFA20, 0x0170, 0x08B0, 0x0E70, 0x1330, 0x1750, 0x1B60, 0x1FA0, + 0x2440, 0x2870, 0x2E10, 0x3270, 0x3730, 0x3B60, 0x3F50, 0x43D0, 0x4830, 0x4D80, 0x5290, 0x57F0, 0x5CC0, 0x60C0, 0x7000, 0x7290, + 0x74F0, 0x76C0, 0x7810, 0x7A20, 0x7B60, 0x7C70, 0x7CE0, 0x7D40, 0x7DD0, 0x7E30, 0x7EB0, 0x7EC0, 0x7EB0, 0x7F10, 0x7EF0, 0x7F30, + 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F30, + 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7F20, 0x7F00, 0x7EF0, 0x7EF0, + 0x7F30, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EE0, 0x7ED0, 0x7F60, 0x7F20, 0x7E90, 0x7EB0, 0x7EB0, 0x7F00, + 0x7EF0, 0x7EA0, 0x7F00, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, + 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F10, + 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7EF0, 0x7ED0, 0x7EE0, + 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F40, 0x7F10, + 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7520, 0x6750, 0x5980, 0x4A20, + 0x3CF0, 0x2FB0, 0x23A0, 0x1860, 0x0D50, 0x02F0, 0xF9E0, 0xF2D0, 0xECE0, 0xEA10, 0xEA10, 0xEC30, 0xF0A0, 0xF680, 0xFCC0, 0x02E0, + 0x0810, 0x0E20, 0x1370, 0x1990, 0x20A0, 0x2940, 0x3460, 0x4090, 0x4D30, 0x5970, 0x6460, 0x6D10, 0x7490, 0x7A60, 0x7EA0, 0x7F10, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7CA0, 0x73D0, 0x6B80, 0x6330, 0x5B20, 0x5350, 0x4B60, 0x4450, + 0x3D50, 0x3650, 0x2F20, 0x2790, 0x1FB0, 0x17E0, 0x0FC0, 0x07A0, 0xFF90, 0xF830, 0xEFC0, 0xE710, 0xDE30, 0xD550, 0xCBB0, 0xC2A0, + 0xB890, 0xAED0, 0xA4D0, 0x9B00, 0x9130, 0x8A70, 0x8710, 0x85C0, 0x8540, 0x8500, 0x84F0, 0x84E0, 0x84D0, 0x84D0, 0x84D0, 0x84C0, + 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8530, 0x85B0, 0x86F0, 0x8A80, 0x94C0, 0x9F00, 0xA8F0, 0xB180, 0xB8A0, + 0xBF30, 0xC490, 0xCA10, 0xCF20, 0xD3F0, 0xD830, 0xDC30, 0xE060, 0xE340, 0xE5F0, 0xE700, 0xE5A0, 0xE240, 0xDAA0, 0xCFA0, 0xC1C0, + 0xB070, 0x9C90, 0x8B00, 0x85A0, 0x84F0, 0x84D0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, + 0x8500, 0x8540, 0x85F0, 0x8900, 0x96D0, 0xA910, 0xBA80, 0xCA10, 0xD5A0, 0xD980, 0xD4F0, 0xC820, 0xB3D0, 0x9B00, 0x8820, 0x8500, + 0x84C0, 0x8490, 0x8480, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8420, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, + 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83C0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83B0, 0x83F0, 0x83E0, 0x83E0, 0x83F0, + 0x83C0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8430, 0x8400, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, + 0x8410, 0x83E0, 0x83E0, 0x83D0, 0x83F0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, + 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, + 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8480, 0x8450, 0x8460, 0x8430, 0x8470, 0x8460, 0x8490, 0x84A0, 0x84C0, + 0x84E0, 0x8520, 0x8580, 0x86B0, 0x8950, 0x8DB0, 0x9260, 0x9740, 0xAE30, 0xB190, 0xB570, 0xBAD0, 0xC2C0, 0xCC80, 0xD6D0, 0xE0D0, + 0xE840, 0xEDD0, 0xF0A0, 0xF210, 0xF450, 0xF850, 0xFFD0, 0x0A30, 0x17A0, 0x2820, 0x38E0, 0x48F0, 0x55E0, 0x5EA0, 0x6480, 0x6730, + 0x6820, 0x6750, 0x66D0, 0x67B0, 0x69E0, 0x6E60, 0x74F0, 0x7C20, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, + 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, 0x7EE0, 0x7F10, 0x7F30, 0x7F00, + 0x7F80, 0x7F10, 0x7F10, 0x7EE0, 0x7EE0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, 0x7EF0, 0x7F30, + 0x7EE0, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F00, 0x7F10, 0x7E90, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7E90, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, + 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, + 0x7F50, 0x7EF0, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7F00, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, + 0x7EE0, 0x7E70, 0x7EF0, 0x7F10, 0x7F30, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7EA0, 0x7F20, 0x7F10, 0x7F00, 0x7F00, + 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7F20, + 0x7F80, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7F20, 0x7EE0, 0x7ED0, 0x7EB0, 0x7F30, + 0x7EF0, 0x7EB0, 0x7EC0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7ED0, 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, + 0x7F00, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7EF0, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, 0x7F10, 0x7F70, + 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, + 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7E90, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7EC0, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F00, + 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F40, 0x7F00, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7C50, 0x7A30, 0x78F0, 0x7900, 0x7AA0, 0x7CD0, 0x7EB0, 0x7F10, 0x7F20, + 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F00, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F10, 0x7F30, 0x7F30, + 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F40, 0x7F30, 0x7F30, + 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7DB0, 0x7B60, 0x7880, 0x7480, 0x7030, 0x6BE0, 0x6720, 0x6250, + 0x5D80, 0x57E0, 0x5290, 0x4D90, 0x4920, 0x4480, 0x4010, 0x3AD0, 0x3570, 0x2FE0, 0x2A00, 0x24B0, 0x1FF0, 0x1C40, 0x1950, 0x1710, + 0x15C0, 0x1520, 0x14C0, 0x1400, 0x1380, 0x1210, 0x1010, 0x1030, 0x1160, 0x14E0, 0x1A40, 0x2190, 0x2AF0, 0x34E0, 0x3F60, 0x49C0, + 0x5490, 0x5F30, 0x6900, 0x7200, 0x79C0, 0x7E90, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7A70, 0x6E20, + 0x6280, 0x5830, 0x5170, 0x4CA0, 0x48B0, 0x4370, 0x3BD0, 0x2F40, 0x1FB0, 0x0C30, 0xF600, 0xDF40, 0xC700, 0xAFE0, 0x9900, 0x88F0, + 0x8520, 0x84D0, 0x84D0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83F0, 0x83F0, 0x8420, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x8350, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, + 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x8410, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8440, + 0x8460, 0x8460, 0x8470, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84C0, 0x84E0, 0x8530, 0x86D0, 0x9220, 0xA740, 0xBC00, + 0xD030, 0xE410, 0xF4A0, 0x0250, 0x0C60, 0x1180, 0x13C0, 0x1240, 0x0E30, 0x0870, 0x01E0, 0xFB90, 0xF4D0, 0xEF00, 0xEB70, 0xEB80, + 0xEEA0, 0xF460, 0xFD10, 0x0650, 0x0F30, 0x17C0, 0x1F50, 0x2630, 0x2DF0, 0x3720, 0x42B0, 0x4FD0, 0x5EB0, 0x6E60, 0x7C10, 0x7F00, + 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F30, 0x7F20, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EA0, 0x7F10, 0x7EF0, + 0x7F20, 0x7F00, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7F10, 0x7F20, 0x7F00, 0x7F70, 0x7EF0, 0x7F20, + 0x7F20, 0x7F00, 0x7F90, 0x7F20, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, + 0x7EF0, 0x7F00, 0x7ED0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F00, 0x7EB0, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7E90, + 0x7EE0, 0x7EF0, 0x7F10, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, + 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F50, 0x7F00, + 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7EE0, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F80, 0x7F20, + 0x7F00, 0x7EF0, 0x7ED0, 0x7F30, 0x7F10, 0x7EB0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F50, 0x7F10, 0x7E90, + 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, + 0x7EE0, 0x7F00, 0x7F00, 0x7F90, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, + 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F20, + 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F80, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F90, 0x7F10, + 0x7F20, 0x7F10, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E90, + 0x7ED0, 0x7ED0, 0x7F10, 0x7F00, 0x7E90, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, + 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, 0x7F00, 0x7550, 0x6A30, 0x5DF0, 0x5140, 0x4300, 0x35C0, 0x2880, 0x1AA0, 0x0CE0, + 0xFF10, 0xF1B0, 0xE390, 0xD540, 0xC680, 0xB900, 0xAB90, 0x9E60, 0x91D0, 0x8950, 0x8610, 0x8560, 0x84F0, 0x84D0, 0x84C0, 0x84B0, + 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, + 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x84F0, 0x84F0, 0x8500, 0x84F0, 0x8500, 0x8500, 0x84E0, 0x84D0, 0x84D0, 0x84D0, + 0x84E0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84B0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8440, 0x8460, 0x8450, 0x8450, + 0x8450, 0x8440, 0x8440, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8410, 0x8420, 0x8420, 0x8460, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x8490, + 0x84B0, 0x84C0, 0x84E0, 0x8530, 0x8680, 0x8FA0, 0xA270, 0xB450, 0xC540, 0xD480, 0xE140, 0xEC80, 0xF3C0, 0xF840, 0xF990, 0xF7B0, + 0xF350, 0xECE0, 0xE4B0, 0xDBB0, 0xD170, 0xC6D0, 0xBC80, 0xB2F0, 0xAAC0, 0xA380, 0x9C40, 0x9590, 0x8E80, 0x88D0, 0x85E0, 0x8500, + 0x84C0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8470, 0x8430, 0x8430, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, + 0x8480, 0x8490, 0x8490, 0x84B0, 0x84B0, 0x84D0, 0x84F0, 0x8540, 0x8600, 0x88C0, 0x9170, 0x9DF0, 0xA9F0, 0xB690, 0xC1E0, 0xCCB0, + 0xD770, 0xE130, 0xEB20, 0xF450, 0xFD10, 0x05C0, 0x0DE0, 0x15C0, 0x1DF0, 0x25F0, 0x2F20, 0x3780, 0x4050, 0x4960, 0x51E0, 0x5C10, + 0x6520, 0x6E80, 0x76D0, 0x7D70, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, + 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F50, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7F30, + 0x7EE0, 0x7E70, 0x7EF0, 0x7F10, 0x7F30, 0x7EC0, 0x7E90, 0x7F00, 0x7F00, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EF0, 0x7F20, 0x7EF0, + 0x7F80, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F70, 0x7EE0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EE0, 0x7EE0, 0x7F30, + 0x7F00, 0x7EC0, 0x7ED0, 0x7ED0, 0x7F10, 0x7F00, 0x7E90, 0x7ED0, 0x7F10, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, + 0x7F60, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F70, + 0x7F00, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7EA0, 0x7F00, 0x7EB0, 0x7EE0, 0x7EF0, + 0x7F30, 0x7EE0, 0x7EC0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7F80, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F80, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, 0x7F20, + 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, + 0x7F10, 0x7F10, 0x7E90, 0x7EB0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, + 0x7EF0, 0x7EF0, 0x7DB0, 0x7A40, 0x7640, 0x72F0, 0x6F00, 0x6B20, 0x6690, 0x6200, 0x5DB0, 0x5940, 0x53B0, 0x4EA0, 0x48F0, 0x4490, + 0x3F30, 0x3A60, 0x3540, 0x3050, 0x2C70, 0x27C0, 0x23F0, 0x2110, 0x1D70, 0x1B00, 0x1890, 0x15F0, 0x14A0, 0x1360, 0x12E0, 0x12C0, + 0x12B0, 0x13A0, 0x1460, 0x15E0, 0x1710, 0x18F0, 0x1BC0, 0x1E40, 0x2170, 0x2470, 0x2720, 0x2B50, 0x2EB0, 0x32B0, 0x3670, 0x3A00, + 0x3E00, 0x4080, 0x42D0, 0x4550, 0x46E0, 0x49A0, 0x4B10, 0x4D70, 0x4F10, 0x50C0, 0x5250, 0x5370, 0x5430, 0x54E0, 0x5490, 0x54B0, + 0x54A0, 0x5460, 0x5420, 0x5380, 0x53D0, 0x53B0, 0x53A0, 0x5420, 0x53C0, 0x5450, 0x54A0, 0x54E0, 0x54D0, 0x5430, 0x5340, 0x5180, + 0x4E90, 0x4C90, 0x4A00, 0x47C0, 0x4570, 0x42F0, 0x4120, 0x3D90, 0x39D0, 0x34C0, 0x2E80, 0x2810, 0x1FB0, 0x1580, 0x0A80, 0xFE70, + 0xF1A0, 0xE2E0, 0xD3C0, 0xC370, 0xB270, 0xA170, 0x8F60, 0x8720, 0x8530, 0x84E0, 0x84C0, 0x84B0, 0x84B0, 0x8490, 0x84A0, 0x84B0, + 0x84B0, 0x84D0, 0x84F0, 0x8530, 0x85D0, 0x8790, 0x8B90, 0x92C0, 0x9A70, 0xA1B0, 0xA810, 0xAE50, 0xB470, 0xB960, 0xBCF0, 0xBE10, + 0xBC90, 0xB7B0, 0xB090, 0xA6F0, 0x9BF0, 0x9090, 0x8900, 0x85F0, 0x8510, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8450, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, + 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8510, 0x8530, 0x8560, 0x85B0, + 0x8620, 0x86D0, 0x87E0, 0x8940, 0x8B10, 0x8CE0, 0x8FB0, 0x9360, 0x9820, 0x9E20, 0xA5C0, 0xAEE0, 0xB8C0, 0xC450, 0xD140, 0xDF00, + 0xEFF0, 0xFFC0, 0x1050, 0x20B0, 0x3080, 0x3FA0, 0x4D90, 0x5AD0, 0x6630, 0x7100, 0x7A00, 0x7EB0, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, + 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7EF0, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x6050, 0x2690, 0xF290, 0xC6B0, 0xA370, 0x9090, 0x8AC0, 0x8C60, 0x9630, + 0xA670, 0xB800, 0xC930, 0xD780, 0xE2C0, 0xEA60, 0xEE50, 0xF130, 0xF4C0, 0xFAB0, 0x0310, 0x0EB0, 0x1B40, 0x27B0, 0x3060, 0x3580, + 0x3750, 0x3730, 0x3620, 0x3540, 0x3480, 0x33B0, 0x3380, 0x32E0, 0x3110, 0x2E10, 0x29E0, 0x25C0, 0x2110, 0x1D10, 0x1970, 0x1620, + 0x13D0, 0x1110, 0x0D70, 0x0A40, 0x06B0, 0x0250, 0xFE20, 0xFB00, 0xF7A0, 0xF4A0, 0xF140, 0xEE20, 0xEB50, 0xE7D0, 0xE4B0, 0xE240, + 0xE100, 0xE0B0, 0xE210, 0xE3A0, 0xE620, 0xE920, 0xEC20, 0xEFB0, 0xF230, 0xF470, 0xF6C0, 0xF840, 0xF960, 0xF9A0, 0xFA10, 0xF990, + 0xF830, 0xF670, 0xF350, 0xF0B0, 0xEDF0, 0xEC60, 0xEBF0, 0xEC80, 0xEEC0, 0xF2A0, 0xF6D0, 0xFB30, 0xFF00, 0x01C0, 0x02D0, 0x02A0, + 0x0140, 0xFF70, 0xFCF0, 0xFAF0, 0xF970, 0xF7D0, 0xF670, 0xF4E0, 0xF440, 0xF450, 0xF580, 0x0B90, 0x1820, 0x2810, 0x3A10, 0x4BA0, + 0x5BA0, 0x6800, 0x7050, 0x7520, 0x7780, 0x7910, 0x7B10, 0x7DA0, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, + 0x7F10, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F90, 0x7F30, 0x7EE0, 0x7F20, 0x7F10, 0x7F50, 0x7F20, 0x7EA0, 0x7F10, 0x7F10, 0x7F40, 0x7F00, + 0x7E90, 0x7E90, 0x7EE0, 0x7EF0, 0x7ED0, 0x7EA0, 0x7F00, 0x7F10, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7D40, 0x78B0, 0x71B0, 0x6970, 0x5E00, 0x51C0, 0x43D0, 0x34B0, 0x24B0, 0x1400, 0x02F0, + 0xF250, 0xE0A0, 0xCF60, 0xC000, 0xB2A0, 0xA7B0, 0xA100, 0x9EA0, 0xA130, 0xA970, 0xB700, 0xC950, 0xDD40, 0xF2A0, 0x06D0, 0x1970, + 0x2860, 0x34E0, 0x3DD0, 0x43E0, 0x4840, 0x4AA0, 0x4BD0, 0x4D20, 0x4DA0, 0x4F10, 0x5080, 0x5270, 0x5420, 0x5430, 0x5270, 0x4D00, + 0x4790, 0x43E0, 0x44C0, 0x4BC0, 0x53F0, 0x59F0, 0x5860, 0x4D40, 0x3950, 0x1EA0, 0x0100, 0xE270, 0xC550, 0xAA30, 0x9040, 0x8580, + 0x84D0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8430, 0x8410, 0x83F0, 0x83E0, 0x83C0, 0x83A0, + 0x8390, 0x8380, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8380, 0x8380, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, + 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x8400, 0x83D0, 0x83D0, 0x83E0, + 0x83A0, 0x83E0, 0x83E0, 0x83F0, 0x8380, 0x8400, 0x8400, 0x8410, 0x8420, 0x8410, 0x8410, 0x8430, 0x8440, 0x8410, 0x8420, 0x8420, + 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x83F0, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, + 0x8450, 0x8450, 0x8470, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8430, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8460, 0x8440, 0x8440, 0x8440, 0x8460, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8480, 0x8450, 0x8460, 0x8460, 0x8440, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, + 0x84A0, 0x84B0, 0x84E0, 0x8530, 0x8690, 0x9090, 0xA450, 0xB7A0, 0xCB60, 0xDE10, 0xF040, 0x0300, 0x14D0, 0x2700, 0x3860, 0x4B40, + 0x5C80, 0x6E40, 0x7BD0, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F70, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7F60, 0x7EE0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, + 0x7EE0, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F20, + 0x7F00, 0x7F10, 0x7EF0, 0x7F00, 0x7F20, 0x7EF0, 0x7F80, 0x7EE0, 0x7F10, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, + 0x7F70, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F70, 0x7F00, 0x7ED0, 0x7EB0, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EC0, 0x7EC0, 0x7EF0, + 0x7F20, 0x7EA0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7E90, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7E70, 0x7EE0, 0x7F10, 0x7F10, 0x7F20, + 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F40, 0x7F10, 0x7F00, + 0x7F30, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7F70, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F50, 0x7EB0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F30, + 0x7EC0, 0x7EB0, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7E90, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, + 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, + 0x7F70, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F90, 0x7F20, 0x6280, 0x3EC0, 0x16D0, 0xEC60, 0xC040, 0x90E0, 0x8500, 0x84B0, 0x8480, + 0x8470, 0x8460, 0x8480, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8450, 0x8440, 0x8440, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84D0, 0x84C0, + 0x84D0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, + 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84A0, + 0x84A0, 0x84A0, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84E0, 0x84F0, + 0x8500, 0x8510, 0x8530, 0x8560, 0x85A0, 0x8610, 0x86F0, 0x8840, 0x8A20, 0x8CC0, 0x8F90, 0x9270, 0x9540, 0x97A0, 0x9990, 0x9B10, + 0x9CD0, 0x9E40, 0x9F80, 0xA070, 0xA0D0, 0xA170, 0xA2F0, 0xA450, 0xA5E0, 0xA7E0, 0xA9C0, 0xABE0, 0xADE0, 0xB0B0, 0xB460, 0xB8D0, + 0xBD70, 0xC1F0, 0xC700, 0xCC80, 0xD1C0, 0xD760, 0xDD50, 0xE430, 0xEAA0, 0xF110, 0xF7A0, 0xFE00, 0x03F0, 0x0A30, 0x1150, 0x1820, + 0x1F10, 0x2530, 0x2AE0, 0x30C0, 0x3650, 0x3BB0, 0x4130, 0x4700, 0x4C50, 0x5240, 0x5740, 0x5B70, 0x6110, 0x65E0, 0x69D0, 0x6E50, + 0x7180, 0x7500, 0x77C0, 0x7970, 0x7B90, 0x7BE0, 0x7C80, 0x7CD0, 0x7C70, 0x7BF0, 0x7460, 0x7150, 0x6D90, 0x68B0, 0x6400, 0x5E10, + 0x5910, 0x5320, 0x4BF0, 0x4550, 0x3DB0, 0x3680, 0x2EE0, 0x2640, 0x1ED0, 0x16A0, 0x0F60, 0x0870, 0x0230, 0xFD70, 0xF8C0, 0xF580, + 0xF290, 0xF090, 0xF020, 0xEF80, 0xEFD0, 0xEF60, 0xEF20, 0xEED0, 0xEDF0, 0xEC60, 0xEA40, 0xE6F0, 0xE3B0, 0xDF30, 0xDA10, 0xD4C0, + 0xCE80, 0xC8F0, 0xC2E0, 0xBCD0, 0xB670, 0xAFD0, 0xA850, 0xA0D0, 0x9980, 0x9160, 0x8BA0, 0x8820, 0x8650, 0x8580, 0x8530, 0x8500, + 0x84E0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x8490, 0x8490, + 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8450, 0x8430, 0x8420, 0x8410, 0x8420, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8420, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, + 0x8420, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x84A0, 0x84A0, 0x84F0, 0x8580, 0x8910, 0x99C0, 0xAAC0, 0xB990, + 0xC570, 0xCF20, 0xD6A0, 0xDC10, 0xDFE0, 0xE2A0, 0xE560, 0xE790, 0xE870, 0xE8C0, 0xE770, 0xE450, 0xDF20, 0xD7B0, 0xCF10, 0xC4B0, + 0xB9C0, 0xAD00, 0x9EF0, 0x90B0, 0x87B0, 0x8530, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, + 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8480, 0x8490, 0x84B0, 0x84C0, 0x84F0, 0x8550, 0x86A0, + 0x8BF0, 0x97D0, 0xA370, 0xAE50, 0xB880, 0xC250, 0xCAC0, 0xD1F0, 0xD700, 0xDAF0, 0xDE40, 0xE120, 0xE490, 0xE910, 0xECC0, 0xF290, + 0xF770, 0xFD20, 0x02E0, 0x0830, 0x0E00, 0x1320, 0x1960, 0x1FD0, 0x2770, 0x2F40, 0x3710, 0x3FF0, 0x47E0, 0x4F70, 0x5800, 0x5E80, + 0x6560, 0x6C60, 0x71F0, 0x7790, 0x7C10, 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7F20, + 0x7EC0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EB0, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F10, 0x7E90, + 0x7EA0, 0x7E80, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F50, + 0x7F20, 0x7EF0, 0x7EF0, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F50, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, + 0x7EC0, 0x7EF0, 0x7F00, 0x7F50, 0x7EB0, 0x7EA0, 0x7EF0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, + 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7E70, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F40, + 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7F80, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F00, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, + 0x7EE0, 0x7ED0, 0x7F00, 0x7F20, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F40, + 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F60, 0x7EA0, 0x79D0, 0x7490, 0x6E30, 0x6760, 0x5FC0, 0x5790, 0x4ED0, 0x4610, 0x3C60, 0x31F0, + 0x2610, 0x1930, 0x0B30, 0xFC20, 0xEC70, 0xDA80, 0xCAD0, 0xBAB0, 0xAB70, 0x9D40, 0x91A0, 0x8A90, 0x8780, 0x8660, 0x85D0, 0x8580, + 0x8530, 0x84F0, 0x84D0, 0x84C0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x8500, 0x8530, 0x8570, + 0x85C0, 0x8700, 0x88E0, 0x8C50, 0x9210, 0x97E0, 0x9E00, 0xA460, 0xAA90, 0xB0E0, 0xB790, 0xBDC0, 0xC330, 0xC950, 0xCED0, 0xD4B0, + 0xDA60, 0xE140, 0xE7F0, 0xEF30, 0xF740, 0xFF40, 0x0820, 0x1170, 0x1AE0, 0x2530, 0x2EE0, 0x38D0, 0x4290, 0x4CC0, 0x56F0, 0x61B0, + 0x6B70, 0x7590, 0x7D90, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, + 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, + 0x7F40, 0x7F30, 0x73B0, 0x6620, 0x5840, 0x49B0, 0x3B50, 0x2D20, 0x1FA0, 0x10F0, 0x03A0, 0xF640, 0xE880, 0xDB20, 0xCD40, 0xBFE0, + 0xB2F0, 0xA6C0, 0x9A50, 0x8F40, 0x88B0, 0x8600, 0x8530, 0x84E0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x84A0, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8450, 0x8450, 0x8440, 0x8450, 0x8440, 0x8480, 0x8450, + 0x8460, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8410, + 0x8400, 0x83F0, 0x83E0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, + 0x83C0, 0x83C0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8450, 0x8460, 0x8480, 0x8480, + 0x8490, 0x84C0, 0x84E0, 0x8520, 0x8580, 0x85B0, 0x85F0, 0x85B0, 0x85A0, 0x8590, 0x8540, 0x85C0, 0x85F0, 0x8660, 0x86F0, 0x87B0, + 0x8840, 0x88D0, 0x8930, 0x8970, 0x89D0, 0x89F0, 0x8970, 0x88E0, 0x87B0, 0x8510, 0x84F0, 0x84F0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, + 0x8490, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8470, 0x8450, 0x8400, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8490, 0x84B0, 0x8520, 0x8A30, 0xA9D0, 0xC2F0, 0xD340, 0xDF30, + 0xE870, 0xF160, 0xFA70, 0x05A0, 0x1160, 0x1D50, 0x2B30, 0x36A0, 0x4270, 0x4DD0, 0x5930, 0x6580, 0x7180, 0x7CD0, 0x7F10, 0x7F40, + 0x7F10, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7F40, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, + 0x7F20, 0x7F40, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7EE0, 0x7F10, 0x7F60, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, + 0x7F60, 0x7F10, 0x7E90, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EE0, 0x7F00, + 0x7EF0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F30, 0x7EF0, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EE0, 0x7F10, + 0x7F10, 0x7F10, 0x7E90, 0x7EC0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7D30, 0x65E0, 0x4F80, 0x37D0, 0x2010, 0x0830, + 0xF240, 0xDE10, 0xCBB0, 0xBBB0, 0xAC50, 0xA140, 0x99E0, 0x9730, 0x9A90, 0xA470, 0xB530, 0xCA70, 0xE2D0, 0xFDE0, 0x1640, 0x2C20, + 0x4090, 0x53B0, 0x6520, 0x7480, 0x7E90, 0x7F00, 0x7F90, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, + 0x7F10, 0x7EB0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7E00, 0x6F10, 0x61E0, 0x5570, + 0x4B90, 0x4340, 0x3E40, 0x39C0, 0x3620, 0x32A0, 0x2E20, 0x2950, 0x2590, 0x2370, 0x2540, 0x29B0, 0x2FF0, 0x36A0, 0x3960, 0x37B0, + 0x2F10, 0x1F60, 0x09F0, 0xED30, 0xD020, 0xB130, 0x9380, 0x8610, 0x84E0, 0x84B0, 0x84A0, 0x8480, 0x8480, 0x8470, 0x8480, 0x8480, + 0x8480, 0x8490, 0x84B0, 0x84D0, 0x8570, 0x8EE0, 0xADF0, 0xC8C0, 0xDF00, 0xF0B0, 0xFD20, 0x05E0, 0x0A90, 0x0CB0, 0x0CC0, 0x0B30, + 0x0970, 0x0760, 0x0600, 0x0610, 0x0870, 0x0C70, 0x11E0, 0x1990, 0x2240, 0x2BE0, 0x3790, 0x4430, 0x5320, 0x62A0, 0x72C0, 0x7EB0, + 0x7EF0, 0x7F60, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EB0, 0x7F00, 0x7EF0, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, + 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7F20, 0x7EE0, 0x7F50, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7EF0, 0x7EF0, + 0x7F00, 0x7F70, 0x7F00, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7EE0, + 0x7F30, 0x7F00, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7F00, 0x7EB0, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F00, 0x7EE0, + 0x7EF0, 0x7F80, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, + 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7EA0, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, + 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7F40, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7EF0, 0x7F10, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7740, 0x6BF0, 0x5FB0, 0x5230, 0x4440, + 0x34F0, 0x2550, 0x14B0, 0x0300, 0xEF80, 0xDCB0, 0xC960, 0xB520, 0xA090, 0x8CF0, 0x85D0, 0x84F0, 0x84B0, 0x8490, 0x8480, 0x8470, + 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8420, + 0x8420, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8420, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8420, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, + 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x85A0, 0x8C00, 0xA450, 0xBB10, 0xD010, 0xE380, 0xF770, 0x0910, + 0x1A30, 0x2B10, 0x3B90, 0x4B30, 0x59E0, 0x6840, 0x7510, 0x7E70, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F50, 0x7F30, + 0x7F80, 0x7F30, 0x7F00, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7EF0, 0x7F20, 0x7F00, 0x7EF0, 0x7ED0, 0x7F10, 0x7F40, + 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, 0x7F50, 0x7EE0, 0x7EA0, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7E90, 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, + 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x75F0, 0x6A80, 0x5D90, + 0x5050, 0x42F0, 0x3540, 0x2850, 0x1C10, 0x10B0, 0x0700, 0x0010, 0xFB80, 0xF900, 0xF8D0, 0xFB50, 0xFF30, 0x06A0, 0x0F20, 0x1A90, + 0x2730, 0x3460, 0x4360, 0x52F0, 0x6270, 0x7220, 0x7D90, 0x7ED0, 0x7F00, 0x7F30, 0x7F10, 0x7EB0, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, + 0x7EC0, 0x7ED0, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, + 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F80, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, + 0x7EE0, 0x7ED0, 0x7F00, 0x7F00, 0x7F50, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EB0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F10, 0x7ED0, + 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F10, + 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, + 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7ED0, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7F60, 0x7ED0, + 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7E90, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EC0, + 0x7F10, 0x7EF0, 0x7F00, 0x7F10, 0x7F00, 0x7F60, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, + 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7FA0, 0x7EF0, 0x7B50, 0x7570, 0x6F60, 0x6850, 0x60B0, 0x5830, 0x4F10, 0x45C0, + 0x3B70, 0x3130, 0x2610, 0x1B00, 0x0FA0, 0x0450, 0xF990, 0xEE10, 0xE450, 0xDAC0, 0xD0F0, 0xC7F0, 0xBE30, 0xB5A0, 0xAD30, 0xA5C0, + 0x9EF0, 0x98C0, 0x93E0, 0x9060, 0x8DF0, 0x8CC0, 0x8C30, 0x8D10, 0x8F60, 0x9320, 0x9890, 0x9F00, 0xA690, 0xAF70, 0xB910, 0xC370, + 0xCDD0, 0xD860, 0xE3C0, 0xEE10, 0xF8C0, 0x02C0, 0x0CF0, 0x16F0, 0x2070, 0x2A60, 0x32F0, 0x3BB0, 0x4340, 0x49F0, 0x50F0, 0x56B0, + 0x5BF0, 0x60F0, 0x6590, 0x69B0, 0x6D90, 0x7050, 0x7260, 0x73E0, 0x7550, 0x75D0, 0x75B0, 0x75A0, 0x7500, 0x7440, 0x72F0, 0x7130, + 0x6FE0, 0x6DC0, 0x6BD0, 0x6980, 0x65A0, 0x6300, 0x5E80, 0x5B00, 0x5720, 0x5300, 0x4F90, 0x4B00, 0x46A0, 0x4180, 0x3B30, 0x3500, + 0x2E40, 0x2750, 0x2000, 0x1720, 0x0F40, 0x05F0, 0xFC10, 0xF1A0, 0xE520, 0xD9D0, 0xCDD0, 0xC1C0, 0xB5A0, 0xA910, 0x9C90, 0x9090, + 0x88D0, 0x85D0, 0x8510, 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8470, + 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, + 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, + 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, + 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8420, 0x8430, 0x8420, 0x8430, + 0x8430, 0x8440, 0x83E0, 0x8440, 0x8450, 0x8440, 0x8450, 0x8460, 0x8450, 0x8450, 0x8410, 0x8460, 0x8460, 0x8450, 0x8460, 0x8460, + 0x8460, 0x83F0, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8410, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8460, 0x8480, 0x8480, 0x8490, 0x8490, 0x84C0, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x84A0, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8490, 0x8460, + 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84B0, 0x84C0, 0x8500, 0x85E0, 0x8C10, 0xA140, 0xB4F0, 0xC8F0, + 0xDA20, 0xE8F0, 0xF720, 0x0320, 0x0EE0, 0x1990, 0x2360, 0x2BE0, 0x3440, 0x3AD0, 0x4100, 0x4720, 0x4BD0, 0x5050, 0x5480, 0x5820, + 0x5B70, 0x5E70, 0x6120, 0x6340, 0x6510, 0x6630, 0x66B0, 0x66A0, 0x64D0, 0x6210, 0x5E60, 0x5A00, 0x54D0, 0x4F70, 0x4960, 0x4340, + 0x3CB0, 0x35D0, 0x2E60, 0x2690, 0x1F00, 0x1820, 0x1110, 0x0930, 0x0110, 0xF7C0, 0xECD0, 0xDFF0, 0xCFA0, 0xBEE0, 0xAE00, 0x9C30, + 0x8D30, 0x8690, 0x8530, 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8460, 0x8480, 0x8480, + 0x8480, 0x8490, 0x8490, 0x84B0, 0x84C0, 0x84E0, 0x8530, 0x8650, 0x8BF0, 0x9E90, 0xAF70, 0xC050, 0xD030, 0xDFB0, 0xEEF0, 0xFE40, + 0x0D50, 0x1D00, 0x2D40, 0x3C10, 0x4B00, 0x5880, 0x65C0, 0x7150, 0x7AB0, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7E70, 0x7EE0, 0x7EF0, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7ED0, 0x7F00, 0x7EB0, 0x7E60, 0x7EC0, + 0x7ED0, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, + 0x7F20, 0x7F00, 0x7F00, 0x7F50, 0x7F10, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F10, 0x7F40, 0x7ED0, 0x7E90, + 0x7F10, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, + 0x7F10, 0x7F20, 0x7F40, 0x7EC0, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, 0x7F10, + 0x7F20, 0x7F10, 0x7F10, 0x77F0, 0x6E60, 0x63C0, 0x5B50, 0x53B0, 0x4DA0, 0x49C0, 0x4750, 0x4780, 0x4970, 0x4D70, 0x5340, 0x5940, + 0x6090, 0x68F0, 0x7130, 0x7940, 0x7E00, 0x7ED0, 0x7F00, 0x7EF0, 0x7F10, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, + 0x7F10, 0x7F00, 0x7F00, 0x70C0, 0x5750, 0x3DA0, 0x2040, 0xFCD0, 0xD0B0, 0x95B0, 0x84D0, 0x84A0, 0x8470, 0x8450, 0x8470, 0x8440, + 0x8440, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, 0x83F0, 0x8400, 0x83E0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x8390, + 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x83B0, 0x83C0, 0x83D0, 0x83D0, + 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83C0, 0x83B0, 0x83B0, + 0x83E0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83E0, 0x83C0, 0x83C0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8450, 0x8460, 0x8490, 0x8490, 0x84A0, 0x84D0, 0x85B0, 0x8B50, 0xA8F0, 0xC4E0, + 0xE1D0, 0xFB60, 0x12C0, 0x2990, 0x3E00, 0x51C0, 0x63E0, 0x73C0, 0x7E70, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, + 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, + 0x7F20, 0x7EF0, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F80, 0x7F20, 0x7F10, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EF0, + 0x7ED0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7E90, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7EB0, + 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7DE0, 0x73D0, 0x6830, 0x5890, 0x48B0, 0x36E0, 0x2320, 0x0EB0, 0xF800, 0xE020, 0xC6B0, + 0xAB70, 0x8F30, 0x85B0, 0x8500, 0x84A0, 0x8480, 0x84A0, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8450, 0x8420, 0x8410, + 0x8410, 0x8450, 0x8410, 0x8410, 0x8410, 0x8430, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8430, 0x8460, + 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8460, 0x8450, 0x8450, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, + 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84F0, 0x85A0, 0x8E80, 0xA990, 0xC530, + 0xE260, 0x0100, 0x1FB0, 0x3DB0, 0x5C40, 0x73B0, 0x7EF0, 0x7EE0, 0x7F50, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F60, 0x7F00, 0x7F10, + 0x7F10, 0x7EF0, 0x7F60, 0x7EE0, 0x7EB0, 0x7F10, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7EF0, 0x7EF0, 0x7F20, 0x7ED0, 0x7E90, 0x7EF0, + 0x7EE0, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F10, 0x7F00, 0x7F30, 0x7F00, + 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F90, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EF0, + 0x7EB0, 0x7EE0, 0x7F50, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, 0x7EC0, 0x7F50, 0x7F10, 0x7E70, 0x7EC0, + 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, + 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7150, 0x5A60, 0x4260, + 0x2B10, 0x13D0, 0xFAD0, 0xE4D0, 0xCF30, 0xBB00, 0xA880, 0x97E0, 0x8C50, 0x8770, 0x8600, 0x85A0, 0x85C0, 0x85E0, 0x86B0, 0x88E0, + 0x8E30, 0x96E0, 0x9E70, 0xA3E0, 0xA710, 0xA6A0, 0xA450, 0x9ED0, 0x9760, 0x8F10, 0x88F0, 0x8600, 0x8520, 0x84D0, 0x84B0, 0x84A0, + 0x8480, 0x8470, 0x8470, 0x8460, 0x8450, 0x8420, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, + 0x8400, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, + 0x83A0, 0x83A0, 0x83C0, 0x83B0, 0x83A0, 0x83B0, 0x83D0, 0x83C0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x8410, 0x83F0, 0x83F0, + 0x83F0, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8470, 0x8480, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, + 0x84B0, 0x84C0, 0x84E0, 0x8570, 0x8A10, 0xA5E0, 0xC170, 0xDB00, 0xF170, 0x0370, 0x1080, 0x1980, 0x1FB0, 0x22A0, 0x22E0, 0x2190, + 0x1CC0, 0x1590, 0x0A50, 0xFD60, 0xEED0, 0xDE80, 0xCD10, 0xBAE0, 0xA7F0, 0x9550, 0x8890, 0x8540, 0x84E0, 0x84B0, 0x84A0, 0x8480, + 0x8470, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8420, 0x8430, + 0x8410, 0x8450, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84C0, 0x8500, 0x8610, 0x93D0, 0xB140, 0xCDE0, 0xE9B0, 0x0350, 0x1B80, 0x3270, + 0x4890, 0x5ED0, 0x7160, 0x7ED0, 0x7F10, 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F10, 0x7F70, 0x7EF0, 0x7ED0, 0x7F00, 0x7F10, 0x7F30, + 0x7EB0, 0x7E70, 0x7EF0, 0x7EE0, 0x7F30, 0x7ED0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7EC0, 0x7EF0, 0x7F10, + 0x7F50, 0x7ED0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F10, 0x7EF0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F10, + 0x7F20, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F20, + 0x7F10, 0x7F90, 0x7EF0, 0x7EE0, 0x7F10, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EE0, 0x7F00, 0x7EF0, + 0x7F30, 0x7F10, 0x7E70, 0x7EC0, 0x7EF0, 0x7F20, 0x7EF0, 0x7E90, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, + 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F10, 0x7F00, 0x7300, 0x5A00, 0x4780, 0x3820, 0x29E0, 0x1DD0, + 0x1690, 0x1740, 0x22A0, 0x37D0, 0x5670, 0x75B0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F20, 0x7EF0, 0x7F90, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F30, 0x7EC0, 0x7EC0, 0x5410, 0x1730, 0xD8B0, 0xA040, 0x8600, 0x84E0, 0x84D0, 0x84E0, 0x8510, 0x8610, 0x8A80, 0x9360, 0x9740, + 0x96F0, 0x9440, 0x92C0, 0x93C0, 0x96A0, 0x9CD0, 0xADB0, 0xAEA0, 0xAEB0, 0xAD30, 0xAD30, 0xAD60, 0xADB0, 0xAEC0, 0xAF90, 0xB0C0, + 0xB110, 0xB150, 0xB1A0, 0xB170, 0xB160, 0xB150, 0xB200, 0xB2C0, 0xB370, 0xB470, 0xB4C0, 0xB510, 0xB450, 0xB340, 0xB120, 0xAE00, + 0xAA20, 0xA5D0, 0xA030, 0x9A80, 0x94B0, 0x8E10, 0x8930, 0x8680, 0x8560, 0x8500, 0x84D0, 0x8450, 0x84A0, 0x8490, 0x8480, 0x8430, + 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83E0, 0x83D0, 0x83D0, 0x83F0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x8400, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84B0, + 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8530, 0x8570, 0x85E0, 0x8660, 0x8690, 0x8630, 0x8590, 0x8520, 0x84E0, + 0x84C0, 0x84B0, 0x8490, 0x8480, 0x8430, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8470, 0x8450, 0x8440, 0x8440, + 0x83F0, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8470, 0x8490, 0x84D0, 0x92F0, 0xDA30, 0x1BC0, 0x5750, 0x7ED0, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x75C0, 0x66F0, 0x5830, 0x4960, 0x3B40, 0x2E10, 0x2180, 0x1720, + 0x0EC0, 0x07F0, 0x0360, 0xFF20, 0xFC60, 0xF9C0, 0xF690, 0xF300, 0xEFB0, 0xEBD0, 0xE810, 0xE460, 0xE090, 0xDD90, 0xDAF0, 0xD970, + 0xD7B0, 0xD690, 0xD4B0, 0xD210, 0xCE40, 0xC960, 0xC390, 0xBD10, 0xB7D0, 0xB290, 0xB020, 0xAE70, 0xAF60, 0xB1F0, 0xB5A0, 0xBA40, + 0xBF50, 0xC4F0, 0xCAD0, 0xCF70, 0xD360, 0xD5F0, 0xD6A0, 0xD490, 0xCFF0, 0xC8B0, 0xBE40, 0xAF30, 0x9D00, 0x8A60, 0x8530, 0x84C0, + 0x8490, 0x8470, 0x8460, 0x8440, 0x8430, 0x8420, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, + 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, + 0x8440, 0x8450, 0x8480, 0x8460, 0x8460, 0x8470, 0x8430, 0x8490, 0x84A0, 0x84B0, 0x84F0, 0x85E0, 0x90C0, 0xADB0, 0xCA10, 0xE730, + 0x0340, 0x1E60, 0x3A30, 0x5640, 0x6D50, 0x7E30, 0x7F00, 0x7EF0, 0x7EF0, 0x7F50, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7F20, + 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7ED0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F30, 0x7EF0, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, + 0x7F10, 0x7F20, 0x7F20, 0x7ED0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F80, 0x7F10, + 0x7F10, 0x7EF0, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F70, 0x7F20, 0x7ED0, 0x7030, 0x6020, 0x4F40, 0x3F30, 0x2E30, + 0x1EA0, 0x0ED0, 0xFED0, 0xF080, 0xE220, 0xD980, 0xD610, 0xD820, 0xE2C0, 0xF350, 0x09B0, 0x22E0, 0x3D50, 0x5910, 0x6F70, 0x7E80, + 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7EA0, + 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F20, 0x7F00, 0x7F50, + 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7EB0, + 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x72B0, 0x6420, 0x56C0, 0x4BF0, 0x4190, 0x3700, 0x2DD0, 0x24C0, + 0x1C70, 0x1500, 0x0F10, 0x0B90, 0x0A10, 0x0B40, 0x1040, 0x18D0, 0x2610, 0x3560, 0x4690, 0x5660, 0x63C0, 0x6F80, 0x77D0, 0x7DF0, + 0x7EE0, 0x7EE0, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EE0, 0x7F00, 0x7EE0, 0x7F30, 0x7F10, 0x7E70, 0x7ED0, 0x7EB0, 0x7F30, 0x7EF0, + 0x7EB0, 0x7EE0, 0x7F20, 0x7F10, 0x7F10, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7E90, + 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7ED0, 0x7940, 0x71C0, 0x67F0, 0x5C20, 0x4EE0, 0x4090, 0x3230, 0x2270, 0x12E0, + 0x0250, 0xF2E0, 0xE470, 0xD5D0, 0xC6F0, 0xB700, 0xA660, 0x95F0, 0x8970, 0x8570, 0x84F0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8480, + 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, + 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83F0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, + 0x83B0, 0x83B0, 0x8390, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83B0, 0x83A0, 0x83A0, 0x8380, + 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, + 0x83A0, 0x83D0, 0x83E0, 0x83B0, 0x83C0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, + 0x83D0, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8480, 0x84A0, 0x84E0, 0x88F0, 0xBCD0, 0xE9A0, 0x1150, + 0x30A0, 0x48A0, 0x5980, 0x63F0, 0x6C20, 0x7140, 0x7610, 0x7930, 0x7B70, 0x7CC0, 0x7C30, 0x7B10, 0x78C0, 0x7590, 0x72F0, 0x70A0, + 0x7080, 0x7200, 0x7400, 0x7820, 0x7C00, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7F20, 0x7F50, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, + 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, + 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F30, 0x7F50, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F30, + 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F30, 0x7EF0, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, + 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F50, 0x7F10, 0x7EB0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F30, 0x7E70, 0x7ED0, 0x7EF0, + 0x7EF0, 0x7F00, 0x7E80, 0x7EC0, 0x7EB0, 0x7F10, 0x7EF0, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F20, 0x7F20, + 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7F10, 0x7F00, 0x7F00, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, + 0x7EF0, 0x7F60, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F40, 0x7ED0, 0x7E90, 0x7EF0, 0x7F00, 0x7F30, 0x7EB0, 0x7E70, 0x7F20, 0x7EF0, + 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F30, 0x7EC0, 0x7F40, 0x7F10, 0x7520, + 0x5EC0, 0x4840, 0x3310, 0x1F30, 0x0CB0, 0xF9F0, 0xE910, 0xD8C0, 0xC950, 0xB900, 0xA970, 0x9960, 0x8B80, 0x8630, 0x8500, 0x84D0, + 0x84B0, 0x84C0, 0x8480, 0x8480, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, 0x83F0, 0x8400, 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83C0, + 0x83B0, 0x83A0, 0x8390, 0x8390, 0x8380, 0x8380, 0x8370, 0x8370, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, + 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8380, 0x8370, 0x8380, 0x8380, 0x8380, + 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, + 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8470, 0x8480, 0x8490, 0x84C0, 0x84E0, 0x85B0, 0x8BA0, 0xA340, 0xBA50, 0xD210, 0xE9E0, 0x0220, 0x1A90, + 0x3250, 0x4C20, 0x6310, 0x7790, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F60, 0x7F20, 0x7E90, 0x7EB0, 0x7EB0, + 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F20, 0x7EC0, 0x7ED0, 0x7EF0, 0x7F00, 0x7EF0, 0x7EC0, 0x7F10, + 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, + 0x7F10, 0x7F10, 0x7F00, 0x7F30, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F80, 0x7EF0, 0x7EB0, + 0x7EF0, 0x7EF0, 0x7F50, 0x7EF0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7EF0, 0x7E90, 0x7F00, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7F60, 0x7F00, + 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, + 0x7EB0, 0x7EE0, 0x7F50, 0x7F00, 0x7E70, 0x7ED0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F00, 0x7F10, 0x7E90, 0x7EE0, + 0x7F00, 0x7ED0, 0x7F10, 0x7F00, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7F10, 0x7F10, 0x7F20, 0x7F70, 0x7ED0, 0x7F00, + 0x7F00, 0x7F10, 0x7F50, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EF0, 0x7EA0, 0x7EE0, + 0x7EF0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, + 0x7F00, 0x7ED0, 0x7F30, 0x7F00, 0x7E70, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x6DE0, 0x4EC0, 0x2E30, 0x0E30, 0xEAF0, 0xCAD0, + 0xABD0, 0x8ED0, 0x8590, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8420, 0x8400, 0x83F0, 0x83F0, + 0x8430, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, + 0x8410, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8470, 0x8490, 0x84A0, 0x84D0, 0x8520, 0x8730, + 0x98F0, 0xB1D0, 0xC970, 0xE120, 0x29D0, 0x38A0, 0x4830, 0x5310, 0x5C20, 0x6450, 0x6A90, 0x7030, 0x7460, 0x7820, 0x7A90, 0x7C90, + 0x7DE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F40, 0x7F30, 0x7F30, 0x7F30, + 0x7F40, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F20, 0x6410, + 0x3FF0, 0x1AD0, 0xF5C0, 0xD150, 0xAD90, 0x8D60, 0x8520, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, + 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83D0, + 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8420, 0x8400, 0x8400, 0x8410, 0x8420, + 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x8500, 0x8600, 0xA2A0, 0xCC70, 0xF550, 0x1DD0, 0x49D0, 0x6E70, 0x7F40, + 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F20, + 0x7F40, 0x7F20, 0x7F00, 0x7F00, 0x7ED0, 0x7F10, 0x7EE0, 0x7ED0, 0x7ED0, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F10, + 0x7F10, 0x7E70, 0x7EE0, 0x7EB0, 0x7EF0, 0x7F20, 0x7E90, 0x7EF0, 0x7F00, 0x7F20, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7F10, 0x7EF0, + 0x7EA0, 0x7EE0, 0x7F10, 0x7F20, 0x7F00, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, + 0x7F30, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, + 0x7F00, 0x7ED0, 0x7EF0, 0x7EF0, 0x7F20, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, + 0x7EC0, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, + 0x7F80, 0x7EF0, 0x7F10, 0x7EF0, 0x7B60, 0x73D0, 0x6D30, 0x65F0, 0x5FA0, 0x58F0, 0x53B0, 0x4FA0, 0x4D40, 0x4E10, 0x5030, 0x54A0, + 0x5AF0, 0x61B0, 0x68E0, 0x7000, 0x75D0, 0x7B90, 0x7E60, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F10, + 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7ED0, 0x7F10, + 0x7F60, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7C70, 0x71F0, + 0x6810, 0x5C90, 0x5100, 0x42C0, 0x3490, 0x2570, 0x1570, 0x0580, 0xF550, 0xE410, 0xD320, 0xC190, 0xAE30, 0x9BF0, 0x8C40, 0x8640, + 0x8510, 0x84D0, 0x84B0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8450, 0x8440, + 0x8440, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8470, 0x8460, 0x8450, 0x8450, 0x8470, 0x8440, 0x8440, + 0x8440, 0x8410, 0x8430, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8430, 0x8440, 0x8430, + 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8450, 0x8460, 0x8470, 0x8480, 0x84A0, 0x84C0, 0x8530, 0x89B0, 0xA7C0, + 0xC710, 0xE030, 0xF720, 0x0B40, 0x1C50, 0x2C60, 0x3A60, 0x4770, 0x5390, 0x5F50, 0x68A0, 0x7120, 0x7740, 0x7B90, 0x7DB0, 0x7EA0, + 0x7EE0, 0x7F50, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F80, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, + 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7EE0, 0x77D0, 0x6B50, 0x5C70, 0x4B40, 0x37D0, 0x2200, 0x0B30, 0xF200, 0xD590, 0xBA20, 0x9DB0, + 0x8900, 0x8510, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, + 0x8410, 0x8440, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x83F0, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x83D0, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, + 0x8450, 0x8450, 0x8460, 0x8470, 0x8490, 0x84C0, 0x8540, 0x8AF0, 0xA910, 0xC0D0, 0xD480, 0xE470, 0xF2A0, 0xFE10, 0x09C0, 0x11C0, + 0x16B0, 0x19B0, 0x18E0, 0x1660, 0x10C0, 0x09B0, 0x0140, 0xF850, 0xF090, 0xE900, 0xE140, 0xDA70, 0xD1A0, 0xC770, 0xBBA0, 0xAD50, + 0x9D50, 0x8EB0, 0x8710, 0x8530, 0x84E0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8410, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, + 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8510, 0x8510, 0x8500, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, + 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x8460, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84D0, 0x84F0, 0x8510, 0x8570, 0x8610, 0x8720, 0x87E0, 0x87C0, 0x86A0, + 0x8580, 0x84F0, 0x84C0, 0x8490, 0x8480, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, + 0x8410, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8440, 0x8430, 0x8430, 0x8440, 0x8450, 0x8470, 0x8490, + 0x84E0, 0x8680, 0x98E0, 0xAA00, 0xB670, 0xC210, 0xD0A0, 0xE450, 0xF900, 0x0C50, 0x1B90, 0x24C0, 0x2760, 0x2410, 0x1CC0, 0x1350, + 0x0880, 0xFF00, 0xF630, 0xD4E0, 0xCBB0, 0xC400, 0xBEC0, 0xBC80, 0xBDE0, 0xC340, 0xCAC0, 0xD530, 0xE0E0, 0xEE30, 0xFC10, 0x09E0, + 0x18C0, 0x26D0, 0x3640, 0x4570, 0x5510, 0x6480, 0x7340, 0x7E40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F30, 0x7F10, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7D20, 0x69E0, 0x5950, 0x4A80, 0x3F00, 0x3740, 0x3150, 0x2DE0, 0x2BD0, + 0x2AB0, 0x29F0, 0x2940, 0x2870, 0x26F0, 0x2430, 0x1FD0, 0x1920, 0x0E90, 0x0330, 0xF5A0, 0xE710, 0xD7D0, 0xC8D0, 0xBA00, 0xABF0, + 0x9E30, 0x9100, 0x88D0, 0x85C0, 0x8500, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, + 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8440, 0x8460, 0x8470, + 0x8480, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x84F0, 0x8560, 0x8690, 0x8A40, 0x9160, 0x97A0, 0x9CC0, 0xA160, 0xA5A0, 0xAAA0, + 0xB1A0, 0xB8E0, 0xBFF0, 0xC730, 0xCE00, 0xD3C0, 0xD900, 0xDD90, 0xE120, 0xE540, 0xE830, 0xEAC0, 0xED20, 0xEDD0, 0xEE30, 0xEDB0, + 0xED20, 0xEC90, 0xEC00, 0xEC80, 0xECD0, 0xEFB0, 0xF300, 0xF6A0, 0xFB50, 0x0030, 0x05E0, 0x0BF0, 0x1130, 0x1760, 0x1D20, 0x22B0, + 0x27F0, 0x2C80, 0x3140, 0x3390, 0x3520, 0x3540, 0x3350, 0x3110, 0x2D30, 0x2940, 0x23B0, 0x1F60, 0x1B20, 0x1640, 0x1310, 0x1100, + 0x0F80, 0x10D0, 0x1370, 0x18A0, 0x1F60, 0x27D0, 0x32A0, 0x3C20, 0x44F0, 0x4C10, 0x5160, 0x5500, 0x5650, 0x55B0, 0x5400, 0x5010, + 0x4C10, 0x48A0, 0x4660, 0x47C0, 0x4BA0, 0x5380, 0x5CC0, 0x6550, 0x6CA0, 0x7040, 0x7290, 0x7510, 0x7A60, 0x7F00, 0x7ED0, 0x7F30, + 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F80, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F80, 0x7F20, + 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7EF0, 0x7EF0, 0x7EE0, 0x7ED0, 0x7F50, 0x7F10, 0x7EA0, 0x7ED0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, + 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7EA0, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F00, + 0x7F20, 0x7F00, 0x7F10, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, 0x5FB0, + 0x3A00, 0x10C0, 0xE0F0, 0xB2F0, 0x8950, 0x84C0, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8460, 0x8460, + 0x8460, 0x8470, 0x84A0, 0x8490, 0x84B0, 0x84D0, 0x84E0, 0x84E0, 0x84D0, 0x84D0, 0x84B0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8490, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8490, 0x8460, 0x8470, 0x8480, 0x8440, 0x84C0, 0x8510, 0x8720, 0x9A00, + 0xAE70, 0xBFB0, 0xCCD0, 0xD5C0, 0xDAD0, 0xDC70, 0xDAE0, 0xD620, 0xCF40, 0xC860, 0xC130, 0xBAB0, 0xB580, 0xB200, 0xB080, 0xB080, + 0xB310, 0xB6B0, 0xBC10, 0xC170, 0xC8B0, 0xD080, 0xD8A0, 0xE1A0, 0xEB40, 0xF550, 0x01B0, 0x0D00, 0x18F0, 0x2470, 0x2FE0, 0x3C70, + 0x4850, 0x5580, 0x6280, 0x7150, 0x7D90, 0x7EA0, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F40, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, + 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F50, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F90, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F60, + 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, + 0x7E90, 0x7EA0, 0x7EE0, 0x7F10, 0x7F20, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7E90, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, + 0x7F60, 0x7F20, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, + 0x7ED0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F70, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, 0x7E90, 0x7F10, 0x7F00, 0x7F30, 0x7EB0, + 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, 0x7EC0, + 0x7F40, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F90, 0x7F00, 0x7F20, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F70, + 0x7F10, 0x7F20, 0x7F10, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F30, 0x7F10, 0x7EB0, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, + 0x7E70, 0x7EC0, 0x7ED0, 0x7F00, 0x7F00, 0x7B90, 0x7230, 0x6720, 0x5AA0, 0x4D80, 0x3F10, 0x30A0, 0x1FD0, 0x1070, 0x0170, 0xF2C0, + 0xE3D0, 0xD520, 0xC640, 0xB7C0, 0xA8D0, 0x99D0, 0x8DE0, 0x87B0, 0x85D0, 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84D0, 0x84C0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84F0, 0x84F0, 0x8520, 0x8590, 0x8700, 0x8BF0, + 0x9750, 0xA330, 0xAF20, 0xBC00, 0xC800, 0xD490, 0xE140, 0xEF50, 0xFCF0, 0x09F0, 0x1760, 0x24E0, 0x3290, 0x40A0, 0x4E60, 0x5C40, + 0x6A30, 0x75E0, 0x7E40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F50, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F70, 0x7F10, 0x7EF0, + 0x7F20, 0x7F40, 0x7F50, 0x7F30, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7E60, 0x7EB0, 0x7F20, 0x7F20, 0x7EF0, 0x7E90, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F10, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7EC0, 0x7F30, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F20, 0x7EF0, + 0x7F10, 0x7F20, 0x7F20, 0x7F80, 0x7950, 0x6FC0, 0x6790, 0x5F70, 0x5790, 0x50A0, 0x4950, 0x4310, 0x3D10, 0x37C0, 0x32F0, 0x2E60, + 0x2BA0, 0x2840, 0x2510, 0x2270, 0x1FA0, 0x1CF0, 0x1A10, 0x1720, 0x1450, 0x10F0, 0x0E30, 0x0BA0, 0x08D0, 0x06B0, 0x03E0, 0x0100, + 0xFDB0, 0xFA10, 0xF770, 0xF450, 0xF120, 0xEE20, 0xEB70, 0xE910, 0xE680, 0xE3D0, 0xE110, 0xDE70, 0xDCA0, 0xDA60, 0xD8C0, 0xD6D0, + 0xD450, 0xD2C0, 0xD030, 0xCE20, 0xCCC0, 0xCB10, 0xCB50, 0xCB40, 0xCBE0, 0xCC70, 0xCD70, 0xCF00, 0xD000, 0xD110, 0xD220, 0xD2A0, + 0xD390, 0xD510, 0xD6B0, 0xD8F0, 0xDB10, 0xDDF0, 0xE0E0, 0xE2F0, 0xE5F0, 0xE840, 0xEB20, 0xED90, 0xF0B0, 0xF400, 0xF6F0, 0xFB00, + 0xFE20, 0x01C0, 0x0520, 0x0870, 0x0BA0, 0x0F00, 0x12B0, 0x16A0, 0x1A40, 0x1E10, 0x2280, 0x2600, 0x2AA0, 0x2E80, 0x32B0, 0x3740, + 0x3A80, 0x3EE0, 0x41E0, 0x4500, 0x4790, 0x4A50, 0x4DB0, 0x5070, 0x5330, 0x5620, 0x5870, 0x5BD0, 0x5EB0, 0x6120, 0x63C0, 0x6650, + 0x6990, 0x6C80, 0x6EF0, 0x7170, 0x7300, 0x74F0, 0x7600, 0x76F0, 0x7770, 0x77D0, 0x7850, 0x7900, 0x7940, 0x7910, 0x77F0, 0x77E0, + 0x7760, 0x7650, 0x76B0, 0x75F0, 0x7690, 0x7730, 0x7760, 0x78E0, 0x7980, 0x7AB0, 0x7C00, 0x7CC0, 0x7DB0, 0x7E20, 0x7EC0, 0x7F10, + 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F40, 0x7F10, 0x7F00, 0x7F30, 0x7EF0, 0x7F40, 0x7F10, 0x7F00, 0x7F00, 0x7D30, 0x7A60, + 0x7740, 0x72D0, 0x6DF0, 0x6860, 0x61E0, 0x5A50, 0x5160, 0x45E0, 0x0B40, 0xFB40, 0xE9D0, 0xD6C0, 0xC340, 0xAD50, 0x95A0, 0x8720, + 0x84F0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, 0x8410, 0x8430, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83D0, + 0x83D0, 0x83E0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83D0, 0x8390, 0x8390, 0x8390, 0x83B0, 0x8390, 0x8390, 0x8390, + 0x83C0, 0x8380, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83C0, 0x83A0, 0x83B0, 0x83A0, 0x83A0, 0x83B0, + 0x83A0, 0x8340, 0x83B0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8420, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8460, 0x84B0, 0x8480, 0x84A0, 0x84C0, 0x84E0, 0x8560, 0x8760, 0x90B0, 0x9E90, 0xAAA0, 0xB490, 0xBC90, + 0xC310, 0xC7D0, 0xCC10, 0xCE70, 0xD090, 0xD260, 0xD410, 0xD630, 0xD800, 0xD9E0, 0xDB80, 0xDC30, 0xDC60, 0xDB90, 0xDA10, 0xD750, + 0xD400, 0xD060, 0xCC30, 0xC730, 0xC1A0, 0xBB90, 0xB650, 0xB070, 0xAA90, 0xA500, 0x9F30, 0x98F0, 0x9170, 0x8A40, 0x86A0, 0x8550, + 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8490, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84F0, 0x8500, 0x8510, 0x8520, + 0x8530, 0x8520, 0x8510, 0x8500, 0x84E0, 0x84C0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, + 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8410, + 0x8410, 0x8420, 0x8430, 0x8440, 0x8450, 0x8450, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x8550, 0x8780, 0x9380, 0xA410, 0xB1F0, + 0xBF60, 0xCAD0, 0xD590, 0xDF20, 0xE6C0, 0xED30, 0xF1D0, 0xF430, 0xF6A0, 0xF790, 0xF8A0, 0xF920, 0xFA10, 0xFB30, 0xFC30, 0xFDA0, + 0xFFF0, 0x0200, 0x0490, 0x06F0, 0x0930, 0x0AE0, 0x0CC0, 0x0F10, 0x1190, 0x1460, 0x1730, 0x1A30, 0x1D40, 0x2040, 0x22B0, 0x23F0, + 0x2510, 0x2530, 0x24B0, 0x2490, 0x2500, 0x2620, 0x26C0, 0x2730, 0x2800, 0x2790, 0x26F0, 0x2570, 0x2380, 0x2160, 0x1D80, 0x1870, + 0x11E0, 0x08D0, 0xFE30, 0xF130, 0xE210, 0xD3A0, 0xC500, 0xB7A0, 0xABF0, 0xA270, 0x9A60, 0x94A0, 0x8FB0, 0x8BC0, 0x8900, 0x8700, + 0x85C0, 0x8540, 0x8500, 0x84D0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8480, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, + 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x8370, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, + 0x8340, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83B0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83B0, + 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x8430, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8440, 0x8450, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84F0, 0x8530, 0x8640, 0x8A10, 0x9580, 0xA250, 0xAF70, + 0xBD60, 0xCBD0, 0xDDB0, 0xF040, 0x04C0, 0x1AF0, 0x32B0, 0x4B00, 0x62A0, 0x76F0, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7FA0, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EB0, 0x7EF0, 0x7F40, 0x7EB0, 0x7EE0, 0x7EC0, + 0x7ED0, 0x7F30, 0x7F40, 0x7EF0, 0x7ED0, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F30, 0x7EA0, 0x7EF0, 0x7EE0, + 0x7F30, 0x7F50, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, + 0x7F10, 0x7E90, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F40, 0x7EC0, 0x7F40, 0x7EF0, 0x7F20, 0x7F40, + 0x7F10, 0x7F80, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F80, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F00, 0x7F00, 0x7F00, 0x7F00, + 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F30, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E90, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F00, 0x7EC0, 0x7EB0, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7F10, 0x7F20, 0x7F20, + 0x7EE0, 0x6B50, 0x5520, 0x3A80, 0x1E30, 0xFF90, 0xE070, 0xC160, 0xA390, 0x8BB0, 0x8550, 0x84E0, 0x84C0, 0x84B0, 0x84C0, 0x84B0, + 0x84E0, 0x8570, 0x90C0, 0xC3B0, 0xFAC0, 0x39F0, 0x7810, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7ED0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, + 0x7EE0, 0x7E90, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F40, 0x7F10, 0x7EE0, 0x7F10, + 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7F00, 0x7EF0, 0x7ED0, + 0x7F60, 0x7F10, 0x7ED0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F30, 0x7F00, 0x7E90, 0x7EB0, 0x7EE0, 0x7EE0, + 0x7EF0, 0x7E90, 0x7EC0, 0x7ED0, 0x7F10, 0x7F10, 0x7EC0, 0x7F00, 0x7F10, 0x7F00, 0x7ED0, 0x7F00, 0x7F00, 0x7E90, 0x7ED0, 0x7F00, + 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F50, 0x7F10, 0x7F00, 0x7EE0, 0x7EF0, 0x7F60, 0x7F00, 0x7F20, + 0x7F10, 0x7EF0, 0x7F50, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F60, 0x7EE0, 0x7EB0, 0x7EF0, + 0x7EE0, 0x7F20, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F00, 0x7E90, 0x7EF0, 0x7EE0, + 0x7ED0, 0x7F10, 0x7F00, 0x7F40, 0x7ED0, 0x7F10, 0x7F40, 0x7F00, 0x7F30, 0x7EE0, 0x7F00, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F20, + 0x7F20, 0x7F00, 0x7F90, 0x7EF0, 0x7EF0, 0x7EE0, 0x7ED0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, + 0x7EC0, 0x7F30, 0x7F00, 0x7E70, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, 0x7E90, 0x7E90, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7F30, 0x7F20, + 0x7F00, 0x7F10, 0x7F50, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x78D0, 0x6A50, 0x5860, 0x4580, + 0x30D0, 0x1AF0, 0x0440, 0xEAF0, 0xD0D0, 0xB560, 0x9960, 0x8710, 0x84F0, 0x84D0, 0x84C0, 0x8480, 0x8470, 0x8470, 0x8450, 0x8450, + 0x8440, 0x8460, 0x8430, 0x8420, 0x83C0, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x8430, 0x83F0, 0x83F0, 0x83F0, 0x83E0, + 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83F0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, + 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, + 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, + 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, + 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8460, 0x8420, 0x8430, 0x8420, + 0x8440, 0x8440, 0x8450, 0x84A0, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84E0, 0x8550, 0x87F0, 0x9910, 0xAED0, 0xC520, + 0xDB80, 0xF570, 0x0DE0, 0x2700, 0x4080, 0x5A30, 0x70D0, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F50, 0x7F20, 0x7F40, 0x7A10, 0x5F20, 0x4070, 0x2210, + 0x02B0, 0xE220, 0xC0F0, 0x9E90, 0x8740, 0x84E0, 0x84D0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, + 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, + 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83F0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, + 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8430, 0x8400, + 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x84A0, 0x8550, 0x85F0, 0xA040, 0xC580, 0xE180, 0xF450, + 0xFDB0, 0x0030, 0xFEB0, 0xFDB0, 0xFF40, 0x04D0, 0x0EF0, 0x1CB0, 0x2C40, 0x3D00, 0x4B40, 0x55C0, 0x5C90, 0x6050, 0x6430, 0x6920, + 0x6F50, 0x7790, 0x7EA0, 0x7EF0, 0x7F10, 0x7F80, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F70, + 0x7F10, 0x7EE0, 0x7F10, 0x7ED0, 0x7F30, 0x7F00, 0x7ED0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F00, 0x7F00, 0x7F10, 0x7F20, + 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7160, 0x5290, 0x3970, 0x2790, 0x1D20, + 0x1B50, 0x23A0, 0x3460, 0x4D50, 0x6AF0, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, + 0x7F00, 0x7EC0, 0x7EF0, 0x7F00, 0x7F60, 0x7EF0, 0x7EB0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7ED0, 0x7E70, 0x7EF0, 0x7EF0, 0x7F30, 0x7EE0, + 0x7EC0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7EF0, 0x7F00, 0x7F20, 0x7F00, + 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F00, 0x7F00, 0x7F00, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, + 0x7F00, 0x7EE0, 0x7EF0, 0x7F00, 0x7F60, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F50, 0x7F00, + 0x7F00, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, 0x7ED0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, + 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F00, 0x7F30, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F70, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F90, 0x7F00, 0x7F20, 0x7F10, 0x7F20, 0x7F40, 0x7F10, + 0x7F70, 0x7EF0, 0x7F00, 0x7F30, 0x7F00, 0x7F80, 0x7F10, 0x7F10, 0x7EE0, 0x7EE0, 0x7F70, 0x7F10, 0x7EE0, 0x7ED0, 0x7EF0, 0x7F60, + 0x7F20, 0x7EC0, 0x7EB0, 0x7EB0, 0x7EF0, 0x7F10, 0x7E70, 0x7EC0, 0x7ED0, 0x7F10, 0x7B00, 0x5E80, 0x43D0, 0x2AB0, 0x1240, 0x00C0, + 0xF200, 0xE570, 0xDAE0, 0xD280, 0xCD90, 0xCB60, 0xCDA0, 0xD2E0, 0xDAC0, 0xE440, 0xEDE0, 0xF5D0, 0xFB20, 0xFC20, 0xFAF0, 0xF6C0, + 0xF240, 0xEE80, 0xECE0, 0xEDC0, 0xF0C0, 0xF610, 0xFD50, 0x0410, 0x0A40, 0x0E70, 0x0E30, 0x0A60, 0x0210, 0xF710, 0xE960, 0xDAA0, + 0xCB50, 0xBB80, 0xAA60, 0x9A70, 0x8BC0, 0x8610, 0x8500, 0x84D0, 0x84B0, 0x8490, 0x8490, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8450, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8460, 0x8430, 0x8430, 0x8430, 0x83C0, 0x8430, 0x8430, 0x8460, + 0x8430, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8470, 0x8490, 0x84A0, 0x84D0, 0x8550, 0x8A40, 0xA760, + 0xC390, 0xE090, 0xFB20, 0x1420, 0x2CE0, 0x4490, 0x5BB0, 0x7120, 0x7EC0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, + 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7ED0, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F80, + 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7EB0, 0x7EF0, 0x7F20, 0x7EF0, 0x7ED0, 0x7EA0, 0x7F00, 0x7F00, 0x7F30, 0x7F00, + 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F30, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, + 0x7F30, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7F00, 0x7F90, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, + 0x7F20, 0x7EC0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7E70, 0x7ED0, 0x7ED0, 0x7F00, 0x7F00, + 0x7E90, 0x7E90, 0x7F00, 0x7F20, 0x7F10, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F00, + 0x7F30, 0x7F20, 0x7EF0, 0x7EF0, 0x7F10, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F40, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7ED0, 0x7EB0, 0x7EE0, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, + 0x7E90, 0x7F00, 0x7F00, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7EF0, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F00, + 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7AA0, 0x6270, 0x4B00, 0x3240, + 0x1850, 0xFDB0, 0xE1C0, 0xC600, 0xAA40, 0x90E0, 0x8620, 0x8500, 0x84D0, 0x84D0, 0x84D0, 0x84F0, 0x8530, 0x8650, 0x8B80, 0x9590, + 0x9700, 0x8F00, 0x86C0, 0x84F0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8450, 0x8430, 0x8420, 0x8420, 0x8410, + 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8480, 0x8490, 0x84B0, 0x84F0, 0x86B0, 0xA680, 0xD0B0, 0xFB60, + 0x2500, 0x4C40, 0x6D50, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7E20, 0x6F90, 0x6090, 0x50A0, 0x3F60, 0x2CB0, 0x1850, + 0x02D0, 0xEB40, 0xCFE0, 0xB430, 0x96A0, 0x8620, 0x84B0, 0x84A0, 0x8480, 0x8460, 0x8460, 0x8440, 0x8460, 0x8430, 0x8420, 0x8410, + 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83C0, + 0x83C0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, + 0x83E0, 0x83F0, 0x83E0, 0x83F0, 0x8400, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8410, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, + 0x8480, 0x8490, 0x84C0, 0x8500, 0x8650, 0x9710, 0xB330, 0xCCD0, 0xE540, 0xFB60, 0x0F40, 0x20B0, 0x30C0, 0x3DF0, 0x48B0, 0x52E0, + 0x5B40, 0x6250, 0x6A10, 0x7030, 0x7740, 0x7D30, 0x7F00, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F00, 0x7EE0, 0x7F10, + 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, + 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, 0x7E90, 0x7F00, + 0x7EE0, 0x7EF0, 0x7EE0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F20, 0x7EF0, + 0x7F10, 0x7F20, 0x7F20, 0x7F50, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7EE0, 0x7F10, 0x7EF0, 0x7F10, 0x7F70, 0x7F10, 0x7F20, + 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F60, 0x7F10, 0x7ED0, 0x7EF0, 0x7F00, 0x7F50, 0x7F10, 0x7E90, 0x7EE0, + 0x7ED0, 0x7F30, 0x7F00, 0x7E80, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7EC0, + 0x7F10, 0x7F00, 0x7EF0, 0x7D50, 0x7500, 0x6DC0, 0x6750, 0x6190, 0x5D40, 0x5980, 0x5680, 0x54A0, 0x5470, 0x55E0, 0x5900, 0x5F40, + 0x6750, 0x7170, 0x7C60, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x6710, 0x4210, 0x1820, 0xEC80, 0xC310, 0x9CE0, 0x86D0, 0x84E0, + 0x8490, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x84B0, 0x84B0, 0x8480, 0x8490, 0x84C0, 0x8490, 0x84D0, 0x84B0, 0x84C0, 0x84B0, + 0x84C0, 0x8490, 0x84E0, 0x8510, 0x85A0, 0x8830, 0x94F0, 0xA720, 0xB640, 0xC250, 0xCBD0, 0xD1F0, 0xD500, 0xD560, 0xD470, 0xD270, + 0xD0F0, 0xD010, 0xD090, 0xD1F0, 0xD350, 0xD4D0, 0xD630, 0xD6F0, 0xD6C0, 0xD580, 0xD440, 0xD2C0, 0xD170, 0xD210, 0xD360, 0xD7A0, + 0xDD10, 0xE4B0, 0xEEE0, 0xF9C0, 0x0600, 0x12E0, 0x1FE0, 0x2D10, 0x3900, 0x43A0, 0x4D40, 0x55B0, 0x5D60, 0x6300, 0x6790, 0x6B60, + 0x6DA0, 0x6EE0, 0x6E50, 0x6C30, 0x6960, 0x6550, 0x61F0, 0x5D00, 0x5760, 0x5180, 0x4A50, 0x4330, 0x3B40, 0x30B0, 0x2600, 0x1AC0, + 0x0E50, 0x0010, 0xF090, 0xE0A0, 0xCEF0, 0xBD50, 0xA980, 0x9650, 0x88D0, 0x8540, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, + 0x8450, 0x8410, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8420, 0x8400, 0x8400, + 0x8400, 0x8420, 0x8420, 0x8440, 0x8480, 0x8460, 0x8470, 0x8490, 0x84B0, 0x84E0, 0x8550, 0x8820, 0x9A70, 0xAF30, 0xC340, 0xD580, + 0xE770, 0xF560, 0x00F0, 0x09D0, 0x1090, 0x15A0, 0x1770, 0x16F0, 0x14E0, 0x0E70, 0x05B0, 0xF9C0, 0xEA40, 0xD840, 0xC370, 0xADF0, + 0x9740, 0x8840, 0x8520, 0x84D0, 0x84B0, 0x84A0, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8480, + 0x8450, 0x8450, 0x8400, 0x8450, 0x8450, 0x8470, 0x8440, 0x8440, 0x8450, 0x8450, 0x8440, 0x8450, 0x8460, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8460, 0x8460, 0x84A0, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x84F0, + 0x8510, 0x8530, 0x8570, 0x85B0, 0x8600, 0x8670, 0x8760, 0x8A00, 0x90F0, 0x9C80, 0xAA40, 0xB8E0, 0xC760, 0xD4F0, 0xE160, 0xEB80, + 0xF4B0, 0xFBA0, 0x0180, 0x05E0, 0x0960, 0x0B40, 0x0BA0, 0x0A20, 0x07C0, 0x0470, 0x0060, 0xFC00, 0xF780, 0xF290, 0xEE60, 0xEAB0, + 0xE6D0, 0xE360, 0xDFD0, 0xDC70, 0xD8F0, 0xD530, 0xD150, 0xCD40, 0xC890, 0xC360, 0xBE40, 0xB890, 0xB270, 0xAC80, 0xA620, 0x9FE0, + 0x9880, 0x90A0, 0x89B0, 0x8650, 0x8530, 0x84E0, 0x84F0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, 0x8420, + 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x83F0, 0x8400, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x84A0, 0x84D0, 0x8500, 0x8610, 0x8E90, 0xA4A0, 0xB8B0, 0xCC80, 0xDE90, + 0xF050, 0x00E0, 0x1060, 0x2030, 0x2E70, 0x3B20, 0x46A0, 0x5110, 0x5A60, 0x6220, 0x6900, 0x6F30, 0x7520, 0x79E0, 0x7D50, 0x7EF0, + 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F90, 0x7F20, 0x7EE0, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7ED0, 0x7F20, 0x7F00, 0x7F10, 0x7E10, 0x7CC0, 0x7B80, 0x7A50, 0x78F0, 0x7760, 0x7490, 0x71D0, 0x6D90, 0x6800, + 0x6150, 0x5930, 0x5100, 0x47C0, 0x3D30, 0x32D0, 0x2700, 0x1B10, 0x0E90, 0x00A0, 0xF3D0, 0xE5D0, 0xD7F0, 0xC940, 0xB9E0, 0xAA80, + 0x9BA0, 0x8E10, 0x8710, 0x8550, 0x84F0, 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, + 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8430, 0x8400, 0x8400, + 0x8410, 0x8400, 0x8410, 0x8410, 0x8430, 0x8410, 0x8410, 0x8420, 0x8440, 0x8420, 0x8420, 0x8450, 0x8450, 0x8430, 0x8440, 0x8470, + 0x8450, 0x8450, 0x8470, 0x84A0, 0x8480, 0x8490, 0x84C0, 0x8500, 0x86D0, 0x9C90, 0xBBD0, 0xD790, 0xF290, 0x0B70, 0x2210, 0x36B0, + 0x49F0, 0x5A20, 0x68D0, 0x7600, 0x7E30, 0x7F10, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, + 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F90, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, + 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7F10, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, + 0x7F00, 0x7F30, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F30, 0x7F10, + 0x7F70, 0x7EE0, 0x7EF0, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7EF0, 0x7EE0, + 0x7ED0, 0x7F70, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F60, 0x7F10, 0x6C30, 0x55C0, 0x3CE0, 0x2070, 0x06B0, 0xECA0, 0xD1F0, 0xB5E0, + 0x97B0, 0x86A0, 0x84D0, 0x84A0, 0x8480, 0x8470, 0x8450, 0x8440, 0x8440, 0x8430, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, + 0x83E0, 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, + 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x8500, 0x85D0, 0x91F0, + 0xB130, 0xD040, 0xF090, 0x1280, 0x3860, 0x5CF0, 0x7B90, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7F10, 0x7F10, 0x7F00, + 0x7EE0, 0x7F50, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, + 0x7F70, 0x7F00, 0x7EC0, 0x7F00, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, + 0x7EA0, 0x6980, 0x5A10, 0x4D90, 0x4400, 0x3F60, 0x3D80, 0x3FD0, 0x45E0, 0x4EC0, 0x5D00, 0x6C00, 0x7C00, 0x7F10, 0x7F10, 0x7F20, + 0x7EF0, 0x7F90, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F00, 0x7EE0, 0x7EE0, 0x7ED0, + 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F50, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F00, 0x7F20, + 0x7F20, 0x7EC0, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, + 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F10, 0x7F50, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F60, 0x7F00, 0x7ED0, 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7F20, + 0x7F10, 0x7EB0, 0x7F10, 0x7EE0, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F80, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F80, 0x7F00, 0x7F20, 0x7F00, 0x7EF0, 0x7F30, 0x7EF0, 0x7EC0, 0x7ED0, 0x7EE0, + 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7ED0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F20, + 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, + 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F00, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F50, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, + 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x72D0, 0x4900, 0x1BA0, 0xEB90, 0xBA70, 0x8D10, 0x84E0, 0x84A0, 0x8480, 0x8470, 0x8460, + 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x83B0, 0x8410, 0x8410, 0x8410, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8420, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x8400, 0x83E0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8410, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x8390, 0x8390, 0x8380, 0x8370, 0x8370, 0x8360, 0x8350, 0x8370, 0x8350, 0x8350, + 0x8350, 0x8380, 0x8350, 0x8360, 0x8310, 0x8370, 0x8370, 0x8370, 0x8380, 0x8380, 0x8380, 0x83C0, 0x8390, 0x8390, 0x8390, 0x8390, + 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83F0, 0x8400, 0x8410, 0x8430, + 0x8450, 0x8470, 0x84B0, 0x86E0, 0xBE00, 0xF710, 0x2C80, 0x5C80, 0x7E60, 0x7EE0, 0x7E90, 0x7F10, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, + 0x7EF0, 0x7EF0, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7EF0, 0x7F30, 0x7EC0, 0x7F40, + 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EF0, 0x7F00, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F80, 0x7F10, + 0x7F00, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F10, 0x7E70, + 0x7ED0, 0x7F10, 0x7F00, 0x7EF0, 0x7E90, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7EC0, 0x7F40, + 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F40, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, 0x7F50, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EC0, 0x7EF0, 0x7EE0, 0x7F50, 0x7EF0, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7EB0, 0x7EC0, + 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7EB0, 0x7F20, 0x6890, 0x5130, 0x3720, 0x1AD0, 0xFF50, 0xE350, 0xC900, 0xB080, 0x9A90, 0x8B20, + 0x8610, 0x8520, 0x84E0, 0x84C0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8480, 0x8450, 0x8440, 0x8420, 0x8430, 0x8420, 0x8410, + 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83D0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8410, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83E0, 0x8400, 0x8400, 0x8400, 0x83F0, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8440, 0x8450, 0x8440, 0x8440, 0x8490, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8460, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, + 0x8490, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8E20, 0xBB50, 0xE9E0, + 0x17E0, 0x4640, 0x6E50, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7EF0, 0x7F00, 0x7EC0, + 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7F80, 0x7F00, 0x7F20, 0x7F10, 0x7EF0, 0x7F70, + 0x7F20, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7ED0, 0x7ED0, 0x7EB0, 0x7EF0, 0x7EF0, + 0x7E90, 0x7ED0, 0x7F00, 0x7F10, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, + 0x7F20, 0x7850, 0x6A10, 0x5F30, 0x55E0, 0x4F10, 0x4A30, 0x4800, 0x49C0, 0x4D70, 0x53E0, 0x5D60, 0x68E0, 0x7690, 0x7EF0, 0x7F70, + 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, 0x7EE0, 0x7F00, 0x7F10, 0x7F70, 0x7EF0, 0x7ED0, 0x7EF0, 0x7EF0, 0x7F30, 0x7ED0, + 0x7EB0, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7E90, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, + 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7F00, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, + 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, + 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F10, 0x7F30, 0x7F10, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7EE0, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F70, 0x7F20, 0x7EF0, + 0x7F30, 0x7F30, 0x7F30, 0x7EF0, 0x7E90, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7E80, 0x7D80, 0x4F00, 0x2090, 0xF470, 0xCC20, 0xAB70, + 0x9120, 0x8730, 0x8550, 0x84F0, 0x84D0, 0x8470, 0x84A0, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8410, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8420, 0x8430, 0x8420, 0x8420, 0x8420, 0x8440, 0x8420, 0x8410, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8420, 0x8410, 0x8410, 0x8410, 0x83E0, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8410, 0x8430, + 0x8410, 0x8410, 0x83C0, 0x8410, 0x8410, 0x8410, 0x83F0, 0x8420, 0x8420, 0x8420, 0x8450, 0x8420, 0x8420, 0x8410, 0x8430, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8450, 0x8440, 0x8430, 0x8430, 0x8460, + 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8490, 0x8480, 0x8470, 0x8480, 0x84A0, 0x8490, 0x8490, 0x8490, 0x84D0, 0x84A0, + 0x84B0, 0x84C0, 0x84C0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84B0, 0x84A0, 0x8480, 0x8470, 0x8470, 0x8470, + 0x8450, 0x8440, 0x8430, 0x8440, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8410, 0x83F0, 0x83E0, 0x83E0, 0x8400, 0x83E0, + 0x83E0, 0x83E0, 0x83F0, 0x83D0, 0x83D0, 0x8370, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x8380, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83B0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, + 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x8360, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x8410, 0x8400, 0x8400, 0x83B0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8390, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, + 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83C0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, + 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x84E0, 0x8520, 0x85A0, 0x8730, 0x8D90, 0x9B30, 0xA9A0, 0xB860, 0xC790, 0xD820, 0xE800, + 0xF880, 0x0A10, 0x1D60, 0x33C0, 0x4D00, 0x6850, 0x7E60, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, + 0x7F00, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, 0x7F00, + 0x7EA0, 0x7ED0, 0x7EE0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EE0, 0x7F10, 0x7F10, 0x7E90, 0x7ED0, 0x7ED0, 0x7F00, 0x7EE0, 0x7E90, + 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F40, 0x7F30, 0x7F20, 0x7EF0, 0x7F00, 0x7F40, + 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F50, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, + 0x7EF0, 0x7830, 0x5070, 0x2950, 0x01D0, 0xDAE0, 0xB4C0, 0x8FE0, 0x8510, 0x84D0, 0x8490, 0x8470, 0x8460, 0x8480, 0x8450, 0x8450, + 0x8440, 0x8470, 0x8440, 0x8450, 0x8420, 0x8450, 0x8450, 0x8450, 0x8420, 0x8450, 0x8450, 0x8460, 0x8450, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8430, 0x8430, 0x8440, 0x8440, 0x8480, 0x8460, 0x8480, 0x84B0, 0x8530, 0x91F0, 0xB790, 0xD450, 0xE980, 0xFC20, 0x0F10, + 0x23F0, 0x3D30, 0x5720, 0x6FE0, 0x7ED0, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F00, + 0x7EE0, 0x7EF0, 0x7F80, 0x7F00, 0x7EC0, 0x7F00, 0x7F10, 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, + 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F20, 0x7F10, + 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, + 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F40, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, 0x7F20, 0x7EF0, 0x7ED0, 0x7F00, 0x7EC0, 0x7EC0, 0x7EE0, 0x7F20, 0x7EC0, + 0x7F10, 0x7F30, 0x7EC0, 0x7EF0, 0x7F10, 0x7EE0, 0x7F40, 0x7ED0, 0x7F00, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7EE0, 0x7F10, 0x7EF0, + 0x7F30, 0x7EE0, 0x7E90, 0x7F30, 0x7F00, 0x7F20, 0x7EE0, 0x7EA0, 0x7F00, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7EF0, + 0x7EF0, 0x7EB0, 0x7F30, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F80, 0x7F00, 0x7F40, 0x7EF0, + 0x7EF0, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7EF0, 0x7F00, 0x7EF0, 0x7F60, 0x7F20, 0x7ED0, 0x7ED0, 0x7EB0, + 0x7EF0, 0x7EF0, 0x7E90, 0x7EE0, 0x7EC0, 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, + 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7960, 0x6450, 0x4DE0, + 0x3320, 0x15F0, 0xF6D0, 0xD580, 0xB410, 0x9110, 0x8530, 0x84B0, 0x8480, 0x8460, 0x8460, 0x8450, 0x8440, 0x8410, 0x8420, 0x8420, + 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83C0, 0x83C0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, + 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x83C0, 0x8390, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, + 0x83B0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, + 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8420, 0x8400, 0x8400, 0x8410, + 0x8400, 0x8400, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8440, 0x8420, 0x8420, 0x8420, 0x8470, 0x8420, 0x8420, 0x8410, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8440, 0x8410, 0x8410, 0x8440, 0x8410, 0x8430, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x84C0, 0x8540, 0x9210, 0xBC50, 0xE680, 0x0B60, 0x2F80, 0x51B0, + 0x7030, 0x7E70, 0x7EC0, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7F60, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F80, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7F00, 0x7F00, + 0x7F00, 0x7F60, 0x7F00, 0x7ED0, 0x7EB0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F20, 0x7EA0, 0x7ED0, 0x7EF0, + 0x7F00, 0x7EE0, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7F00, + 0x7EF0, 0x7F10, 0x7F60, 0x7F40, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F80, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F10, 0x7F70, 0x7EF0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, + 0x7F40, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, 0x7EF0, 0x7F00, + 0x7F40, 0x7F00, 0x7F40, 0x7EF0, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F70, 0x7EF0, 0x7EF0, 0x7F10, + 0x7F00, 0x7F20, 0x7F10, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, + 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F50, 0x7F40, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7890, 0x6BB0, 0x5DE0, 0x4F80, 0x3FF0, 0x2FD0, 0x1F70, 0x0DE0, + 0xFB10, 0xE5F0, 0xD170, 0xBCD0, 0xA760, 0x9290, 0x8740, 0x8510, 0x84D0, 0x84D0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, + 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83E0, 0x83F0, 0x83E0, 0x83D0, 0x8380, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83E0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, + 0x83C0, 0x83C0, 0x8400, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, + 0x84C0, 0x84E0, 0x8540, 0x86E0, 0x9320, 0xA5E0, 0xB910, 0xCC50, 0xDF50, 0xF2E0, 0x0680, 0x19F0, 0x2DB0, 0x4340, 0x5710, 0x6990, + 0x79D0, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7ED0, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7E90, 0x7F00, 0x7F00, 0x7F00, 0x7F00, + 0x7E80, 0x7ED0, 0x7EF0, 0x7F10, 0x7EF0, 0x7E80, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, + 0x7EF0, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7EB0, 0x4110, 0x16D0, 0xFCB0, 0xF4A0, 0xFBE0, 0x0CF0, + 0x23F0, 0x3B80, 0x51C0, 0x64B0, 0x72A0, 0x7CA0, 0x7ED0, 0x7F10, 0x7EF0, 0x7F30, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7C00, + 0x7960, 0x7C50, 0x7EF0, 0x7F20, 0x7F00, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7F00, + 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F80, 0x7F00, 0x7F20, 0x7F20, 0x7F20, 0x7F90, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F70, + 0x7F20, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EE0, 0x7F50, 0x7F00, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, + 0x7EC0, 0x7ED0, 0x7EE0, 0x7F10, 0x7F10, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x6390, + 0x36E0, 0x04E0, 0xCE10, 0x9550, 0x84E0, 0x8480, 0x8480, 0x8450, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8410, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, + 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, + 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, + 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84B0, 0x84C0, + 0x84F0, 0x8540, 0x8670, 0x8D80, 0x9BC0, 0xA8A0, 0xB380, 0xBB50, 0xC0E0, 0xC420, 0xC570, 0xC520, 0xC2E0, 0xC030, 0xBB90, 0xB660, + 0xB0D0, 0xAAB0, 0xA410, 0x9D20, 0x9530, 0x8E50, 0x89D0, 0x87C0, 0x86D0, 0x8690, 0x86D0, 0x87D0, 0x8B00, 0x93B0, 0xA100, 0xAFA0, + 0xBEE0, 0xCE30, 0xDD00, 0xEAE0, 0xF830, 0x0500, 0x1260, 0x2210, 0x3120, 0x42C0, 0x5500, 0x6710, 0x77F0, 0x7F20, 0x7EF0, 0x7EF0, + 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F10, 0x7F70, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F60, + 0x7EE0, 0x7E90, 0x7F20, 0x7F20, 0x6D70, 0x4A30, 0x2330, 0xFB70, 0xD4A0, 0xB0F0, 0x9280, 0x8670, 0x8500, 0x84D0, 0x84C0, 0x84E0, + 0x84B0, 0x84B0, 0x84B0, 0x84D0, 0x84F0, 0x8540, 0x86B0, 0x8F50, 0xA3C0, 0xBA40, 0xD1F0, 0xEBF0, 0x07B0, 0x2650, 0x4370, 0x5EE0, + 0x7660, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F80, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, + 0x7F10, 0x7EC0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E70, 0x7EC0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7E90, 0x7EE0, 0x7F20, 0x7F10, 0x7F10, + 0x7EA0, 0x7EF0, 0x7F10, 0x7F00, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F40, 0x7F10, 0x7EF0, 0x7EE0, + 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EE0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, + 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7E90, 0x7EF0, 0x7EF0, 0x7EF0, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F30, 0x7F00, + 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, 0x7EF0, 0x7F00, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7F00, 0x7F10, + 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x53F0, 0x2AD0, 0x01E0, 0xD960, 0xB0B0, 0x8C80, 0x8510, + 0x84B0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8440, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, + 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8490, 0x84A0, 0x84D0, + 0x8500, 0x8550, 0x8560, 0x84E0, 0x84C0, 0x8490, 0x8480, 0x8480, 0x8490, 0x84B0, 0x94D0, 0xB0B0, 0xCD30, 0xEA60, 0x05E0, 0x1BF0, + 0x28B0, 0x26C0, 0x1340, 0xED10, 0xB420, 0x8570, 0x8480, 0x8450, 0x8430, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8430, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, + 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83D0, 0x83E0, 0x8390, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8440, 0x8410, 0x8410, 0x8410, 0x8410, 0x8430, 0x8420, 0x8440, + 0x8420, 0x8430, 0x8430, 0x8430, 0x8450, 0x8400, 0x8460, 0x8480, 0x84B0, 0x84D0, 0x85B0, 0x9400, 0xB1E0, 0xCC00, 0xE330, 0xF8A0, + 0x0980, 0x17F0, 0x22A0, 0x2A40, 0x2DF0, 0x2D50, 0x2A20, 0x23E0, 0x1A10, 0x0EE0, 0x0160, 0xF290, 0xE2B0, 0xD230, 0xC180, 0xB1D0, + 0xA330, 0x9680, 0x8DD0, 0x8940, 0x8730, 0x8640, 0x85E0, 0x85B0, 0x85B0, 0x85C0, 0x8610, 0x86C0, 0x8820, 0x8B30, 0x9080, 0x9750, + 0x9E40, 0xA650, 0xAE90, 0xB740, 0xBE40, 0xC370, 0xC540, 0xC480, 0xC140, 0xBD40, 0xBA40, 0xB9E0, 0xBDD0, 0xC7D0, 0xD750, 0xEC50, + 0x0720, 0x2840, 0x4CC0, 0x7180, 0x7F10, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F20, + 0x7EF0, 0x7ED0, 0x7F80, 0x7F00, 0x7F00, 0x7ED0, 0x7EF0, 0x7F70, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7EC0, + 0x7EE0, 0x7F30, 0x7F00, 0x7E90, 0x7EB0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7EA0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, + 0x7F00, 0x7EE0, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, + 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F20, 0x7F20, 0x7F00, 0x7F80, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F50, 0x7EE0, 0x7ED0, 0x7F10, + 0x7F20, 0x7F50, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7E90, + 0x7D90, 0x7B00, 0x7960, 0x7A80, 0x7C30, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F30, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F10, 0x7F80, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7EF0, + 0x7F10, 0x7F00, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F30, 0x7EE0, 0x7EA0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7E90, + 0x7EF0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7EE0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, + 0x7EF0, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7F30, 0x7F20, 0x76C0, 0x6BF0, 0x6070, 0x52C0, 0x4360, 0x30F0, 0x1D70, 0x0760, 0xEE80, + 0xD420, 0xB900, 0x9C40, 0x87F0, 0x8500, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8440, 0x8430, 0x8450, 0x8440, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8460, 0x8450, 0x8430, 0x8420, 0x8410, + 0x8400, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x8400, 0x8410, 0x8420, 0x8440, 0x8450, 0x8470, + 0x8480, 0x84A0, 0x84D0, 0x8530, 0x88C0, 0xA340, 0xBDA0, 0xD370, 0xE2E0, 0xEC90, 0xF090, 0xF0F0, 0xEF90, 0xEF30, 0xF120, 0xF6A0, + 0xFF50, 0x0BB0, 0x19A0, 0x28F0, 0x3910, 0x4700, 0x5370, 0x5D40, 0x65B0, 0x6D00, 0x73C0, 0x79C0, 0x7DB0, 0x7F00, 0x7EC0, 0x7F10, + 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F20, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7EE0, 0x7EF0, 0x7F80, 0x7EE0, + 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7EF0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, + 0x7F10, 0x7F00, 0x7F40, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F30, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x6D10, 0x4A50, 0x27D0, 0x0770, 0xE920, 0xCC50, 0xB070, 0x9530, 0x8640, 0x84E0, 0x84B0, 0x84A0, + 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, + 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, + 0x8460, 0x8470, 0x84A0, 0x8500, 0x87C0, 0x9FA0, 0xB360, 0xC390, 0xD290, 0xE5A0, 0xFA80, 0x1350, 0x2EB0, 0x4BE0, 0x68F0, 0x7E90, + 0x7F20, 0x7F20, 0x7F10, 0x7F60, 0x7F00, 0x7F00, 0x7F00, 0x7EE0, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7EE0, 0x7F10, 0x7F10, 0x7F20, + 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F40, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F20, + 0x7F40, 0x7B30, 0x4570, 0x0FE0, 0xD6C0, 0x9A20, 0x84F0, 0x8480, 0x8450, 0x8440, 0x8420, 0x8410, 0x8400, 0x83F0, 0x83E0, 0x83D0, + 0x8390, 0x83C0, 0x83C0, 0x83E0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, + 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, + 0x8460, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x8500, 0x85C0, 0x8B10, 0x9DA0, 0xAD60, 0xBA20, 0xC3D0, 0xCA90, 0xCF20, 0xD190, 0xD460, + 0xD6D0, 0xD8E0, 0xDB60, 0xDCE0, 0xDD30, 0xD8C0, 0xCF20, 0xC050, 0xABE0, 0x9330, 0x8620, 0x84E0, 0x84C0, 0x8490, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8450, 0x8430, 0x8430, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8460, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x83D0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8380, + 0x8380, 0x8360, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8390, 0x8380, 0x8380, + 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x83D0, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, + 0x8370, 0x8370, 0x8370, 0x8380, 0x8370, 0x8380, 0x8380, 0x8380, 0x8390, 0x8390, 0x8340, 0x83A0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, + 0x83D0, 0x83E0, 0x8440, 0x8400, 0x8410, 0x8430, 0x8450, 0x8470, 0x84A0, 0x8640, 0xC110, 0x02F0, 0x4240, 0x76F0, 0x7F10, 0x7F00, + 0x7EF0, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7EB0, 0x7F00, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F70, 0x7EF0, 0x7F10, 0x7F00, + 0x7F00, 0x7F80, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7EE0, 0x7ED0, 0x7ED0, 0x7EE0, 0x7F40, 0x7F10, 0x7E90, 0x7EB0, 0x7ED0, + 0x7F10, 0x7F00, 0x7E70, 0x7EC0, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7F00, 0x7F00, 0x7EF0, + 0x7F10, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, + 0x7F00, 0x7F80, 0x7EF0, 0x7F20, 0x7F10, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F40, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, + 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F20, 0x7EF0, 0x7F00, + 0x7F00, 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, + 0x7EF0, 0x7F80, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EE0, 0x7EE0, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, + 0x7F10, 0x7F00, 0x7E90, 0x7EB0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, + 0x7F00, 0x7EC0, 0x7F30, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F40, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, + 0x7EF0, 0x7F50, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, + 0x7F60, 0x7EE0, 0x7E90, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EA0, 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, + 0x7F20, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, + 0x7EF0, 0x7F80, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F50, 0x7EE0, 0x7EE0, 0x7ED0, 0x7EE0, + 0x7F30, 0x7F00, 0x7E90, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7E70, 0x7EC0, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F10, + 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F10, + 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F30, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F10, + 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, + 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F00, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7EF0, 0x7F30, 0x7F30, 0x7C20, 0x6A70, 0x59D0, 0x48F0, 0x3860, 0x2820, 0x1790, 0x0800, 0xF960, + 0xEB60, 0xDE10, 0xD170, 0xC550, 0xB9E0, 0xAF40, 0xA610, 0x9D20, 0x9130, 0x8780, 0x8500, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8450, + 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8420, 0x8450, 0x8460, 0x8480, 0x84B0, + 0x8510, 0x8E10, 0xBAA0, 0xE380, 0x09C0, 0x3040, 0x5110, 0x6D30, 0x7EE0, 0x7EE0, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F00, 0x7F60, + 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, 0x7EE0, 0x7EC0, 0x7F30, 0x7F00, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, + 0x7F00, 0x7F20, 0x7F10, 0x7F80, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F60, 0x7F00, 0x7F00, 0x7F00, 0x7EF0, 0x7F30, 0x7EE0, 0x7EC0, + 0x7ED0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7E70, 0x7EC0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7E90, 0x7F10, 0x7F10, 0x7EE0, 0x7EC0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F40, + 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EE0, 0x7F00, + 0x7EE0, 0x7EF0, 0x7F70, 0x7F00, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7E90, 0x7EF0, 0x7EE0, 0x7EF0, 0x7ED0, 0x7EB0, 0x7F00, + 0x7F00, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7ED0, 0x7F30, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F10, + 0x7F10, 0x7EF0, 0x7EE0, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7EF0, 0x7F00, 0x7F90, 0x7EF0, 0x7EE0, + 0x7EE0, 0x7ED0, 0x7F50, 0x7F10, 0x7F70, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F10, 0x7EB0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, + 0x7EA0, 0x7EC0, 0x7F00, 0x7F30, 0x7F20, 0x7E90, 0x7EB0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7EB0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, + 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F20, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7F50, + 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F20, 0x7F80, 0x7EF0, 0x7EB0, 0x7F20, 0x7EF0, 0x7F30, 0x7EE0, + 0x7EC0, 0x7F10, 0x7F10, 0x7F40, 0x7ED0, 0x7E90, 0x7F00, 0x7EE0, 0x7EF0, 0x7EE0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, + 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F90, 0x7F20, 0x7F40, 0x7F40, 0x7F10, 0x7F70, + 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F80, 0x7C10, 0x6C20, 0x5CC0, 0x4AD0, 0x37F0, 0x24B0, 0x1060, 0xFC40, 0xE470, 0xCDE0, 0xB780, + 0xA000, 0x8BB0, 0x8580, 0x84D0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8410, 0x8430, 0x8450, 0x8430, 0x8410, + 0x8410, 0x8400, 0x8400, 0x83F0, 0x8400, 0x83F0, 0x83E0, 0x83E0, 0x83F0, 0x83D0, 0x83D0, 0x8380, 0x83C0, 0x83C0, 0x83C0, 0x8340, + 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, 0x8350, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, + 0x83B0, 0x8340, 0x83C0, 0x83C0, 0x83E0, 0x83C0, 0x83C0, 0x83C0, 0x83F0, 0x83C0, 0x83D0, 0x83C0, 0x83F0, 0x83B0, 0x83C0, 0x8380, + 0x83B0, 0x83B0, 0x83B0, 0x8350, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83C0, 0x83C0, 0x83B0, + 0x83C0, 0x83F0, 0x83C0, 0x83F0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83E0, 0x83C0, 0x83B0, 0x83B0, 0x83E0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8470, 0x8480, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, + 0x84D0, 0x84E0, 0x8520, 0x8600, 0x88C0, 0x8F10, 0x96B0, 0x9E60, 0xA510, 0xACF0, 0xB640, 0xC1D0, 0xD020, 0xE220, 0xF520, 0x0940, + 0x1E90, 0x35E0, 0x4D00, 0x6370, 0x77D0, 0x7EA0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7EB0, + 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F40, 0x7EF0, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, + 0x7F00, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F40, 0x7F20, 0x7F20, 0x7F30, 0x7F10, 0x7F30, 0x7F20, 0x7EF0, 0x7F20, 0x7F00, + 0x6E30, 0x5BF0, 0x4870, 0x34E0, 0x2090, 0x0C20, 0xF7A0, 0xE2C0, 0xCE90, 0xB910, 0xA500, 0x9200, 0x8770, 0x8540, 0x84E0, 0x84B0, + 0x84A0, 0x8490, 0x8470, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8400, 0x8410, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8430, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8430, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x8370, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83B0, + 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x8400, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x8350, + 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8380, 0x83A0, 0x83A0, 0x83A0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8430, 0x8410, 0x8410, 0x8400, 0x8420, 0x8420, + 0x8430, 0x8420, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8460, 0x8480, 0x8490, 0x84B0, 0x84C0, 0x84F0, 0x8550, 0x8640, + 0x8850, 0x8BC0, 0x8F70, 0x9160, 0x9220, 0x9110, 0x8ED0, 0x8BF0, 0x8910, 0x86F0, 0x85B0, 0x8520, 0x84F0, 0x84C0, 0x84D0, 0x84A0, + 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8470, 0x8440, 0x8440, 0x8430, + 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8440, 0x8460, + 0x8470, 0x8480, 0x84C0, 0x8500, 0x8750, 0xA400, 0xC9D0, 0xF3D0, 0x1FE0, 0x4BE0, 0x7200, 0x7F30, 0x7EF0, 0x7F10, 0x7F10, 0x7EF0, + 0x7F60, 0x7ED0, 0x7EF0, 0x7F00, 0x7F00, 0x7F50, 0x7F00, 0x7EE0, 0x7F10, 0x7F10, 0x7F30, 0x7EC0, 0x7E90, 0x7F10, 0x7F20, 0x7F30, + 0x7ED0, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F50, 0x7EE0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, + 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EE0, 0x7F10, 0x7F00, 0x7EC0, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7F10, + 0x7F10, 0x7EE0, 0x7F70, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F50, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7EC0, 0x7ED0, + 0x7EE0, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7E70, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, + 0x7F10, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, 0x7F00, 0x7F20, 0x7EC0, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, + 0x7EF0, 0x7EE0, 0x7F40, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F60, 0x7ED0, 0x7EF0, 0x7EE0, + 0x7EF0, 0x7F50, 0x7EE0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7EE0, 0x7E90, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EA0, 0x7F20, 0x7F00, + 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, 0x7F00, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F60, 0x7F10, 0x7F10, + 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7F10, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F80, 0x7F10, 0x7EE0, 0x7EE0, + 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7EF0, 0x7EE0, 0x7F40, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7E80, 0x7EC0, 0x7F00, + 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, + 0x7EF0, 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, + 0x7F10, 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7EB0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F30, 0x7EC0, 0x7E90, 0x7F10, 0x7F00, + 0x7F00, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F00, 0x7F10, + 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F90, 0x7F00, 0x7F40, 0x7EF0, 0x7EF0, 0x7F70, 0x7EE0, 0x7F10, 0x7EF0, + 0x7EE0, 0x7F70, 0x7F10, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F00, 0x7EF0, 0x7E90, 0x7F00, 0x7F20, + 0x7F10, 0x7F20, 0x7EA0, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F40, 0x7F00, 0x7470, 0x5D80, 0x4500, 0x2C60, 0x1380, 0xFA40, + 0xE270, 0xCAA0, 0xB1E0, 0x9CA0, 0x8A90, 0x8580, 0x8530, 0x84C0, 0x84A0, 0x8490, 0x84B0, 0x8470, 0x8460, 0x8460, 0x8480, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8490, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x84E0, 0x8500, 0x84E0, + 0x8510, 0x8530, 0x8500, 0x8500, 0x8500, 0x84F0, 0x84D0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, + 0x8470, 0x8470, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84B0, 0x84C0, + 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, + 0x8460, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, + 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8380, 0x83B0, 0x8380, 0x8380, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, + 0x8370, 0x8370, 0x8360, 0x8350, 0x8360, 0x8360, 0x8380, 0x8360, 0x8360, 0x8370, 0x8370, 0x8360, 0x8370, 0x8370, 0x8370, 0x8380, + 0x8380, 0x8380, 0x83B0, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83D0, 0x83B0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x8390, 0x8380, + 0x8380, 0x8380, 0x8370, 0x8360, 0x8360, 0x8360, 0x8350, 0x8350, 0x8350, 0x8350, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, + 0x8340, 0x8340, 0x8340, 0x8340, 0x8350, 0x8350, 0x8350, 0x8350, 0x8350, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, + 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8360, 0x8370, 0x8370, 0x8370, 0x8380, + 0x8380, 0x8380, 0x8380, 0x8390, 0x8390, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8420, 0x8430, 0x8430, 0x8450, 0x8460, 0x8480, 0x84A0, 0x84F0, 0x8840, 0xB250, 0xE0E0, + 0x1110, 0x4450, 0x7500, 0x7F20, 0x7EF0, 0x7EA0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EC0, 0x7F20, 0x7EF0, 0x7EE0, 0x7EF0, 0x7ED0, + 0x7F30, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, 0x7F20, 0x7EF0, 0x7ED0, 0x7F60, + 0x7F00, 0x7EF0, 0x7EB0, 0x7EE0, 0x7F50, 0x7EF0, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F30, 0x7F00, 0x7EA0, 0x7EB0, 0x7EB0, 0x7EE0, 0x7EF0, + 0x7E90, 0x7EA0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7E90, 0x7EE0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, + 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F30, 0x7F00, 0x7F10, 0x7F00, 0x7F00, 0x7F50, + 0x7ED0, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F60, 0x7EE0, 0x7E90, 0x7F00, 0x7EE0, 0x7F50, 0x7EB0, + 0x7E70, 0x7EE0, 0x7EF0, 0x7F20, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, + 0x7EF0, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F80, + 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, + 0x7F50, 0x7F00, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x6BD0, 0x3AC0, 0x0FD0, 0xE790, 0xC2E0, 0xA170, 0x8960, 0x8510, + 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8470, 0x8400, 0x8460, 0x8460, 0x8460, 0x8440, 0x8450, 0x8460, 0x8460, + 0x8460, 0x8470, 0x8470, 0x8470, 0x84A0, 0x84B0, 0x84F0, 0x85F0, 0x93E0, 0xB320, 0xD0C0, 0xEE40, 0x09A0, 0x2480, 0x3D00, 0x5380, + 0x6790, 0x78F0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F80, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F70, + 0x7F00, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7F20, 0x7E90, 0x7EB0, 0x7EE0, 0x7F30, 0x7F10, 0x7E70, 0x7EC0, 0x7ED0, 0x7EF0, 0x6860, + 0x4A40, 0x24A0, 0xFCE0, 0xD100, 0xA410, 0x8670, 0x84C0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8470, 0x8440, 0x8430, 0x8420, 0x8420, + 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8420, 0x8420, 0x8420, 0x8430, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84D0, + 0x84F0, 0x8520, 0x8580, 0x85C0, 0x85C0, 0x8580, 0x8560, 0x8500, 0x84D0, 0x84D0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, + 0x8490, 0x8490, 0x8460, 0x8460, 0x8480, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x83E0, 0x8440, 0x8430, 0x8440, 0x8400, + 0x8430, 0x8430, 0x8460, 0x8420, 0x8450, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8470, 0x8450, 0x8450, + 0x8460, 0x8470, 0x8490, 0x84B0, 0x8540, 0x9770, 0xC440, 0xED20, 0x0FC0, 0x2AD0, 0x3CC0, 0x4580, 0x4800, 0x4610, 0x4830, 0x50A0, + 0x6250, 0x7970, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F50, + 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7EC0, 0x7EF0, 0x7F00, 0x7F70, 0x7ED0, 0x7E90, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, + 0x7EA0, 0x7EF0, 0x7F00, 0x7F20, 0x7F00, 0x7E90, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, + 0x7F50, 0x7EF0, 0x7F00, 0x7F10, 0x7EF0, 0x7F60, 0x7EE0, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, + 0x7EE0, 0x7EE0, 0x7ED0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EE0, 0x7F50, 0x7EF0, 0x7E70, 0x7EC0, 0x7ED0, 0x7EF0, 0x7EF0, + 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, + 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, + 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7AC0, 0x3B30, 0x00F0, 0xC340, 0x89C0, + 0x84B0, 0x8470, 0x8450, 0x8460, 0x8420, 0x8400, 0x83F0, 0x83F0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83A0, 0x8390, 0x8390, 0x8390, + 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83E0, 0x83C0, 0x83D0, 0x8370, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, + 0x8390, 0x8390, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8380, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, + 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83E0, + 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83F0, + 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x84D0, 0x86E0, 0xB6C0, 0xEFC0, 0x29C0, + 0x6360, 0x7F00, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7EE0, 0x7F80, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7F10, + 0x7EF0, 0x7EE0, 0x7F40, 0x7EF0, 0x7EF0, 0x7EE0, 0x7ED0, 0x7F70, 0x7F00, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F60, 0x7F10, 0x7E90, 0x7EE0, + 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7EE0, 0x7F00, 0x7F00, 0x7E90, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x6960, 0x33C0, + 0xFCD0, 0xC740, 0x9470, 0x84F0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, + 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, 0x8470, 0x8490, 0x84A0, 0x84D0, 0x8510, 0x85E0, 0x87D0, 0x8890, 0x8750, 0x85D0, 0x8550, + 0x8520, 0x8540, 0x85C0, 0x8850, 0x9810, 0xAB50, 0xBF30, 0xD3A0, 0xE990, 0x0090, 0x1740, 0x2E40, 0x4190, 0x5260, 0x5EC0, 0x66D0, + 0x6E30, 0x75A0, 0x7DA0, 0x7EF0, 0x7EF0, 0x7F00, 0x7EF0, 0x7F80, 0x7F20, 0x7EE0, 0x7EF0, 0x7ED0, 0x7F30, 0x7EF0, 0x7E90, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EC0, 0x7F00, 0x7F10, 0x7F10, 0x7E90, 0x7ED0, 0x7F00, 0x7EE0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F20, + 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F50, 0x7F20, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, + 0x7F00, 0x7EE0, 0x7F50, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F00, 0x7F80, 0x7EF0, 0x7EB0, 0x7EE0, + 0x7EF0, 0x7F30, 0x7EE0, 0x7D20, 0x5710, 0x2BF0, 0x0070, 0xD200, 0xA150, 0x8570, 0x84D0, 0x8470, 0x83F0, 0x8400, 0x83F0, 0x83F0, + 0x8410, 0x83D0, 0x83C0, 0x8360, 0x83B0, 0x83A0, 0x8390, 0x8350, 0x8380, 0x83B0, 0x8370, 0x8370, 0x8360, 0x8360, 0x8350, 0x8350, + 0x8350, 0x8350, 0x8350, 0x8340, 0x8350, 0x8350, 0x8350, 0x8350, 0x8350, 0x8340, 0x8350, 0x8350, 0x8340, 0x8350, 0x8350, 0x8350, + 0x8350, 0x8360, 0x8360, 0x8360, 0x8370, 0x8350, 0x8380, 0x8380, 0x8390, 0x8390, 0x83A0, 0x83B0, 0x83A0, 0x83C0, 0x83D0, 0x83E0, + 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, + 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x8400, + 0x8410, 0x8410, 0x8430, 0x8440, 0x8450, 0x84D0, 0x85F0, 0xA270, 0xCC20, 0xF470, 0x1B70, 0x4120, 0x6470, 0x7E90, 0x7EB0, 0x7F00, + 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F10, + 0x7F20, 0x7F00, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F70, 0x7EF0, 0x7EB0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, + 0x7EF0, 0x7EF0, 0x7F20, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, 0x7EF0, 0x7E90, 0x7F00, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F80, 0x7EF0, + 0x7F10, 0x7F20, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, + 0x7EB0, 0x7EF0, 0x4D90, 0x0FF0, 0xD240, 0x9590, 0x84E0, 0x8490, 0x8460, 0x8490, 0x8430, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, + 0x83D0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8420, 0x8420, + 0x8440, 0x8460, 0x8480, 0x84C0, 0x8700, 0xC400, 0x0640, 0x4DB0, 0x7EB0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, + 0x7EF0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F10, 0x7EF0, 0x7F00, 0x7F00, 0x7EF0, 0x7F80, 0x7F00, + 0x7F20, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F20, 0x7F10, 0x7F10, + 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7EE0, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F60, 0x7EF0, 0x7EB0, 0x7F10, 0x7F40, 0x7F10, 0x7ED0, 0x7E80, 0x7F40, 0x7F10, + 0x7EB0, 0x7E70, 0x7E60, 0x7EF0, 0x7EF0, 0x7F20, 0x7ED0, 0x7E90, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F40, 0x7EF0, 0x7EE0, + 0x7EF0, 0x7ED0, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7EF0, 0x7F30, 0x7EF0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, 0x7F10, 0x7F20, 0x7F00, + 0x7EF0, 0x7F60, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7F40, 0x7EF0, 0x7EB0, 0x7EF0, 0x7ED0, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, + 0x7960, 0x5D40, 0x4F90, 0x4DB0, 0x5260, 0x5840, 0x5D90, 0x5E00, 0x5B40, 0x54D0, 0x4C30, 0x4460, 0x3C40, 0x3680, 0x3120, 0x2A20, + 0x22F0, 0x1A40, 0x10A0, 0x05F0, 0xFB90, 0xF240, 0xEAE0, 0xE570, 0xE190, 0xDE30, 0xDBF0, 0xD890, 0xD510, 0xD0C0, 0xCAD0, 0xC5D0, + 0xC0C0, 0xBCB0, 0xB9D0, 0xB810, 0xB810, 0xB8B0, 0xB9B0, 0xBB60, 0xBB90, 0xB980, 0xB4B0, 0xAC20, 0x9FD0, 0x90C0, 0x8750, 0x8520, + 0x84D0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84C0, 0x8530, 0x8CB0, 0xAD10, 0xC270, 0xC760, 0xBAC0, 0x9E70, 0x8660, + 0x84C0, 0x8490, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8460, 0x8470, 0x8470, 0x8490, 0x84B0, 0x84F0, 0x8580, 0x8700, 0x8940, + 0x8C00, 0x9150, 0x9D30, 0xAFB0, 0xC8F0, 0xE260, 0xFB00, 0x10C0, 0x2230, 0x30B0, 0x3C40, 0x4650, 0x50B0, 0x5B00, 0x6490, 0x6D10, + 0x7470, 0x7B20, 0x7E60, 0x7ED0, 0x7F00, 0x7F20, 0x7F10, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, + 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F20, 0x7F20, 0x7F10, + 0x7F10, 0x7F60, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F80, 0x7F00, 0x7ED0, 0x6A90, 0x2140, + 0x1530, 0x0EC0, 0x0A70, 0x08C0, 0x0870, 0x0A70, 0x0CA0, 0x0F50, 0x1300, 0x1660, 0x1B40, 0x1F70, 0x2230, 0x23A0, 0x2180, 0x1CB0, + 0x13B0, 0x05D0, 0xF690, 0xE5B0, 0xD3B0, 0xC080, 0xAC50, 0x9820, 0x88F0, 0x8550, 0x84E0, 0x84B0, 0x84C0, 0x8490, 0x8480, 0x8480, + 0x8470, 0x8470, 0x8470, 0x8490, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x8500, + 0x85B0, 0x8950, 0x9A70, 0xAE60, 0xC020, 0xD1D0, 0xDF30, 0xE920, 0xF060, 0xF350, 0xF390, 0xEFF0, 0xE8A0, 0xDE60, 0xD050, 0xC2F0, + 0xB6D0, 0xAEE0, 0xACE0, 0xB0A0, 0xB980, 0xC680, 0xD590, 0xE810, 0xF900, 0x0A60, 0x1AC0, 0x2910, 0x35F0, 0x3F60, 0x4600, 0x4990, + 0x4940, 0x46D0, 0x3FD0, 0x3560, 0x26B0, 0x1400, 0xFEC0, 0xE590, 0xC980, 0xA8B0, 0x8C30, 0x8520, 0x84C0, 0x84A0, 0x8490, 0x8480, + 0x8470, 0x8470, 0x8410, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84C0, 0x84F0, 0x85E0, 0x8FE0, + 0xA8A0, 0xBEA0, 0xD1F0, 0xE200, 0xF0E0, 0xFB50, 0x0350, 0x0A00, 0x0E80, 0x10D0, 0x1170, 0x0EE0, 0x0B80, 0x0510, 0xFDC0, 0xF5F0, + 0xEC50, 0xE2B0, 0xD890, 0xCDE0, 0xC2F0, 0xB7E0, 0xABC0, 0x9FB0, 0x9300, 0x8A30, 0x8660, 0x8540, 0x84F0, 0x84D0, 0x84E0, 0x84B0, + 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x8500, 0x8570, 0x8830, 0x9EC0, 0xBA90, 0xD830, 0xF620, 0x1360, 0x2E40, 0x4430, 0x5700, + 0x6460, 0x6E90, 0x7600, 0x7A80, 0x7E00, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, + 0x7F10, 0x7F00, 0x7EE0, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x6F50, 0x5080, 0x2A10, 0x0230, 0xD520, 0xA540, + 0x8690, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8490, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x84B0, 0x84D0, 0x8530, 0x8AE0, 0xB430, 0xE0F0, 0x1160, 0x4170, 0x6DC0, 0x7ED0, + 0x7F30, 0x7F20, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, + 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, + 0x7F10, 0x7F60, 0x7F00, 0x7ED0, 0x7F00, 0x7F00, 0x7F90, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F30, 0x7EE0, 0x7ED0, 0x7F00, 0x7F20, + 0x7F50, 0x7ED0, 0x7E90, 0x7F00, 0x7F10, 0x7EE0, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F50, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F30, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F10, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F40, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F60, 0x7F40, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, + 0x7EF0, 0x6120, 0x30C0, 0xFD30, 0xC530, 0x8CB0, 0x84C0, 0x8480, 0x8450, 0x8440, 0x8420, 0x8410, 0x8400, 0x83F0, 0x83F0, 0x83E0, + 0x83E0, 0x83D0, 0x83D0, 0x8390, 0x83D0, 0x83D0, 0x83D0, 0x83B0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83A0, 0x83B0, + 0x83A0, 0x83A0, 0x8380, 0x8390, 0x83C0, 0x8380, 0x83A0, 0x8380, 0x8380, 0x8390, 0x83A0, 0x8370, 0x8380, 0x8310, 0x8380, 0x8380, + 0x83B0, 0x8390, 0x8390, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83F0, 0x83D0, 0x83D0, 0x83D0, 0x8370, 0x83E0, 0x83E0, 0x83F0, 0x83F0, + 0x8430, 0x8410, 0x8410, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x84A0, 0x84D0, 0x8520, 0x86C0, 0x9370, 0xA810, + 0xBAA0, 0xCC60, 0xDF40, 0xEF30, 0xFF20, 0x0D50, 0x1B00, 0x27F0, 0x3300, 0x3E60, 0x48F0, 0x5360, 0x5D40, 0x6600, 0x6FB0, 0x7860, + 0x7EE0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F80, + 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7EE0, + 0x7EC0, 0x7F10, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EC0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, + 0x7F80, 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F90, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F70, + 0x7F00, 0x7EE0, 0x7ED0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, + 0x7E90, 0x7EB0, 0x7F00, 0x7EF0, 0x7EF0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7EB0, + 0x7F20, 0x7EB0, 0x7ED0, 0x7ED0, 0x7F00, 0x7F00, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7EE0, 0x7F40, 0x7F30, 0x7F20, 0x7EF0, 0x7F10, 0x7F60, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F20, 0x7EE0, 0x7EF0, + 0x7F70, 0x7F00, 0x7F00, 0x7F10, 0x7ED0, 0x78F0, 0x7140, 0x6910, 0x61E0, 0x59F0, 0x51A0, 0x48F0, 0x4010, 0x3760, 0x2E00, 0x23F0, + 0x1AE0, 0x1140, 0x0810, 0xFEA0, 0xF560, 0xED00, 0xE4D0, 0xDDD0, 0xD6E0, 0xD010, 0xC9A0, 0xC310, 0xBCE0, 0xB6D0, 0xB1B0, 0xADA0, + 0xAAE0, 0xA970, 0xA890, 0xA830, 0xA870, 0xA8E0, 0xA920, 0xA9E0, 0xAA90, 0xAB80, 0xACD0, 0xADD0, 0xAFB0, 0xB150, 0xB2A0, 0xB3C0, + 0xB450, 0xB540, 0xB560, 0xB530, 0xB3D0, 0xB1F0, 0xB030, 0xAD80, 0xAAF0, 0xA820, 0xA5D0, 0xA450, 0xA320, 0xA260, 0xA200, 0xA220, + 0xA360, 0xA530, 0xA900, 0xAD80, 0xB3F0, 0xBCE0, 0xC600, 0xD140, 0xDBF0, 0xE7D0, 0xF4C0, 0x01C0, 0x0FC0, 0x1EB0, 0x2E40, 0x3D80, + 0x4BB0, 0x59E0, 0x6660, 0x7140, 0x7AF0, 0x7F00, 0x7F60, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, + 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7D70, 0x7560, 0x6DA0, 0x6430, 0x5AB0, 0x5120, 0x4690, 0x3D10, 0x32C0, 0x27D0, + 0x1E10, 0x1400, 0x09F0, 0x0180, 0xFA30, 0xF4E0, 0xF020, 0xED40, 0xEBA0, 0xEAB0, 0xEB00, 0xEBB0, 0xED40, 0xEF20, 0xF0D0, 0xF3B0, + 0xF620, 0xF970, 0xFCF0, 0xFF50, 0x0140, 0x0040, 0xFD10, 0xF760, 0xEF50, 0xE630, 0xDC90, 0xD2E0, 0xCAC0, 0xC3E0, 0xBF40, 0xBD00, + 0xBDA0, 0xC190, 0xC890, 0xD2D0, 0xDE90, 0xEB10, 0xF740, 0xFFB0, 0x0500, 0x06C0, 0x0490, 0x00D0, 0xFA80, 0xF320, 0xE9F0, 0xDDF0, + 0xD040, 0xBF80, 0xABF0, 0x9560, 0x8720, 0x8500, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, + 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8450, 0x8430, 0x8430, 0x8440, 0x8430, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8440, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, + 0x83C0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, + 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, + 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8440, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x8500, 0x8590, 0x8820, + 0x9220, 0xA120, 0xAD70, 0xB760, 0xBF60, 0xC570, 0xC8D0, 0xC9C0, 0xC9C0, 0xC830, 0xC610, 0xC470, 0xC2B0, 0xC180, 0xBF30, 0xBC50, + 0xB710, 0xAF70, 0xA570, 0x9860, 0x8BB0, 0x8600, 0x84F0, 0x84C0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, + 0x8450, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8460, 0x84A0, 0x8470, 0x8490, 0x8480, 0x8490, 0x8490, + 0x84A0, 0x84B0, 0x84B0, 0x84D0, 0x84E0, 0x8500, 0x8560, 0x8690, 0x8B00, 0x9820, 0xA6A0, 0xB4D0, 0xC190, 0xCD90, 0xD850, 0xE1B0, + 0xEAD0, 0xF230, 0xF990, 0x0170, 0x09C0, 0x12E0, 0x1C90, 0x26D0, 0x3120, 0x3CF0, 0x47F0, 0x53A0, 0x5E70, 0x6970, 0x72F0, 0x7B40, + 0x7F00, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F90, 0x7F30, 0x7F00, 0x7F40, 0x7F30, 0x7F50, 0x7F40, 0x7EE0, + 0x7F10, 0x7F10, 0x7EF0, 0x7EF0, 0x7EB0, 0x7470, 0x6620, 0x5590, 0x4370, 0x2E30, 0x1800, 0xFEC0, 0xE330, 0xC380, 0xA440, 0x8970, + 0x84F0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, + 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83A0, 0x8390, 0x8390, 0x8380, 0x8370, 0x8360, 0x8360, 0x8350, 0x8350, + 0x8350, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8340, 0x8350, + 0x8350, 0x8350, 0x8350, 0x8360, 0x8360, 0x8360, 0x8360, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8370, 0x8380, 0x8380, 0x8380, + 0x8380, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x8400, + 0x8410, 0x8420, 0x8430, 0x8440, 0x8450, 0x8470, 0x8480, 0x84A0, 0x84C0, 0x8510, 0x8700, 0x9830, 0xAD10, 0xBE50, 0xCD10, 0xD900, + 0xE450, 0xEDF0, 0xF6E0, 0xFF80, 0x0850, 0x1260, 0x1BA0, 0x2680, 0x3180, 0x3EA0, 0x4C90, 0x5B30, 0x6B70, 0x7A00, 0x7F20, 0x7F10, + 0x7F20, 0x7F20, 0x7ED0, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F50, 0x7F00, 0x7F20, + 0x7F00, 0x7F10, 0x7F70, 0x7EE0, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, + 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7E60, 0x68E0, 0x5310, 0x3D10, 0x2870, 0x1500, 0x0290, 0xF120, + 0xE1A0, 0xD4D0, 0xC9A0, 0xC030, 0xB820, 0xB150, 0xAC80, 0xA860, 0xA580, 0xA3B0, 0xA260, 0xA1A0, 0xA100, 0xA080, 0x9FF0, 0x9E60, + 0x9C10, 0x9860, 0x9340, 0x8560, 0x8500, 0x84E0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84F0, 0x8550, 0x8800, + 0x9DE0, 0xBB00, 0xD950, 0xF7B0, 0x15A0, 0x31C0, 0x4CC0, 0x67A0, 0x7BC0, 0x7EF0, 0x7ED0, 0x7F00, 0x7EE0, 0x7F30, 0x7F10, 0x7E70, + 0x7ED0, 0x7EB0, 0x7F10, 0x7EF0, 0x7E90, 0x7ED0, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, + 0x7F10, 0x7F20, 0x7EF0, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F50, 0x7F10, + 0x7F20, 0x7F10, 0x7F10, 0x7F70, 0x7EF0, 0x7F10, 0x7EF0, 0x7F20, 0x7F70, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, + 0x7EF0, 0x7EF0, 0x7F20, 0x7ED0, 0x7E90, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, 0x7F00, 0x7EC0, 0x7F00, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, + 0x7F10, 0x7F20, 0x7F00, 0x7F80, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EE0, 0x7ED0, 0x7EF0, 0x7F60, 0x7F00, 0x7E90, + 0x7EB0, 0x7EB0, 0x7EF0, 0x7F00, 0x7E70, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7E90, 0x7EE0, + 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F00, 0x7ED0, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F40, 0x7EF0, + 0x7F20, 0x7F00, 0x7F00, 0x7F50, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, 0x7E90, + 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F20, + 0x7EF0, 0x7F10, 0x7EE0, 0x7EC0, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7EE0, 0x7F10, 0x7F10, 0x7EE0, 0x7F60, 0x7EF0, + 0x7F20, 0x7F00, 0x7F00, 0x7F50, 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F70, 0x7F10, 0x7EE0, + 0x7EE0, 0x7ED0, 0x7F30, 0x7EF0, 0x7E70, 0x7EC0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7E90, 0x7EE0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7ED0, + 0x7F10, 0x7F00, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F40, 0x7F40, 0x6780, 0x4630, 0x28A0, 0x0CA0, 0xEF90, + 0xCF00, 0xA5A0, 0x86C0, 0x84C0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8470, + 0x8480, 0x84D0, 0x8FB0, 0xEAA0, 0x3190, 0x6730, 0x7EB0, 0x7F20, 0x7ED0, 0x7EB0, 0x7F20, 0x7F10, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F10, + 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x63C0, 0x3AB0, 0x0D30, 0xDFD0, 0xB580, 0x8F10, 0x8500, 0x84B0, 0x84B0, 0x8470, + 0x8450, 0x8440, 0x8430, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83E0, 0x83C0, 0x83C0, 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, + 0x8390, 0x8390, 0x8390, 0x8380, 0x8380, 0x8380, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83E0, 0x83A0, 0x8390, 0x8390, + 0x8390, 0x8390, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8390, 0x83F0, 0x83F0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8410, 0x8420, + 0x8450, 0x8440, 0x8450, 0x8460, 0x8480, 0x8490, 0x84B0, 0x84E0, 0x8650, 0xA820, 0xDE50, 0x1F90, 0x6820, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, + 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, + 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7EF0, + 0x7F20, 0x7F00, 0x7F20, 0x7F20, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, + 0x7F00, 0x7F10, 0x7F30, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7F20, 0x7EA0, 0x7F10, 0x7F20, 0x7F40, + 0x7EF0, 0x7E90, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7E80, 0x7EA0, 0x7ED0, 0x7F20, 0x7F00, 0x7EC0, 0x7F00, 0x7EB0, 0x7F20, 0x7F20, + 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7ED0, 0x7EF0, + 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, 0x7EF0, 0x7ED0, 0x7F10, 0x7EE0, 0x7EC0, 0x7EF0, 0x7EE0, 0x7F20, + 0x7F10, 0x7E90, 0x7EF0, 0x7EE0, 0x7F10, 0x7F00, 0x7E70, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F10, 0x7F10, + 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F10, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EE0, + 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7EB0, 0x7A40, 0x7550, 0x7060, 0x6B70, 0x6680, 0x6000, 0x5920, 0x5100, 0x4810, + 0x3F50, 0x3580, 0x2CF0, 0x2470, 0x1BE0, 0x1420, 0x0CF0, 0x0610, 0xFF90, 0xF9A0, 0xF3C0, 0xEE70, 0xEAE0, 0xE780, 0xE410, 0xE1A0, + 0xDF40, 0xDDC0, 0xDC90, 0xDB60, 0xDAF0, 0xDAC0, 0xDAE0, 0xDB00, 0xDC20, 0xDD90, 0xDF10, 0xE170, 0xE480, 0xE770, 0xEB70, 0xEDC0, + 0xF030, 0xF2D0, 0xF500, 0xF780, 0xFAB0, 0xFDA0, 0x0020, 0x01B0, 0x0310, 0x0360, 0x0350, 0x0310, 0x0130, 0xFF60, 0xFC80, 0xF930, + 0xF560, 0xF0A0, 0xEB50, 0xE530, 0xDEC0, 0xD860, 0xD140, 0xC900, 0xC020, 0xB6A0, 0xAD60, 0xA360, 0x9930, 0x8FE0, 0x8940, 0x8640, + 0x8540, 0x84F0, 0x84D0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84D0, 0x84F0, 0x8530, + 0x85A0, 0x85F0, 0x8600, 0x85D0, 0x85D0, 0xB680, 0xCEF0, 0xE410, 0xF290, 0xFBF0, 0x0370, 0x0E60, 0x1E00, 0x2E30, 0x3760, 0x2AD0, + 0xFE30, 0xA990, 0x84B0, 0x8460, 0x8440, 0x8420, 0x8410, 0x8400, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x8400, + 0x8420, 0x8440, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, 0x84B0, 0x84E0, 0x8520, 0x8520, 0x84E0, 0x84A0, 0x8470, 0x8460, 0x8440, + 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, + 0x83A0, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8350, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8390, 0x8330, 0x8390, 0x8390, + 0x8390, 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x8370, + 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x8370, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, + 0x8390, 0x83C0, 0x83B0, 0x8380, 0x8380, 0x8390, 0x8380, 0x8370, 0x8370, 0x8350, 0x8360, 0x8360, 0x8370, 0x8350, 0x8350, 0x8350, + 0x8360, 0x8340, 0x8340, 0x8340, 0x8350, 0x8340, 0x8340, 0x8370, 0x8360, 0x8340, 0x8340, 0x8380, 0x8350, 0x8350, 0x8350, 0x8380, + 0x8350, 0x8360, 0x8380, 0x8370, 0x8380, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83D0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, + 0x8390, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8410, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x84A0, 0x84D0, 0x8520, 0x8670, 0x8F20, 0xA190, 0xB330, 0xC370, 0xD2E0, 0xE080, + 0xECF0, 0xF7F0, 0x0410, 0x0F20, 0x1C20, 0x2A40, 0x3950, 0x4890, 0x56A0, 0x6410, 0x7080, 0x7C60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, + 0x7F70, 0x7F10, 0x7EB0, 0x7EC0, 0x7ED0, 0x7F30, 0x7F00, 0x7EA0, 0x7ED0, 0x7EE0, 0x7F20, 0x7F20, 0x7E90, 0x7EE0, 0x7EE0, 0x7F10, + 0x7F10, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7E90, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F00, 0x7EF0, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F10, 0x7C00, 0x6F50, 0x6410, 0x59B0, 0x5020, 0x46F0, 0x3E30, 0x3580, 0x2D20, 0x2620, 0x2190, 0x21B0, 0x27D0, + 0x3590, 0x4C30, 0x69F0, 0x7EF0, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F50, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, + 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F10, + 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F10, 0x48C0, 0x16C0, 0xEEC0, 0xD730, 0xD1D0, 0xDED0, 0xFA00, + 0x20F0, 0x4740, 0x6880, 0x7E50, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F10, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F00, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F00, + 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F20, + 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7560, 0x6310, 0x4E30, 0x3670, 0x1D20, 0x02A0, 0xE730, 0xCC50, 0xAF20, + 0x9450, 0x8690, 0x84E0, 0x84C0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, + 0x8460, 0x8430, 0x8440, 0x8490, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8490, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, + 0x8470, 0x8480, 0x84B0, 0x84A0, 0x84B0, 0x84C0, 0x84E0, 0x8520, 0x85F0, 0x8C10, 0xA380, 0xBDB0, 0xDA90, 0xF5B0, 0x0FE0, 0x27C0, + 0x3D50, 0x5030, 0x5F70, 0x6CA0, 0x7610, 0x7DE0, 0x7EF0, 0x7F10, 0x7F00, 0x7EA0, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7F30, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7D40, 0x7590, 0x6E20, 0x66C0, 0x5F80, 0x5870, 0x5030, 0x4920, 0x4210, 0x3B90, 0x35E0, + 0x3080, 0x2BF0, 0x2740, 0x2180, 0x1A10, 0x0FB0, 0x0130, 0xEF70, 0xDAC0, 0xC380, 0xAEC0, 0x9D00, 0x8F30, 0x8870, 0x8630, 0x85B0, + 0x8510, 0x84F0, 0x84C0, 0x84C0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, 0x84F0, + 0x8510, 0x8530, 0x8580, 0x8610, 0x8730, 0x8990, 0x8CB0, 0x90D0, 0x9420, 0x9770, 0x9B30, 0x9F30, 0xA510, 0xACD0, 0xB630, 0xC250, + 0xD080, 0xE060, 0xF160, 0x0450, 0x1990, 0x2FF0, 0x49D0, 0x6130, 0x76F0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7ED0, 0x7EE0, + 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, 0x7F00, + 0x7EF0, 0x7F00, 0x7F00, 0x7EC0, 0x7F20, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7F50, 0x7F00, + 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7ED0, 0x7EE0, 0x7ED0, 0x7F60, 0x7F00, 0x7EC0, + 0x7ED0, 0x7ED0, 0x7EF0, 0x7F00, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EE0, 0x7F00, 0x7F10, 0x7F00, 0x7E90, 0x7ED0, + 0x7F00, 0x7EE0, 0x7EF0, 0x7EC0, 0x7F20, 0x7F20, 0x7F10, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7EC0, + 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F40, 0x7F20, 0x7F10, 0x7EF0, 0x7EE0, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F50, + 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F50, 0x7EF0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, + 0x7E90, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7EF0, 0x7F00, 0x7F00, 0x7EE0, + 0x7F50, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7EE0, 0x7F80, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F70, + 0x7F00, 0x7DD0, 0x3C90, 0xFB60, 0xB160, 0x8580, 0x8490, 0x8470, 0x8450, 0x8440, 0x8440, 0x8440, 0x8450, 0x8470, 0x8490, 0x84F0, + 0x9370, 0xD410, 0x0D20, 0x4250, 0x7200, 0x7EA0, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EA0, + 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F10, 0x7F60, + 0x7F00, 0x7F20, 0x7F00, 0x7F00, 0x7F90, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F30, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7F40, 0x7ED0, + 0x7E90, 0x7EF0, 0x7EE0, 0x7F30, 0x7EE0, 0x7EA0, 0x7ED0, 0x7F10, 0x7F20, 0x7F20, 0x7E90, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F00, + 0x7F20, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F00, 0x7F40, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7F10, 0x7EF0, 0x7F80, + 0x7F10, 0x7F20, 0x7F00, 0x7A10, 0x6F90, 0x64F0, 0x5920, 0x4C30, 0x3FB0, 0x32C0, 0x25C0, 0x18C0, 0x0CC0, 0x01C0, 0xF830, 0xF0D0, + 0xEBC0, 0xEA10, 0xEB80, 0xEF50, 0xF770, 0x0040, 0x0C10, 0x18A0, 0x2660, 0x36F0, 0x45B0, 0x54E0, 0x63D0, 0x7110, 0x7C30, 0x7EC0, + 0x7F40, 0x7F10, 0x7F20, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, + 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7F00, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EB0, 0x7F00, 0x7F10, 0x7F70, 0x7F00, + 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7EE0, 0x7EF0, 0x7F10, 0x7F10, 0x7EA0, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7E90, + 0x7F10, 0x7EF0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F90, + 0x7F20, 0x7F10, 0x7F20, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F20, 0x7F10, + 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, + 0x7EF0, 0x7F10, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F30, + 0x7F30, 0x7EE0, 0x5370, 0x2A50, 0x02D0, 0xE320, 0xC800, 0xAFF0, 0x9B90, 0x8BE0, 0x8630, 0x8540, 0x84E0, 0x84B0, 0x84A0, 0x8490, + 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8470, 0x8440, 0x8440, 0x8450, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8400, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, 0x8400, + 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83F0, + 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, + 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, + 0x83D0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x8390, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8490, + 0x8490, 0x8480, 0x8480, 0x8440, 0x84A0, 0x84A0, 0x84C0, 0x84D0, 0x84F0, 0x8530, 0x85D0, 0x8840, 0x9210, 0xA0C0, 0xB000, 0xC030, + 0xF970, 0x0860, 0x1820, 0x27C0, 0x3700, 0x4740, 0x5600, 0x6530, 0x7400, 0x7E10, 0x7F00, 0x7EE0, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F10, 0x7F40, 0x7EF0, 0x7F20, 0x7F40, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7F20, + 0x7F60, 0x7ED0, 0x7EB0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7E90, 0x7EF0, 0x7F10, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, + 0x7F10, 0x7EA0, 0x7F10, 0x7EF0, 0x7F20, 0x7F00, 0x7EC0, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7F10, 0x7F20, + 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7F10, 0x7ED0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EE0, + 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F30, 0x7EF0, 0x7E90, 0x7ED0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7EE0, 0x7F10, 0x7F10, + 0x7F00, 0x7EC0, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7EE0, + 0x7EF0, 0x7F70, 0x7F00, 0x7F20, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, 0x7EE0, 0x7F50, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, + 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F00, 0x7F30, 0x7EF0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F40, + 0x7F00, 0x7EB0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, 0x7F00, 0x7F20, 0x7EF0, + 0x7F10, 0x7F40, 0x7EF0, 0x7F30, 0x7F30, 0x7F00, 0x7F90, 0x7F10, 0x7F10, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F90, 0x7730, 0x6600, + 0x5650, 0x47A0, 0x3AE0, 0x3050, 0x2730, 0x1FA0, 0x17E0, 0x0F40, 0x0570, 0xF960, 0xEC70, 0xDE40, 0xCF70, 0xC120, 0xB3A0, 0xA740, + 0x9CC0, 0x9190, 0x8A40, 0x8660, 0x8530, 0x84E0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, + 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, + 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8490, 0x84A0, 0x84E0, 0x8560, 0x88B0, 0x9A70, 0xACC0, 0xBD40, 0xCB60, + 0xD830, 0xE2A0, 0xEBF0, 0xF360, 0xF980, 0xFED0, 0x0300, 0x0620, 0x08C0, 0x0A30, 0x0C30, 0x0DE0, 0x0ED0, 0x1010, 0x1080, 0x11D0, + 0x11D0, 0x1110, 0x10F0, 0x1000, 0x0F10, 0x0D70, 0x0BE0, 0x0BB0, 0x0AE0, 0x0AC0, 0x0A60, 0x09C0, 0x08F0, 0x0740, 0x0510, 0x0230, + 0xFE60, 0xFA40, 0xF600, 0xF150, 0xEC30, 0xE5E0, 0xDF30, 0xD880, 0xD160, 0xC9D0, 0xC250, 0xBAE0, 0xB2C0, 0xAAB0, 0xA290, 0x99C0, + 0x9250, 0x8C50, 0x8880, 0x8680, 0x8590, 0x8530, 0x8500, 0x84E0, 0x84D0, 0x84B0, 0x84A0, 0x84A0, 0x8490, 0x8480, 0x8480, 0x8460, + 0x8450, 0x8440, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x8410, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, + 0x83C0, 0x83E0, 0x83C0, 0x83C0, 0x83D0, 0x83C0, 0x83D0, 0x83F0, 0x8400, 0x83D0, 0x83E0, 0x8390, 0x83E0, 0x83F0, 0x8400, 0x83F0, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, + 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8450, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83D0, + 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, + 0x8420, 0x8400, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8490, + 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, + 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, + 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, + 0x8430, 0x8430, 0x8460, 0x8440, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8450, 0x8460, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8470, 0x84A0, + 0x84B0, 0x84D0, 0x8510, 0x8620, 0x9000, 0xA780, 0xBE40, 0xD390, 0xE950, 0xFC10, 0x0C70, 0x1C40, 0x2AE0, 0x37E0, 0x43B0, 0x4EA0, + 0x58C0, 0x6150, 0x6860, 0x6DD0, 0x7280, 0x7610, 0x78B0, 0x7B20, 0x7C40, 0x7D50, 0x7DC0, 0x7E10, 0x7E50, 0x7E90, 0x7EA0, 0x7EC0, + 0x7EB0, 0x7EB0, 0x7E70, 0x7E40, 0x7DF0, 0x7D20, 0x7CA0, 0x7C30, 0x7C30, 0x7C90, 0x7D40, 0x7E40, 0x7F00, 0x7F20, 0x7F20, 0x7EF0, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7F30, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F30, 0x7F20, 0x7F00, 0x7F00, 0x7EB0, + 0x7F00, 0x7ED0, 0x7F10, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F60, 0x7F00, 0x7ED0, 0x7EF0, 0x7F00, 0x7F40, + 0x7EF0, 0x7EB0, 0x7EF0, 0x7EF0, 0x7F30, 0x7F20, 0x7EC0, 0x7F40, 0x7F10, 0x7F20, 0x7EE0, 0x7E90, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, + 0x7EB0, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7C10, 0x71B0, 0x67E0, 0x5F80, 0x56F0, 0x4FE0, 0x49E0, 0x4450, 0x4090, 0x3D60, + 0x3A80, 0x3830, 0x35B0, 0x33E0, 0x3240, 0x2FF0, 0x2E60, 0x2B20, 0x2890, 0x24C0, 0x2040, 0x1C40, 0x1790, 0x12F0, 0x0DF0, 0x0850, + 0x03B0, 0xFEE0, 0xF8F0, 0xF350, 0xEDB0, 0xE900, 0xE4B0, 0xE180, 0xDEA0, 0xDCF0, 0xDD10, 0xDE10, 0xE0A0, 0xE440, 0xE910, 0xEEA0, + 0xF520, 0xFC90, 0x0330, 0x0900, 0x0E50, 0x12D0, 0x16E0, 0x19E0, 0x1CA0, 0x1F70, 0x21C0, 0x2400, 0x25D0, 0x27A0, 0x29F0, 0x3760, + 0x3DB0, 0x4470, 0x4BA0, 0x5410, 0x5B00, 0x6100, 0x6680, 0x6A30, 0x6DA0, 0x6F40, 0x7130, 0x72E0, 0x7460, 0x7740, 0x7A40, 0x7D80, + 0x7EE0, 0x7F00, 0x7EF0, 0x7F10, 0x7F80, 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F80, 0x7F10, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F70, 0x7EF0, + 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F00, 0x7ED0, 0x7EB0, 0x7EE0, 0x7F50, 0x7F10, 0x7E70, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, + 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7EA0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F30, + 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F30, 0x7F00, 0x7A40, 0x7610, 0x7290, 0x6E20, 0x69D0, 0x63F0, 0x5CA0, 0x53A0, + 0x4890, 0x3F30, 0x34C0, 0x2A70, 0x1FF0, 0x15A0, 0x0BE0, 0x02D0, 0xF970, 0xF0A0, 0xE7E0, 0xDFA0, 0xB9E0, 0xB030, 0xA5D0, 0x9AA0, + 0x9040, 0x88E0, 0x85E0, 0x8520, 0x84E0, 0x84C0, 0x84A0, 0x8490, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8480, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84C0, 0x8530, 0x8AF0, + 0xAE50, 0xCF10, 0xEC50, 0x0560, 0x19C0, 0x2950, 0x35C0, 0x3DF0, 0x4550, 0x4C70, 0x5430, 0x5D60, 0x6690, 0x70A0, 0x79E0, 0x7F50, + 0x7F10, 0x7EC0, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7EA0, 0x7ED0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, + 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EC0, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, 0x7EE0, + 0x7F50, 0x7F10, 0x7F20, 0x7EF0, 0x7D30, 0x6DF0, 0x5DF0, 0x4CF0, 0x3C30, 0x2A90, 0x18F0, 0x07C0, 0xF560, 0xE540, 0xD5A0, 0xC6B0, + 0xB920, 0xABB0, 0x9E90, 0x9170, 0x88C0, 0x85C0, 0x84F0, 0x84D0, 0x84B0, 0x8490, 0x8490, 0x8480, 0x8470, 0x8460, 0x8460, 0x8450, + 0x8490, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8450, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8400, 0x8420, 0x8420, + 0x8430, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x84A0, 0x8470, 0x8470, 0x8470, 0x8490, 0x84B0, 0x84D0, 0x8510, + 0x8610, 0x8C40, 0x9F60, 0xB150, 0xC400, 0xD3C0, 0xE330, 0xF180, 0xFE00, 0x09C0, 0x13D0, 0x1C30, 0x22B0, 0x2810, 0x2BD0, 0x2EF0, + 0x32A0, 0x36D0, 0x3CD0, 0x44B0, 0x4EA0, 0x5A50, 0x66A0, 0x71C0, 0x7B50, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, 0x7F20, 0x7F80, + 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F30, 0x7EB0, 0x7EA0, 0x7890, 0x6C70, 0x60F0, 0x56C0, 0x4DB0, 0x47A0, 0x43A0, 0x40B0, 0x3F00, + 0x3D00, 0x3A10, 0x3610, 0x31A0, 0x2E60, 0x2A80, 0x28B0, 0x27B0, 0x2860, 0x29E0, 0x2A40, 0x2960, 0x2650, 0x1FF0, 0x18B0, 0x0FE0, + 0x0670, 0xFDD0, 0xF5E0, 0xEE90, 0xE830, 0xE230, 0xDCA0, 0xD690, 0xD080, 0xCA70, 0xC570, 0xC1A0, 0xBEE0, 0xBD40, 0xBDE0, 0xBF80, + 0xC380, 0xC820, 0xCE50, 0xD5B0, 0xDD90, 0xE710, 0xF0B0, 0xFB30, 0x0660, 0x1140, 0x1C80, 0x26E0, 0x30A0, 0x3950, 0x40B0, 0x4740, + 0x4C10, 0x5110, 0x5530, 0x5840, 0x5BC0, 0x5E00, 0x60B0, 0x63C0, 0x65D0, 0x68E0, 0x6B80, 0x6E80, 0x7190, 0x73F0, 0x7670, 0x78C0, + 0x7B00, 0x7CE0, 0x7E40, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, + 0x7EB0, 0x7E10, 0x7D40, 0x7C80, 0x7BF0, 0x7B70, 0x7B20, 0x7A90, 0x7A70, 0x7AA0, 0x7B90, 0x7C40, 0x7D70, 0x7E60, 0x7EE0, 0x7F30, + 0x7F30, 0x7F40, 0x7F30, 0x7F00, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F40, 0x7F50, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F20, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, 0x7F20, 0x7F20, 0x6790, 0x48A0, 0x2A70, 0x0E50, 0xF480, 0xDD60, 0xC6D0, 0xB480, + 0xA360, 0x93C0, 0x8990, 0x85F0, 0x8520, 0x84E0, 0x84C0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8480, 0x84C0, + 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x84D0, 0x84B0, 0x84E0, 0x8530, 0x8690, 0x8EB0, 0xA060, 0xB150, 0xC2D0, 0xD4B0, 0xE7B0, + 0xFC30, 0x11E0, 0x29E0, 0x3F70, 0x50E0, 0x5C90, 0x5FB0, 0x5920, 0x46C0, 0x2810, 0xFEF0, 0xCAC0, 0x9860, 0x8530, 0x84B0, 0x8490, + 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8410, 0x8470, 0x8480, 0x84B0, 0x8520, 0x91E0, 0xBC50, 0xD5C0, 0xE310, + 0xE710, 0xE560, 0xE220, 0xE040, 0xE0D0, 0xE3A0, 0xE780, 0xEA50, 0xEB70, 0xE770, 0xDDD0, 0xCD40, 0xB5B0, 0x98F0, 0x86C0, 0x8500, + 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8440, 0x8450, 0x8460, 0x8480, + 0x84A0, 0x84D0, 0x8550, 0x8EE0, 0xB030, 0xD000, 0xF050, 0x10E0, 0x3090, 0x4E50, 0x6930, 0x7CA0, 0x7F10, 0x7F00, 0x7EA0, 0x7EF0, + 0x7EF0, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F00, 0x7ED0, 0x7EF0, 0x7EA0, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F20, + 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F30, 0x7EE0, 0x7F40, 0x7F10, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, + 0x7EF0, 0x7EF0, 0x7F60, 0x7ED0, 0x7ED0, 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7EC0, 0x7F10, 0x7F10, 0x7F30, 0x7EC0, 0x7E90, 0x7EF0, + 0x7F10, 0x7F20, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7EC0, 0x7F10, 0x7EF0, 0x7EE0, 0x7F10, 0x7F00, 0x7F30, 0x7F00, + 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F70, 0x7F00, 0x7F10, + 0x7EF0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EB0, 0x7EE0, 0x7ED0, 0x7F70, 0x7F20, 0x7EC0, 0x7ED0, 0x7EB0, 0x7F10, 0x7EF0, 0x7E90, 0x7EB0, + 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7E90, 0x7F00, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F20, 0x7F20, + 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7EE0, 0x7EF0, 0x7F50, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7ED0, 0x7F10, + 0x7EF0, 0x7EE0, 0x7F50, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, 0x7EF0, 0x7F00, 0x7F50, 0x7ED0, 0x7EA0, 0x7EE0, + 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7EB0, 0x7F00, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EE0, 0x7F10, + 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7ED0, 0x7F00, 0x7F40, 0x7EB0, 0x7F00, + 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F00, 0x7EF0, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F40, 0x7F10, + 0x7F10, 0x7F00, 0x7EF0, 0x7F50, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7E80, 0x7C90, 0x7A30, 0x77A0, 0x74A0, 0x7150, 0x6DB0, + 0x69F0, 0x6650, 0x6270, 0x5EA0, 0x5A10, 0x55D0, 0x5120, 0x4BB0, 0x46E0, 0x4000, 0x39B0, 0x3290, 0x2AF0, 0x23F0, 0x1D00, 0x15C0, + 0x0EF0, 0x0710, 0xFFB0, 0xF880, 0xF170, 0xEB20, 0xE4F0, 0xDF90, 0xDAC0, 0xD5B0, 0xD1C0, 0xCD30, 0xC970, 0xC5C0, 0xC1D0, 0xBE60, + 0xBA00, 0xB6A0, 0xB2F0, 0xAF60, 0xAB90, 0xA7D0, 0xA450, 0xA0B0, 0x9CC0, 0x9930, 0x9530, 0x9160, 0x8D70, 0x8A50, 0x8860, 0x8700, + 0x8640, 0x85C0, 0x8570, 0x8540, 0x8520, 0x8510, 0x8500, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, + 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x84F0, 0x8520, 0x84D0, 0x84C0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, + 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84A0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84D0, 0x84E0, 0x84F0, 0x8520, 0x8580, + 0x8670, 0x8940, 0x9190, 0x9F20, 0xAC70, 0xBAC0, 0xC990, 0xD870, 0xE720, 0xF440, 0x0090, 0x0B80, 0x1670, 0x2050, 0x2850, 0x3000, + 0x3480, 0x35D0, 0x3510, 0x3100, 0x2BA0, 0x24B0, 0x1E50, 0x18A0, 0x1400, 0x1190, 0x1170, 0x13C0, 0x1880, 0x1F90, 0x2800, 0x2F90, + 0x3670, 0x3D40, 0x4260, 0x4650, 0x48F0, 0x4960, 0x48C0, 0x4410, 0x3D20, 0x3440, 0x29B0, 0x1F90, 0x1420, 0x0840, 0xFC10, 0xEF70, + 0xE090, 0xD110, 0xC090, 0xAEE0, 0x9B40, 0x8A60, 0x8550, 0x84D0, 0x84B0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8420, + 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8460, 0x8450, 0x8460, 0x8470, 0x8470, 0x8480, + 0x84A0, 0x84D0, 0x8550, 0x8C10, 0xAB40, 0xC8B0, 0xE510, 0xFC50, 0x0FB0, 0x1EF0, 0x2AA0, 0x32C0, 0x3790, 0x3A80, 0x3AC0, 0x3960, + 0x3540, 0x2EF0, 0x2610, 0x19B0, 0x0B00, 0xF870, 0xE2F0, 0xCC60, 0xB210, 0x98B0, 0x87D0, 0x8500, 0x84C0, 0x8490, 0x8480, 0x8470, + 0x8450, 0x8450, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, + 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x8490, 0x84A0, 0x8490, 0x8490, 0x8480, + 0x84A0, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8450, 0x8450, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, 0x8420, 0x8420, 0x8420, + 0x8420, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8450, 0x8440, + 0x8440, 0x8460, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8480, 0x8480, 0x8480, + 0x8480, 0x8480, 0x8480, 0x8480, 0x8470, 0x8470, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8450, 0x8460, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8480, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, + 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8490, 0x8450, 0x8450, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, + 0x8450, 0x8450, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8460, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8460, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, + 0x84B0, 0x84D0, 0x84F0, 0x8540, 0x8630, 0x8960, 0x9230, 0x9DB0, 0xA810, 0xB270, 0xBBD0, 0xC560, 0xCE70, 0xD8C0, 0xE260, 0xEBD0, + 0xF5C0, 0xFE90, 0x0690, 0x0CB0, 0x1130, 0x1560, 0x1930, 0x1D70, 0x21C0, 0x2570, 0x2980, 0x2D60, 0x3140, 0x33B0, 0x3510, 0x3620, + 0x3500, 0x3270, 0x2DA0, 0x26C0, 0x1E90, 0x1400, 0x0800, 0xFB40, 0xEB80, 0xDD90, 0xCF10, 0xC0E0, 0xB3A0, 0xA700, 0x9B50, 0x90A0, + 0x8900, 0x85C0, 0x8500, 0x84C0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8400, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, + 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x8400, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x8400, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x83C0, 0x8410, 0x8410, 0x8410, 0x8440, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8440, 0x8430, 0x8440, 0x8450, + 0x8450, 0x8460, 0x8470, 0x8470, 0x8490, 0x84A0, 0x84C0, 0x8500, 0x85C0, 0x8730, 0x8B90, 0x9360, 0x9A90, 0xA260, 0xAB90, 0xB6D0, + 0xC420, 0xD270, 0xE120, 0xEEF0, 0xFB60, 0x03C0, 0x0810, 0x0770, 0x0360, 0xFBE0, 0xF1B0, 0xE570, 0xD790, 0xC890, 0xBF00, 0xBDF0, + 0xCA50, 0xE430, 0x0B90, 0x39A0, 0x66C0, 0x7EF0, 0x7EA0, 0x7EC0, 0x7EC0, 0x7F10, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F10, + 0x7EA0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F00, + 0x7F60, 0x7EF0, 0x7F20, 0x7F00, 0x7F00, 0x7F90, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, 0x7F00, 0x7F40, + 0x7EC0, 0x7E90, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F50, 0x7ED0, 0x7E70, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7EC0, 0x7F10, 0x7EF0, + 0x7EE0, 0x7EF0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7EF0, 0x7F00, 0x7F10, 0x7F00, 0x7F30, 0x7EE0, 0x7EF0, + 0x7F30, 0x7F10, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F70, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, 0x7F00, + 0x7F00, 0x7F50, 0x7F10, 0x7EA0, 0x7EC0, 0x7ED0, 0x7F30, 0x7EE0, 0x7E90, 0x7ED0, 0x7EE0, 0x7F20, 0x7F10, 0x7ED0, 0x7EF0, 0x7EE0, + 0x7EF0, 0x7ED0, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7EE0, 0x7E90, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, + 0x7F40, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7EF0, 0x7F80, 0x7F10, 0x7F20, 0x7F10, + 0x7EF0, 0x7F70, 0x7F00, 0x7F10, 0x7EF0, 0x7EE0, 0x7F60, 0x7F10, 0x7D30, 0x6860, 0x56E0, 0x4670, 0x3700, 0x29F0, 0x1EF0, 0x1430, + 0x09B0, 0x0040, 0xF740, 0xEF10, 0xE720, 0xDF70, 0xD9E0, 0xD460, 0xD0A0, 0xCCD0, 0xC970, 0xC620, 0xC2C0, 0xBEC0, 0xB9E0, 0xB4E0, + 0xB040, 0xAB20, 0xA6F0, 0xA460, 0xA270, 0xA2D0, 0xA3A0, 0xA630, 0xAA30, 0xAF90, 0xB700, 0xC180, 0xCEF0, 0xDF80, 0xF340, 0x0A40, + 0x24C0, 0x3EC0, 0x5690, 0x6990, 0x77E0, 0x7E70, 0x7F70, 0x7EF0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7ED0, 0x7F10, 0x7F00, + 0x7F30, 0x7ED0, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7F10, 0x7E10, 0x6C70, 0x5D90, 0x5200, 0x4890, 0x4260, 0x3E50, + 0x3D50, 0x3E10, 0x4140, 0x4560, 0x4A00, 0x4F40, 0x5340, 0x5590, 0x5630, 0x5470, 0x5260, 0x4F50, 0x4C30, 0x49F0, 0x48F0, 0x4A10, + 0x4BC0, 0x4DE0, 0x5110, 0x5370, 0x56A0, 0x5940, 0x5CB0, 0x6070, 0x6540, 0x6B10, 0x70F0, 0x7740, 0x7CC0, 0x7E90, 0x7EB0, 0x7EF0, + 0x7F50, 0x7F10, 0x7E70, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, 0x7ED0, 0x7F00, 0x7F00, 0x7010, 0x5E00, 0x4B20, 0x3900, 0x2850, + 0x1C90, 0x1340, 0x0F40, 0x0E90, 0x1120, 0x1600, 0x1BD0, 0x22B0, 0x2960, 0x2E60, 0x31B0, 0x3270, 0x30C0, 0x2D50, 0x2A10, 0x2860, + 0x2960, 0x2D90, 0x37F0, 0x4900, 0x5D50, 0x7200, 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F60, 0x7F00, 0x7F00, 0x7F00, 0x7ED0, + 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F10, 0x7F40, 0x7ED0, 0x7EB0, 0x7F00, 0x7F00, 0x7F10, 0x7E90, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, + 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F10, 0x7F20, 0x7EF0, 0x7EF0, 0x7F10, 0x7EF0, 0x7F30, 0x7F20, + 0x7F00, 0x7590, 0x6B50, 0x61F0, 0x5AE0, 0x57C0, 0x5A10, 0x6170, 0x6C60, 0x7890, 0x7EF0, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F20, + 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7200, 0x6030, 0x4F20, 0x3F70, 0x32A0, 0x28D0, 0x2130, 0x1C60, 0x1970, 0x18B0, 0x1A10, 0x1D30, 0x2350, 0x2C30, + 0x3860, 0x4760, 0x57A0, 0x68C0, 0x7660, 0x7E80, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7F30, 0x7F20, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7EC0, + 0x7210, 0x63F0, 0x5470, 0x4480, 0x34E0, 0x2530, 0x1660, 0x07B0, 0xFB50, 0xF080, 0xE650, 0xDD70, 0xD550, 0xCD60, 0xC560, 0xBD70, + 0xB480, 0xABA0, 0xA1C0, 0x9630, 0x8B30, 0x8620, 0x8500, 0x84C0, 0x84B0, 0x8480, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, + 0x8450, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8430, + 0x8420, 0x8420, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, + 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8410, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, + 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8460, + 0x8470, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, 0x84B0, 0x84C0, 0x84C0, 0x84D0, + 0x84E0, 0x84F0, 0x8510, 0x8510, 0x8520, 0x8520, 0x8520, 0x8540, 0x8570, 0x8620, 0x8830, 0x8F00, 0x99A0, 0x9F60, 0xA220, 0xA020, + 0x9C50, 0x96C0, 0x9190, 0x8D80, 0x8B00, 0x89D0, 0x8990, 0x89C0, 0x8AF0, 0x8D30, 0x92A0, 0x9B90, 0xA6F0, 0xB5B0, 0xC700, 0xD7F0, + 0xE850, 0xF830, 0x0670, 0x1390, 0x1FF0, 0x2CE0, 0x38C0, 0x4690, 0x52C0, 0x5E40, 0x68B0, 0x71B0, 0x7970, 0x7E40, 0x7F50, 0x7F20, + 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7E90, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7E70, 0x7EC0, 0x7ED0, 0x7F10, 0x7F20, 0x7EC0, + 0x7F10, 0x7F10, 0x7F10, 0x7F10, 0x7EB0, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F40, 0x7F30, 0x7E00, 0x7540, 0x6B10, 0x5FF0, + 0x5360, 0x44C0, 0x35F0, 0x2520, 0x1240, 0xFF50, 0xEAB0, 0xD670, 0xC070, 0xAA80, 0x9450, 0x8750, 0x8510, 0x84D0, 0x84A0, 0x8490, + 0x8480, 0x8470, 0x8460, 0x8450, 0x8440, 0x8440, 0x8430, 0x8420, 0x8420, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83E0, 0x8400, 0x83D0, + 0x83C0, 0x83D0, 0x83C0, 0x83B0, 0x83B0, 0x83E0, 0x83B0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83F0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83B0, 0x83A0, 0x83B0, + 0x83A0, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, + 0x8400, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84D0, 0x8520, 0x8640, + 0x8C30, 0x9C40, 0xAA60, 0xB710, 0xC240, 0xEB00, 0xF3D0, 0xFBF0, 0x0380, 0x0C40, 0x1530, 0x1F60, 0x2A30, 0x3590, 0x4310, 0x5160, + 0x5FF0, 0x6E30, 0x7AB0, 0x7F00, 0x7F10, 0x7F60, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7E90, 0x7F10, 0x7EF0, 0x7F70, + 0x7F00, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7EE0, 0x7EA0, 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F10, + 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F50, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, + 0x7F80, 0x7F10, 0x7F20, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7EF0, 0x7EF0, 0x7EE0, 0x7F40, 0x7F10, 0x7EE0, 0x7EE0, 0x7ED0, 0x7F50, + 0x7F20, 0x7EC0, 0x7ED0, 0x7ED0, 0x7F40, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7E90, 0x7F10, 0x7F20, + 0x7EC0, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7EF0, 0x7F00, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, + 0x7F30, 0x7EF0, 0x7F00, 0x7EF0, 0x7F10, 0x7F60, 0x7F00, 0x7EF0, 0x7F20, 0x7F10, 0x7F90, 0x7EF0, 0x7EE0, 0x7EE0, 0x7EF0, 0x7F30, + 0x7F00, 0x7ED0, 0x7A80, 0x6A20, 0x5970, 0x4850, 0x3630, 0x23E0, 0x1140, 0xFE30, 0xE9B0, 0xD640, 0x8E50, 0x8670, 0x8500, 0x84D0, + 0x84B0, 0x84A0, 0x84B0, 0x8480, 0x8470, 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, + 0x8460, 0x8460, 0x8470, 0x8460, 0x8470, 0x8470, 0x84A0, 0x8470, 0x8480, 0x8480, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84B0, 0x84B0, + 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84B0, 0x84C0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x8530, + 0x8520, 0x8570, 0x8630, 0x87A0, 0x8B70, 0x9260, 0x9AC0, 0xA240, 0xA9B0, 0xB2A0, 0xBA20, 0xC1F0, 0xC960, 0xD060, 0xD810, 0xE000, + 0xE8A0, 0xF1A0, 0xFBF0, 0x06E0, 0x1240, 0x1ED0, 0x2C30, 0x3A60, 0x4AC0, 0x5A50, 0x6970, 0x77C0, 0x7EF0, 0x7F10, 0x7F00, 0x7F60, + 0x7EF0, 0x7F30, 0x7F20, 0x7F00, 0x7F90, 0x7F00, 0x7F40, 0x7F10, 0x7EF0, 0x7F70, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F00, 0x7F50, 0x7F10, + 0x7EE0, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7E70, 0x7ED0, 0x7EB0, 0x7F20, 0x7EF0, 0x7E90, 0x7EB0, 0x7F00, 0x7F10, 0x7F10, 0x7EA0, + 0x7ED0, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F60, + 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F70, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7EF0, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7EF0, 0x7F00, 0x7F30, + 0x7F10, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F20, 0x7F20, 0x7F30, + 0x7F30, 0x7F40, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F20, + 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F10, 0x7F20, + 0x7F10, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F30, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F30, + 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7EE0, 0x7F10, 0x7F30, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F20, + 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F40, 0x7F30, 0x7460, 0x5E10, 0x42A0, 0x2420, 0x02E0, 0xDFC0, 0xBB80, 0x9760, 0x8580, + 0x84C0, 0x8490, 0x8470, 0x8460, 0x8450, 0x8440, 0x8430, 0x8430, 0x8410, 0x8410, 0x8420, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, + 0x83E0, 0x83E0, 0x83E0, 0x8410, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x83F0, 0x83F0, 0x83F0, 0x83F0, + 0x83E0, 0x83F0, 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x83A0, 0x8390, 0x8390, 0x8380, + 0x8390, 0x8390, 0x83A0, 0x83A0, 0x83A0, 0x83A0, 0x83B0, 0x83C0, 0x83C0, 0x83D0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8480, 0x8490, 0x84A0, + 0x84D0, 0x8570, 0x92F0, 0xB400, 0xD110, 0xE9B0, 0xFDC0, 0x0DB0, 0x1AB0, 0x26A0, 0x3260, 0x3FF0, 0x4F00, 0x5E00, 0x6CF0, 0x7A30, + 0x7F00, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F10, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7EF0, 0x62A0, 0x3C70, 0x1460, 0xE820, + 0xB980, 0x8C80, 0x84E0, 0x84A0, 0x8480, 0x8470, 0x8460, 0x8460, 0x8460, 0x8460, 0x8460, 0x8470, 0x8470, 0x8470, 0x8490, 0x84B0, + 0x84F0, 0x8880, 0xB970, 0xEC10, 0x1C00, 0x46A0, 0x6800, 0x7E00, 0x7EA0, 0x7ED0, 0x7EB0, 0x7F20, 0x7F10, 0x7E90, 0x7F10, 0x7F00, + 0x7EF0, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F60, 0x7EF0, 0x7F10, + 0x7F10, 0x7F00, 0x7F60, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F70, 0x7EE0, 0x7EC0, 0x7EF0, 0x7F10, 0x7F60, 0x7ED0, 0x7ED0, 0x7F00, + 0x7F00, 0x7F10, 0x7EB0, 0x7E70, 0x7EE0, 0x7EF0, 0x7F30, 0x7EC0, 0x7E90, 0x7F10, 0x7F00, 0x7F00, 0x7F10, 0x7EB0, 0x7F00, 0x7F10, + 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7F20, 0x7F00, 0x7F10, 0x7F10, 0x7EF0, 0x7F60, 0x7EF0, 0x7F10, + 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, 0x7F20, 0x7EF0, 0x7EF0, 0x7F60, 0x7EE0, 0x7F10, 0x7EE0, 0x7EE0, 0x7F50, 0x7F10, 0x7EB0, 0x7EE0, + 0x7ED0, 0x7F10, 0x7F00, 0x7EC0, 0x7EB0, 0x7EB0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7EA0, + 0x7ED0, 0x7ED0, 0x7F00, 0x7EE0, 0x7E90, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7EA0, 0x7F00, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F40, + 0x7F10, 0x7F20, 0x7EF0, 0x7F00, 0x7F60, 0x7F20, 0x7F10, 0x7F10, 0x7EF0, 0x7F40, 0x7EF0, 0x7F10, 0x7EE0, 0x7EF0, 0x7F50, 0x7F00, + 0x7F00, 0x7F10, 0x7F10, 0x7F30, 0x7EF0, 0x7ED0, 0x7EF0, 0x7EE0, 0x7F50, 0x7ED0, 0x7EA0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, + 0x7EF0, 0x7F00, 0x7EF0, 0x7EF0, 0x7EB0, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7EC0, 0x7F40, 0x7F10, 0x7F10, 0x7F20, 0x7EF0, 0x7F20, + 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F10, 0x7F10, 0x7C30, 0x6F60, 0x63F0, 0x5930, 0x4E20, 0x4440, 0x3A10, 0x2FF0, 0x26E0, + 0x1CE0, 0x1380, 0x0A00, 0x0140, 0xF8D0, 0xF030, 0xE860, 0xE0D0, 0xD990, 0xD400, 0xCE90, 0xCAB0, 0xC7D0, 0xC660, 0xC680, 0xC7D0, + 0xCA80, 0xCD10, 0xD0C0, 0xD570, 0xD920, 0xDCC0, 0xDF70, 0xE020, 0xDFE0, 0xDCC0, 0xD7D0, 0xD060, 0xC4E0, 0xB810, 0xA730, 0x93E0, + 0x8710, 0x84F0, 0x84B0, 0x8480, 0x8470, 0x8450, 0x8430, 0x8420, 0x8410, 0x83F0, 0x83F0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83C0, + 0x83C0, 0x83C0, 0x83C0, 0x83D0, 0x83D0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8410, 0x8420, 0x8430, 0x8430, 0x8440, 0x8440, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x84B0, 0x84C0, 0x84E0, + 0x8520, 0x8580, 0x8690, 0x8890, 0x8C50, 0x9140, 0x96C0, 0x9C20, 0xA150, 0xA640, 0xAB20, 0xB050, 0xB510, 0xB980, 0xBE10, 0xC320, + 0xC800, 0xCDC0, 0xD310, 0xD960, 0xE0C0, 0xE890, 0xF150, 0xFAB0, 0x0520, 0x10D0, 0x1C70, 0x29A0, 0x3720, 0x4670, 0x54C0, 0x62C0, + 0x7090, 0x7C10, 0x7F00, 0x7EF0, 0x7E90, 0x7F00, 0x7ED0, 0x7F10, 0x7F20, 0x7EA0, 0x7F00, 0x7F10, 0x7F30, 0x7EE0, 0x7EA0, 0x7EF0, + 0x7F10, 0x7F20, 0x7F10, 0x7E90, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7EE0, 0x7EF0, 0x7F30, 0x7F20, 0x7F60, 0x7F10, + 0x7F10, 0x7F10, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7EF0, 0x7F80, 0x7F00, 0x7F00, 0x7F10, 0x7F00, 0x7F70, 0x7F10, 0x7EB0, + 0x7EE0, 0x7ED0, 0x7F50, 0x7F20, 0x7ED0, 0x7ED0, 0x7EE0, 0x7F30, 0x7F10, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7E70, 0x7EC0, + 0x7F10, 0x7F20, 0x7F20, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7EB0, 0x7F20, 0x7F00, 0x7F10, 0x7F20, 0x7F10, 0x7F10, 0x7F00, + 0x7EF0, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, + 0x7F10, 0x7F10, 0x7F10, 0x7F20, 0x7F40, 0x7F30, 0x7F30, 0x7F00, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F10, 0x7F30, 0x7F20, 0x7F40, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F50, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F30, 0x7F40, 0x7F40, 0x7F30, + 0x75F0, 0x6AC0, 0x6080, 0x5750, 0x5100, 0x4BD0, 0x4710, 0x41D0, 0x3BC0, 0x34C0, 0x2CD0, 0x24A0, 0x1B50, 0x1300, 0x0B10, 0x0400, + 0xFD80, 0xF790, 0xF270, 0xEDD0, 0xEA10, 0xE6D0, 0xE460, 0xE250, 0xE0F0, 0xDF30, 0xDD50, 0xDB60, 0xD8A0, 0xD490, 0xCDF0, 0xC5A0, + 0xBAD0, 0xAD50, 0x9D00, 0x8C90, 0x85F0, 0x84F0, 0x84B0, 0x8490, 0x8480, 0x8470, 0x8460, 0x8450, 0x8450, 0x8440, 0x8430, 0x8430, + 0x8420, 0x8420, 0x8410, 0x8400, 0x8410, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, 0x8400, + 0x8410, 0x8410, 0x8430, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, 0x8460, 0x8460, 0x8460, 0x84A0, 0x8480, 0x84B0, 0x8490, + 0x84B0, 0x84C0, 0x84E0, 0x8510, 0x85D0, 0x8840, 0x9170, 0x9F60, 0xAC30, 0xB920, 0xC600, 0xD2A0, 0xDF50, 0xED00, 0xF9A0, 0x0650, + 0x12F0, 0x1F70, 0x2BF0, 0x37E0, 0x4350, 0x4EF0, 0x5A40, 0x6550, 0x6F30, 0x7870, 0x7EA0, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F30, + 0x7F30, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7F10, 0x7F20, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7F20, 0x7F40, 0x7F50, + 0x7F30, 0x7FC0, 0x7F40, 0x7EF0, 0x7EF0, 0x7EF0, 0x7EF0, 0x7F30, 0x7E90, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7EA0, 0x7EC0, 0x7EF0, + 0x7F10, 0x7EF0, 0x7E90, 0x7EB0, 0x7EE0, 0x7EF0, 0x7F10, 0x7EA0, 0x7F40, 0x7F10, 0x7F10, 0x7EF0, 0x7E90, 0x7F10, 0x7EE0, 0x7EE0, + 0x7EF0, 0x7F00, 0x7F30, 0x7F00, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F20, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7EF0, 0x7F30, + 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F20, 0x7EE0, 0x7F40, 0x7EE0, 0x7F00, 0x7EF0, 0x7F10, 0x7F70, 0x7F00, 0x7EC0, 0x7EF0, 0x7EF0, + 0x7F70, 0x7ED0, 0x7EA0, 0x7EE0, 0x7EF0, 0x7F10, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F10, 0x7EB0, 0x7F10, 0x7EE0, 0x7EF0, + 0x7F10, 0x7F00, 0x7EF0, 0x7F10, 0x7F20, 0x7F20, 0x7F00, 0x7F50, 0x7EF0, 0x7F20, 0x7EF0, 0x7F00, 0x7F60, 0x7EF0, 0x7F10, 0x7F20, + 0x7F20, 0x7F80, 0x7F10, 0x7EF0, 0x7F10, 0x7F10, 0x7F70, 0x7EF0, 0x7EE0, 0x7EF0, 0x7EF0, 0x7F60, 0x7F20, 0x6C80, 0x5570, 0x3F10, + 0x2BF0, 0x1DB0, 0x12E0, 0x0CA0, 0x0890, 0x0600, 0x0370, 0x0090, 0xFE00, 0xFB20, 0xF900, 0xF870, 0xFAB0, 0xFFA0, 0x06C0, 0x1050, + 0x1B20, 0x2680, 0x3230, 0x3D30, 0x46E0, 0x5060, 0x57C0, 0x5EB0, 0x6400, 0x6850, 0x6D30, 0x7160, 0x75C0, 0x7A10, 0x7DE0, 0x7F00, + 0x7F00, 0x7F70, 0x7F20, 0x7F40, 0x7ED0, 0x7F10, 0x7F60, 0x7EE0, 0x7ED0, 0x7F10, 0x7EF0, 0x7F50, 0x7F00, 0x7EE0, 0x7F00, 0x7D80, + 0x77F0, 0x7270, 0x6CE0, 0x6830, 0x64B0, 0x61F0, 0x5FF0, 0x5CF0, 0x59E0, 0x5540, 0x4E50, 0x4710, 0x3CC0, 0x32D0, 0x2780, 0x1BB0, + 0x1040, 0x0580, 0xFB90, 0xF3D0, 0xEE20, 0xEB30, 0xEB00, 0xEC40, 0xEE10, 0xEFF0, 0xF0B0, 0xEE40, 0xE9D0, 0xE310, 0xD8C0, 0xCE90, + 0xC210, 0xB520, 0xA890, 0x9C70, 0x92F0, 0x8CA0, 0x8970, 0x8820, 0x87B0, 0x86F0, 0x86F0, 0x8750, 0x87C0, 0x8890, 0x89E0, 0x8AF0, + 0x8BA0, 0x8B30, 0x8A20, 0x8910, 0x87B0, 0x86F0, 0x8650, 0x85D0, 0x8590, 0x8560, 0x8530, 0x8510, 0x8500, 0x84F0, 0x84E0, 0x84D0, + 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84A0, 0x84C0, 0x84A0, 0x84A0, 0x84A0, 0x8470, + 0x84B0, 0x84B0, 0x84C0, 0x84C0, 0x84C0, 0x84D0, 0x84C0, 0x84D0, 0x84D0, 0x84E0, 0x84E0, 0x84E0, 0x84E0, 0x84D0, 0x84E0, 0x84E0, + 0x84F0, 0x84F0, 0x8500, 0x8510, 0x8520, 0x8530, 0x8560, 0x85A0, 0x8620, 0x86B0, 0x87D0, 0x8940, 0x8B40, 0x8E00, 0x9140, 0x9450, + 0x9850, 0x9B70, 0x9F40, 0xA290, 0xA630, 0xA930, 0xAA90, 0xAC30, 0xACC0, 0xAC20, 0xAB50, 0xA970, 0xA7B0, 0xA5C0, 0xA590, 0xA460, + 0xA360, 0xA1E0, 0x9EC0, 0x98F0, 0x9030, 0x87E0, 0x8530, 0x84C0, 0x8490, 0x8480, 0x8460, 0x8440, 0x8430, 0x8420, 0x8410, 0x8400, + 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8450, 0x8450, 0x8420, + 0x8440, 0x8440, 0x8440, 0x8450, 0x8490, 0x8460, 0x8490, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x84A0, 0x84B0, 0x84C0, 0x84C0, + 0x84D0, 0x84D0, 0x84E0, 0x84C0, 0x84D0, 0x84C0, 0x84C0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8490, 0x8480, 0x8470, + 0x8470, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, 0x8470, 0x8450, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8430, 0x8430, 0x8430, + 0x8430, 0x8420, 0x8420, 0x8420, 0x8410, 0x8410, 0x8410, 0x8410, 0x8400, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x83E0, 0x83E0, + 0x83E0, 0x83D0, 0x83D0, 0x83D0, 0x83C0, 0x83C0, 0x83B0, 0x83B0, 0x83A0, 0x83A0, 0x8390, 0x8380, 0x8380, 0x8370, 0x8370, 0x8370, + 0x8370, 0x8370, 0x8360, 0x8370, 0x8370, 0x8370, 0x8380, 0x8380, 0x8390, 0x8390, 0x8390, 0x83A0, 0x83B0, 0x83B0, 0x83B0, 0x83C0, + 0x83C0, 0x83D0, 0x83D0, 0x83E0, 0x83E0, 0x83F0, 0x83F0, 0x8400, 0x8400, 0x8400, 0x8400, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, + 0x8410, 0x8410, 0x83F0, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8410, 0x8420, 0x8420, 0x8430, 0x8430, 0x8430, 0x8440, 0x8440, + 0x8440, 0x8440, 0x8450, 0x8450, 0x8450, 0x8460, 0x8460, 0x8470, 0x8470, 0x8480, 0x8480, 0x8490, 0x8490, 0x8490, 0x84A0, 0x84A0, + 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84B0, 0x84A0, 0x8490, 0x8490, 0x8490, 0x8480, 0x8480, 0x8470, 0x8470, 0x8460, + 0x8460, 0x8450, 0x8460, 0x8450, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, 0x8440, + 0x8450, 0x8450, 0x8460, 0x8470, 0x8480, 0x8490, 0x8490, 0x84B0, 0x84C0, 0x84E0, 0x8500, 0x8550, 0x85F0, 0x8770, 0x8AE0, 0x91C0, + 0x9950, 0xA140, 0xA940, 0xB210, 0xBC20, 0xC660, 0xD0D0, 0xDC90, 0xE8C0, 0xF580, 0x02C0, 0x1010, 0x1DF0, 0x2D40, 0x3B90, 0x49F0, + 0x5940, 0x67C0, 0x7530, 0x7E90, 0x7F20, 0x7F00, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F10, 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7EF0, + 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7B00, 0x61B0, 0x4950, 0x3100, 0x1890, 0x0380, 0xEFE0, 0xDDD0, 0xCC60, 0xBC10, 0xAC80, 0x9D60, + 0x8F90, 0x8740, 0x8540, 0x84E0, 0x84B0, 0x8490, 0x8490, 0x8470, 0x8470, 0x8460, 0x8460, 0x8470, 0x8460, 0x8460, 0x8460, 0x8450, + 0x8450, 0x8440, 0x8430, 0x8430, 0x8420, 0x8410, 0x8410, 0x8400, 0x8400, 0x83F0, 0x83F0, 0x83F0, 0x8400, 0x8410, 0x8420, 0x8430, + 0x8430, 0x8440, 0x8450, 0x8450, 0x8460, 0x84A0, 0x8470, 0x8490, 0x84B0, 0x8500, 0x87A0, 0x9FE0, 0xB640, 0xC630, 0xD170, 0xD810, + 0xDC20, 0xDDF0, 0xDED0, 0xDEA0, 0xDDA0, 0xDCC0, 0xDDA0, 0xE1C0, 0xEA50, 0xF930, 0x0CA0, 0x24C0, 0x3FF0, 0x5B60, 0x73B0, 0x7F40, + 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F30, 0x7F20, 0x7EF0, 0x7F30, 0x7F30, 0x7F20, 0x7F20, 0x7EF0, + 0x7F30, 0x7F20, 0x7F30, 0x7F30, 0x7F00, 0x7F20, 0x7F10, 0x7F30, 0x7F20, 0x7F40, 0x7F20, 0x7F30, 0x7F20, 0x7F40, 0x7F30, 0x7F30, + 0x7F20, 0x7F20, 0x7F30, 0x7F30, 0x7EF0, 0x7E90, 0x7F30, 0x7F20, 0x7F20, 0x7F00, 0x7E90, 0x7F10, 0x7EB0, 0x7EF0, 0x7EB0, 0x7E60, + 0x7ED0, 0x7ED0, 0x7F30, 0x7F20, 0x7F00, 0x7F50, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, + 0x7F00, 0x7F20, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7EE0, 0x7EC0, 0x7EE0, 0x7F60, 0x7EF0, 0x7EF0, 0x7F00, 0x7EE0, 0x7EF0, 0x7EF0, + 0x7E70, 0x7F10, 0x7EB0, 0x7F30, 0x7EE0, 0x7E90, 0x7ED0, 0x7F00, 0x7F00, 0x7F10, 0x7EA0, 0x7EC0, 0x7EC0, 0x7F10, 0x7F00, 0x7EA0, + 0x7EF0, 0x7F10, 0x7F20, 0x7EF0, 0x7EB0, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7EF0, 0x7EF0, 0x7F70, + 0x7F10, 0x7F40, 0x7F10, 0x7F10, 0x7F30, 0x7F10, 0x7F10, 0x7F00, 0x7EE0, 0x7F70, 0x7EF0, 0x7EE0, 0x7F00, 0x7F10, 0x7F70, 0x7F00, + 0x7ED0, 0x7F10, 0x7F00, 0x7F30, 0x7ED0, 0x7E90, 0x7F00, 0x7EF0, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7EC0, + 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F30, 0x7F00, 0x7F00, 0x7EF0, 0x7F10, 0x7F80, + 0x7F00, 0x7F40, 0x7F30, 0x7F00, 0x7F90, 0x7F10, 0x7F10, 0x7EE0, 0x7EF0, 0x7F50, 0x7F10, 0x7EF0, 0x7EF0, 0x7F00, 0x7F60, 0x7F10, + 0x7EB0, 0x7EB0, 0x7EC0, 0x7EF0, 0x7F10, 0x7E70, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, 0x7EC0, 0x7ED0, 0x7F00, 0x7F10, 0x7F10, 0x7EB0, + 0x7EE0, 0x7EF0, 0x7F10, 0x7F20, 0x7F00, 0x7F40, 0x7F20, 0x7F20, 0x7F10, 0x7F00, 0x7F20, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F40, + 0x7F10, 0x7F20, 0x7F20, 0x7F10, 0x7F50, 0x7EF0, 0x7F00, 0x7EF0, 0x7F00, 0x7F40, 0x7EF0, 0x7F10, 0x7F00, 0x7F20, 0x7F70, 0x7ED0, + 0x7EB0, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EC0, 0x7F10, 0x7F20, 0x7F40, 0x7EC0, 0x7A30, 0x7740, 0x74B0, 0x76C0, 0x7A10, 0x7D20, + 0x7EC0, 0x7ED0, 0x7F10, 0x7F00, 0x7F40, 0x7ED0, 0x7EB0, 0x7EF0, 0x7F10, 0x7F30, 0x7F00, 0x7EC0, 0x7F10, 0x7F10, 0x7F20, 0x7F00, + 0x7EA0, 0x7F00, 0x7EF0, 0x7EF0, 0x7F20, 0x7F00, 0x7F40, 0x7F10, 0x7F10, 0x7F40, 0x7F00, 0x7F30, 0x7F00, 0x7F00, 0x7F40, 0x7F10, + 0x7F70, 0x7F00, 0x7F20, 0x7F20, 0x7F00, 0x7F90, 0x7F00, 0x7F20, 0x7EF0, 0x7ED0, 0x7F70, 0x7EF0, 0x7F10, 0x7F10, 0x7F00, 0x7F70, + 0x7F10, 0x7EB0, 0x7EB0, 0x7EE0, 0x7F30, 0x7F00, 0x7EC0, 0x7ED0, 0x7ED0, 0x7F20, 0x7F20, 0x7E90, 0x7EB0, 0x7EE0, 0x7F10, 0x7F10, + 0x7E70, 0x7EE0, 0x7F10, 0x7F10, 0x7F20, 0x7F00, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F00, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7EE0, + 0x7F40, 0x7F30, 0x7F20, 0x7F10, 0x7F10, 0x7F30, 0x7EE0, 0x7EF0, 0x7F10, 0x7EE0, 0x7F50, 0x7EF0, 0x7F20, 0x7F20, 0x7F10, 0x7F90, + 0x7EF0, 0x7F10, 0x7F10, 0x7F10, 0x7F60, 0x7EE0, 0x7EB0, 0x7F10, 0x7F20, 0x7F40, 0x7F00, 0x7EA0, 0x7F10, 0x7F10, 0x7F20, 0x7EE0, + 0x7EC0, 0x7F10, 0x7F10, 0x7EF0, 0x7F10, 0x7EB0, 0x7F20, 0x7F10, 0x7F10, 0x7F10, 0x7F00, 0x7F40, 0x7F00, 0x7F00, 0x7F10, 0x7F00, + 0x7F60, 0x7F20, 0x7F40, 0x7F10, 0x7F00, 0x7F80, 0x7F10, 0x7F10, 0x7F00, 0x7EF0, 0x7F90, 0x7F10, 0x7F20, 0x7F00, 0x7F10, 0x7F70, + 0x7F10, 0x7EF0, 0x7EB0, 0x7B20, 0x72F0, 0x6A50, 0x6030, 0x5570, 0x4A50, 0x3F30, 0x3500, 0x29F0, 0x1FB0, 0x14D0, 0x0A30, 0x0050, + 0xF4F0, 0xEA40, 0xDFB0, 0xD4D0, 0xCA60, 0xC000, 0xB560, 0xAB10, 0xA170, 0x97B0, 0x9010, 0x8AB0, 0x8800, 0x86A0, 0x8600, 0x85B0, + 0x8580, 0x8580, 0x8590, 0x8580, 0x8610, 0x8690, 0x8790, 0x8970, 0x8CC0, 0x9260, 0x9910, 0xA0A0, 0xA830, 0xB070, 0xB880, 0xC040, + 0xC8B0, 0xD0E0, 0xD9F0, 0xE270, 0xEBE0, 0xF500, 0xFE20, 0x0770, 0x1050, 0x1960, 0x2190, 0x29B0, 0x3260, 0x3AD0, 0x41F0, 0x4970, + 0x5000, 0x5680, 0x5CB0, 0x61F0, 0x6720, 0x6C00, 0x7120, 0x7500, 0x7890, 0x7C30, 0x7E00, 0x7F00, 0x7EF0, 0x7F10, 0x7F30, 0x7EC0, + 0x7F30, 0x7F20, 0x7F20, 0x7F40, 0x7F10, 0x7F70, 0x7EE0, 0x7EF0, 0x7F20, 0x7EE0, 0x7F80, 0x7F10, 0x7F20, 0x7F00, 0x7EF0, 0x7F50, + 0x7F00, 0x7F10, 0x7EF0, 0x7EF0, 0x7F60, 0x7EF0, 0x7ED0, 0x7F00, 0x7F00, 0x7F30, 0x7F20, 0x7EC0, 0x7ED0, 0x7ED0, 0x7F30, 0x7F00, + 0x7E80, 0x7AF0, 0x75E0, 0x6EF0, 0x68F0, 0x6230, 0x5BC0, 0x5490, 0x4D30, 0x4630, 0x3EC0, 0x3740, 0x2FA0, 0x27E0, 0x20F0, 0x1980, + 0x1220, 0x0AE0, 0x0390, 0xFA70, 0xF400, 0xED20, 0xE760, 0xE100, 0xDB80, 0xD650, 0xD0C0, 0xCC00, 0xC710, 0xC2D0, 0xBEB0, 0xBAE0, + 0xB7C0, 0xB4F0, 0xB230, 0xAFD0, 0xADE0, 0xAB90, 0xA9E0, 0xA8C0, 0xA850, 0xA7A0, 0xA780, 0xA750, 0xA7E0, 0xA7F0, 0xA9A0, 0xAA90, + 0xAC00, 0xADB0, 0xAFB0, 0xB270, 0xB510, 0xB800, 0xBB70, 0xBF60, 0xC3E0, 0xC790, 0xCCA0, 0xD130, 0xD640, 0xDBE0, 0xE130, 0xE710, + 0xEDA0, 0xF3F0, 0xFAA0, 0x0150, 0x07B0, 0x0EA0, 0x1570, 0x1BF0, 0x2340, 0x2AC0, 0x31D0, 0x3870, 0x3F40, 0x4590, 0x4B30, 0x5100, + 0x5640, 0x5AF0, 0x5FA0, 0x6330, 0x6670, 0x68D0, 0x6AE0, 0x6CA0, 0x6E20, 0x6F10, 0x6FB0, 0x7000, 0x7070, 0x7090, 0x6FE0, 0x6F80, + 0x6ED0, 0x6EB0, 0x6DD0, 0x6D80, 0x6CB0, 0x6C00, 0x6B60, 0x6AC0, 0x6A50, 0x6780, 0x66C0, 0x6640, 0x6550, 0x64C0, 0x6410, 0x6390, + 0x62E0, 0x6200, 0x6190, 0x6070, 0x5FC0, 0x5EC0, 0x5D50, 0x5C10, 0x5A70, 0x58A0, 0x56C0, 0x54D0, 0x52B0, 0x5060, 0x4E50, 0x4AD0, + 0x4790, 0x44A0, 0x40E0, 0x3D70, 0x3950, 0x35E0, 0x3240, 0x2ED0, 0x2AA0, 0x2780, 0x2350, 0x2090, 0x1D00, 0x1A40, 0x1750, 0x14D0, + 0x1210, 0x0FA0, 0x0D10, 0x0A30, 0x0840, 0x05C0, 0x03B0, 0x0170, 0xFF20, 0xFCC0, 0xF9B0, 0xF6E0, 0xF3C0, 0xF110, 0xEE30, 0xEB50, + 0xE8A0, 0xE610, 0xE450, 0xE300, 0xE1B0, 0xE110, 0xE070, 0xE0C0, 0xE0A0, 0xE110, 0xE1B0, 0xE300, 0xE480, 0xE610, 0xE7E0, 0xEA30, + 0xEC50, 0xEE40, 0xF000, 0xF260, 0xF440, 0xF620, 0xF7E0, 0xF950, 0xFAD0, 0xFBB0, 0xFCF0, 0xFDC0, 0xFE80, 0xFED0, 0xFF20, 0xFF90, + 0x0010, 0x0050, 0x0120, 0x0210, 0x02D0, 0x03D0, 0x04E0, 0x05D0, 0x0710, 0x08A0, 0x09C0, 0x0BA0, 0x0D80, 0x0F40, 0x11A0, 0x12F0, + 0x1540, 0x1700, 0x18F0, 0x1AD0, 0x1C70, 0x1EF0, 0x2140, 0x2350, 0x2540, 0x2840, 0x2AB0, 0x2CA0, 0x2E60, 0x30C0, 0x3270, 0x3470, + 0x36E0, 0x3870, 0x3B30, 0x3CC0, 0x3F10, 0x40F0, 0x41F0, 0x4460, 0x45D0, 0x4790, 0x4960, 0x4A50, 0x4C70, 0x4DB0, 0x4F20, 0x5050, + 0x5130, 0x5220, 0x5300, 0x53D0, 0x54B0, 0x54C0, 0x5590, 0x5680, 0x56B0, 0x57A0, 0x57C0, 0x58B0, 0x5940, 0x5980, 0x59D0, 0x59C0, + 0x5A60, 0x59D0, 0x59F0, 0x5A20, 0x5960, 0x5940, 0x5920, 0x58C0, 0x5840, 0x57B0, 0x5820, 0x5760, 0x5710, 0x5730, 0x5670, 0x5680, + 0x5630, 0x55F0, 0x5660, 0x55F0, 0x5660, 0x5600, 0x5550, 0x5590, 0x54E0, 0x54E0, 0x5480, 0x5370, 0x52F0, 0x51C0, 0x5140, 0x5000, + 0x4E60, 0x4E10, 0x4CB0, 0x4CA0, 0x4BA0, 0x4AC0, 0x4A50, 0x4980, 0x4840, 0x4780, 0x45F0, 0x4520, 0x4440, 0x4350, 0x41C0, 0x4020, + 0x3F30, 0x3DB0, 0x3C30, 0x3A70, 0x3870, 0x3730, 0x35A0, 0x3410, 0x32F0, 0x30E0, 0x2FE0, 0x2E80, 0x2C40, 0x2B40, 0x2910, 0x27D0, + 0x25F0, 0x23E0, 0x22C0, 0x20A0, 0x1F70, 0x1D90, 0x1B90, 0x1A20, 0x1840, 0x1750, 0x1590, 0x13E0, 0x1240, 0x1040, 0x0E70, 0x0CC0, + 0x0A10, 0x0890, 0x0650, 0x0500, 0x0310, 0x0130, 0xFFF0, 0xFE50, 0xFCF0, 0xFBE0, 0xFA60, 0xF9D0, 0xF860, 0xF720, 0xF5E0, 0xF550, + 0xF460, 0xF420, 0xF2D0, 0xF210, 0xF230, 0xF250, 0xF150, 0xF170, 0xF130, 0xF120, 0xF180, 0xF130, 0xF160, 0xF180, 0xF190, 0xF1D0, + 0xF220, 0xF2A0, 0xF2E0, 0xF3C0, 0xF3E0, 0xF3F0, 0xF430, 0xF4C0, 0xF4F0, 0xF530, 0xF590, 0xF570, 0xF5D0, 0xF5A0, 0xF670, 0xF680, + 0xF630, 0xF720, 0xF700, 0xF740, 0xF6C0, 0xF780, 0xF800, 0xF810, 0xF830, 0xF920, 0xF870, 0xF8D0, 0xF8C0, 0xF960, 0xFB50, 0xFBB0, + 0xFC80, 0xFCF0, 0xFDC0, 0xFE30, 0xFEC0, 0xFF90, 0x0010, 0x0120, 0x0180, 0x0200, 0x0270, 0x02C0, 0x0370, 0x0390, 0x03C0, 0x0400, + 0x0460, 0x0530, 0x05B0, 0x0680, 0x0710, 0x0790, 0x0860, 0x0940, 0x09F0, 0x0A90, 0x0B40, 0x0C40, 0x0CB0, 0x0D60, 0x0E20, 0x0ED0, + 0x0FE0, 0x10C0, 0x1150, 0x11F0, 0x12B0, 0x1390, 0x13D0, 0x1440, 0x1500, 0x1550, 0x1650, 0x1700, 0x1740, 0x1810, 0x1820, 0x1920, + 0x1990, 0x19B0, 0x1A20, 0x1A60, 0x1AD0, 0x1AF0, 0x1B60, 0x1B80, 0x1C10, 0x1C60, 0x1CA0, 0x1C40, 0x1CC0, 0x1C80, 0x1C60, 0x1C90, + 0x1BC0, 0x1BE0, 0x1BD0, 0x1B90, 0x1B10, 0x1AC0, 0x1A90, 0x1A70, 0x19C0, 0x1990, 0x19B0, 0x1960, 0x18A0, 0x1850, 0x17D0, 0x16F0, + 0x16A0, 0x1580, 0x1470, 0x1400, 0x12C0, 0x1270, 0x1170, 0x10E0, 0x0F80, 0x0E70, 0x0D60, 0x0BD0, 0x0A70, 0x0970, 0x0860, 0x0750, + 0x0630, 0x0460, 0x0440, 0x0200, 0x00B0, 0xFF40, 0xFDB0, 0xFCF0, 0xFC00, 0xFAA0, 0xF9C0, 0xF880, 0xF700, 0xF580, 0xF430, 0xF2B0, + 0xF140, 0xF000, 0xEE50, 0xECC0, 0xEBA0, 0xE9D0, 0xE880, 0xE6F0, 0xE5A0, 0xE3F0, 0xE280, 0xE1C0, 0xDFF0, 0xDF30, 0xDE40, 0xDCD0, + 0xDC60, 0xDB60, 0xDA40, 0xD910, 0xD7D0, 0xD6B0, 0xD560, 0xD430, 0xD2F0, 0xD1F0, 0xD150, 0xD030, 0xCF30, 0xCE60, 0xCD50, 0xCC30, + 0xCB40, 0xC990, 0xC880, 0xC7B0, 0xC700, 0xC5E0, 0xC510, 0xC4A0, 0xC3E0, 0xC2F0, 0xC1B0, 0xC0C0, 0xC060, 0xBFC0, 0xBF00, 0xBEA0, + 0xBD90, 0xBD00, 0xBC20, 0xBB50, 0xBAB0, 0xB970, 0xB910, 0xB830, 0xB770, 0xB6A0, 0xB5C0, 0xB540, 0xB460, 0xB360, 0xB200, 0xB0D0, + 0xB030, 0xAEF0, 0xAD70, 0xAC90, 0xABC0, 0xAAD0, 0xA9A0, 0xA870, 0xA780, 0xA660, 0xA550, 0xA420, 0xA2F0, 0xA250, 0xA160, 0xA040, + 0x9F40, 0x9DE0, 0x9CD0, 0x9BD0, 0x9A80, 0x99D0, 0x9890, 0x97D0, 0x9690, 0x95F0, 0x94C0, 0x9350, 0x9200, 0x90E0, 0x8F90, 0x8E90, + 0x8D80, 0x8CF0, 0x8C70, 0x8BB0, 0x8B60, 0x8AB0, 0x8A50, 0x89B0, 0x8950, 0x88D0, 0x8890, 0x8840, 0x87F0, 0x87C0, 0x8790, 0x8760, + 0x8730, 0x86F0, 0x86D0, 0x8680, 0x86A0, 0x8690, 0x8690, 0x8680, 0x8670, 0x8670, 0x8650, 0x8650, 0x8650, 0x8650, 0x8640, 0x8650, + 0x8660, 0x8640, 0x8650, 0x8640, 0x8640, 0x8680, 0x8660, 0x8640, 0x8640, 0x8660, 0x8640, 0x8640, 0x8650, 0x8660, 0x8660, 0x8660, + 0x8670, 0x8680, 0x8670, 0x8670, 0x8680, 0x8670, 0x8680, 0x8670, 0x8680, 0x8680, 0x8670, 0x8670, 0x8670, 0x8680, 0x8660, 0x8650, + 0x8660, 0x8650, 0x8640, 0x8630, 0x8630, 0x8630, 0x8620, 0x8620, 0x8620, 0x8610, 0x8610, 0x8600, 0x8600, 0x8600, 0x8600, 0x8600, + 0x8610, 0x8630, 0x8600, 0x8600, 0x85F0, 0x85F0, 0x85F0, 0x85F0, 0x85F0, 0x8600, 0x8600, 0x8610, 0x8620, 0x8630, 0x8640, 0x8640, + 0x8640, 0x8650, 0x8650, 0x8670, 0x8680, 0x86A0, 0x86B0, 0x86D0, 0x8710, 0x8700, 0x8720, 0x8730, 0x8760, 0x8790, 0x87B0, 0x87E0, + 0x8800, 0x8810, 0x8850, 0x8860, 0x88B0, 0x8900, 0x8970, 0x8A10, 0x8A70, 0x8AF0, 0x8B90, 0x8C30, 0x8CC0, 0x8D40, 0x8DC0, 0x8E90, + 0x8F00, 0x8F70, 0x9030, 0x9120, 0x9200, 0x92B0, 0x93E0, 0x9450, 0x9510, 0x9600, 0x96C0, 0x9770, 0x98B0, 0x99A0, 0x9AB0, 0x9BC0, + 0x9C80, 0x9D50, 0x9DC0, 0x9E80, 0x9EF0, 0xA030, 0xA130, 0xA210, 0xA2E0, 0xA470, 0xA540, 0xA680, 0xA7A0, 0xA880, 0xA990, 0xAAB0, + 0xAB80, 0xAC80, 0xAD40, 0xAE40, 0xAF20, 0xAFD0, 0xB0E0, 0xB1A0, 0xB2B0, 0xB320, 0xB420, 0xB4C0, 0xB5A0, 0xB610, 0xB6D0, 0xB790, + 0xB830, 0xB8E0, 0xB9A0, 0xBA70, 0xBB40, 0xBC40, 0xBD20, 0xBDB0, 0xBEA0, 0xBF80, 0xBFE0, 0xC020, 0xC0D0, 0xC110, 0xC1B0, 0xC230, + 0xC240, 0xC2C0, 0xC330, 0xC3A0, 0xC440, 0xC4D0, 0xC570, 0xC620, 0xC6E0, 0xC710, 0xC750, 0xC780, 0xC850, 0xC8A0, 0xC910, 0xC970, + 0xC9F0, 0xCA50, 0xCAE0, 0xCB30, 0xCB40, 0xCB70, 0xCBE0, 0xCC70, 0xCCC0, 0xCD60, 0xCD90, 0xCE40, 0xCDD0, 0xCE70, 0xCE90, 0xCE50, + 0xCE80, 0xCEF0, 0xCEF0, 0xCF60, 0xCF70, 0xCF60, 0xCF80, 0xD010, 0xD090, 0xD0E0, 0xD130, 0xD150, 0xD130, 0xD130, 0xD130, 0xD170, + 0xD1B0, 0xD1B0, 0xD1F0, 0xD1B0, 0xD220, 0xD290, 0xD2C0, 0xD2D0, 0xD3A0, 0xD3D0, 0xD3F0, 0xD430, 0xD420, 0xD410, 0xD410, 0xD430, + 0xD460, 0xD440, 0xD440, 0xD430, 0xD3E0, 0xD3E0, 0xD3B0, 0xD3D0, 0xD420, 0xD3D0, 0xD410, 0xD460, 0xD450, 0xD430, 0xD3B0, 0xD400, + 0xD390, 0xD360, 0xD370, 0xD320, 0xD330, 0xD320, 0xD300, 0xD310, 0xD330, 0xD2D0, 0xD2C0, 0xD2C0, 0xD2F0, 0xD250, 0xD270, 0xD1D0, + 0xD1B0, 0xD190, 0xD0B0, 0xD0A0, 0xD030, 0xD000, 0xCFB0, 0xCF60, 0xCF00, 0xCF00, 0xCED0, 0xCE40, 0xCD80, 0xCDC0, 0xCD20, 0xCD80, + 0xCCD0, 0xCC40, 0xCC40, 0xCBB0, 0xCB60, 0xCAF0, 0xCA50, 0xCA30, 0xC9A0, 0xC990, 0xC8F0, 0xC8D0, 0xC8A0, 0xC810, 0xC790, 0xC6E0, + 0xC630, 0xC5C0, 0xC510, 0xC490, 0xC410, 0xC3D0, 0xC350, 0xC2F0, 0xC270, 0xC200, 0xC190, 0xC1A0, 0xC140, 0xC010, 0xBFF0, 0xBF20, + 0xBEE0, 0xBD90, 0xBCE0, 0xBCA0, 0xBC30, 0xBBB0, 0xBB40, 0xBA40, 0xB9C0, 0xB920, 0xB820, 0xB790, 0xB710, 0xB670, 0xB610, 0xB570, + 0xB570, 0xB510, 0xB500, 0xB440, 0xB3F0, 0xB3B0, 0xB2F0, 0xB280, 0xB240, 0xB190, 0xB110, 0xB020, 0xAFF0, 0xAF30, 0xAE50, 0xADE0, + 0xAD80, 0xAD30, 0xAC70, 0xABC0, 0xABA0, 0xAAF0, 0xAB20, 0xAAB0, 0xAA30, 0xAA50, 0xAA50, 0xA9B0, 0xA940, 0xA910, 0xA8C0, 0xA840, + 0xA820, 0xA7E0, 0xA790, 0xA6F0, 0xA710, 0xA630, 0xA5A0, 0xA4C0, 0xA4B0, 0xA450, 0xA430, 0xA400, 0xA3F0, 0xA3B0, 0xA2F0, 0xA280, + 0xA270, 0xA150, 0xA160, 0xA0E0, 0xA0A0, 0xA030, 0xA020, 0xA040, 0xA000, 0x9FB0, 0x9FB0, 0x9F70, 0x9EE0, 0x9EF0, 0x9E90, 0x9E00, + 0x9D50, 0x9D40, 0x9C80, 0x9C40, 0x9C30, 0x9BA0, 0x9B90, 0x9B70, 0x9AC0, 0x9AB0, 0x9A30, 0x99E0, 0x99E0, 0x9970, 0x9960, 0x9970, + 0x9950, 0x9920, 0x9850, 0x9880, 0x9810, 0x97B0, 0x9770, 0x9700, 0x9730, 0x96E0, 0x96C0, 0x9680, 0x9600, 0x95E0, 0x95A0, 0x9580, + 0x9510, 0x94E0, 0x9500, 0x94B0, 0x94E0, 0x94A0, 0x94B0, 0x9470, 0x9430, 0x9440, 0x9400, 0x9430, 0x9400, 0x93D0, 0x9440, 0x9420, + 0x9440, 0x9450, 0x9430, 0x9460, 0x9480, 0x9480, 0x9490, 0x9420, 0x9470, 0x9430, 0x9410, 0x9410, 0x9420, 0x9470, 0x9450, 0x9410, + 0x9470, 0x93F0, 0x9450, 0x94A0, 0x94A0, 0x9460, 0x9490, 0x94B0, 0x94E0, 0x94D0, 0x9510, 0x9520, 0x9530, 0x9550, 0x9590, 0x95C0, + 0x95D0, 0x95C0, 0x9550, 0x9510, 0x9570, 0x95A0, 0x9580, 0x95C0, 0x9650, 0x96F0, 0x96F0, 0x96F0, 0x9700, 0x9700, 0x96F0, 0x9720, + 0x9710, 0x9720, 0x9720, 0x97D0, 0x98A0, 0x98F0, 0x9930, 0x9910, 0x9960, 0x98D0, 0x9890, 0x98B0, 0x9890, 0x98D0, 0x9900, 0x9920, + 0x9960, 0x9940, 0x9A10, 0x9A30, 0x9A60, 0x9A70, 0x9A80, 0x9A80, 0x9A40, 0x9A40, 0x9AC0, 0x9AF0, 0x9B70, 0x9B40, 0x9B30, 0x9B50, + 0x9B60, 0x9B80, 0x9B50, 0x9B30, 0x9BA0, 0x9C00, 0x9CB0, 0x9CD0, 0x9D40, 0x9DC0, 0x9DD0, 0x9E20, 0x9E10, 0x9DC0, 0x9E20, 0x9E60, + 0x9E50, 0x9EB0, 0x9ED0, 0x9EC0, 0x9F10, 0x9ED0, 0x9F60, 0x9F40, 0x9F90, 0x9FD0, 0x9FF0, 0xA030, 0xA050, 0xA110, 0xA120, 0xA170, + 0xA1A0, 0xA1E0, 0xA270, 0xA2A0, 0xA340, 0xA390, 0xA3B0, 0xA420, 0xA470, 0xA480, 0xA4E0, 0xA4C0, 0xA4C0, 0xA4D0, 0xA4C0, 0xA4F0, + 0xA510, 0xA580, 0xA530, 0xA540, 0xA570, 0xA580, 0xA5B0, 0xA5E0, 0xA600, 0xA6E0, 0xA740, 0xA810, 0xA860, 0xA910, 0xA980, 0xAA00, + 0xAA10, 0xAA90, 0xAA70, 0xAAE0, 0xAB60, 0xABA0, 0xAC00, 0xABD0, 0xABB0, 0xABA0, 0xAB80, 0xABA0, 0xABB0, 0xABC0, 0xABF0, 0xAC10, + 0xAC80, 0xAC60, 0xACF0, 0xACE0, 0xACF0, 0xAD00, 0xAD50, 0xAE20, 0xAE40, 0xAED0, 0xAF30, 0xAFA0, 0xAFF0, 0xB030, 0xAFD0, 0xB080, + 0xB050, 0xB060, 0xB0D0, 0xB070, 0xB0F0, 0xB0E0, 0xB160, 0xB1B0, 0xB1B0, 0xB260, 0xB200, 0xB230, 0xB230, 0xB200, 0xB1E0, 0xB230, + 0xB220, 0xB280, 0xB230, 0xB330, 0xB300, 0xB300, 0xB310, 0xB300, 0xB3A0, 0xB390, 0xB380, 0xB3C0, 0xB3B0, 0xB400, 0xB400, 0xB3A0, + 0xB3D0, 0xB3C0, 0xB3C0, 0xB3D0, 0xB3B0, 0xB400, 0xB3A0, 0xB440, 0xB410, 0xB430, 0xB4B0, 0xB4A0, 0xB4D0, 0xB500, 0xB530, 0xB5C0, + 0xB5B0, 0xB660, 0xB670, 0xB630, 0xB650, 0xB5F0, 0xB650, 0xB670, 0xB630, 0xB6C0, 0xB6E0, 0xB710, 0xB770, 0xB780, 0xB7F0, 0xB7C0, + 0xB800, 0xB840, 0xB7F0, 0xB810, 0xB800, 0xB800, 0xB7F0, 0xB7F0, 0xB7D0, 0xB820, 0xB810, 0xB820, 0xB870, 0xB900, 0xB8F0, 0xB8F0, + 0xB9B0, 0xBA20, 0xBAC0, 0xBB50, 0xBB70, 0xBBD0, 0xBBE0, 0xBB80, 0xBB60, 0xBB50, 0xBAC0, 0xBA70, 0xBA60, 0xBA40, 0xBA30, 0xBA50, + 0xBA60, 0xBA90, 0xBA30, 0xBA80, 0xBAE0, 0xBA80, 0xBB10, 0xBB20, 0xBB60, 0xBB60, 0xBB90, 0xBBA0, 0xBBA0, 0xBBD0, 0xBBF0, 0xBC00, + 0xBC70, 0xBCD0, 0xBD70, 0xBDA0, 0xBDB0, 0xBDA0, 0xBD60, 0xBD90, 0xBDB0, 0xBDA0, 0xBE20, 0xBE80, 0xBEE0, 0xBEF0, 0xBED0, 0xBF10, + 0xBF60, 0xBF40, 0xBFD0, 0xC010, 0xC040, 0xC080, 0xC0F0, 0xC110, 0xC140, 0xC170, 0xC1E0, 0xC1B0, 0xC1F0, 0xC220, 0xC280, 0xC2E0, + 0xC2D0, 0xC2C0, 0xC2E0, 0xC2D0, 0xC340, 0xC380, 0xC3C0, 0xC430, 0xC480, 0xC4B0, 0xC4D0, 0xC520, 0xC550, 0xC5E0, 0xC5B0, 0xC600, + 0xC650, 0xC670, 0xC6C0, 0xC6A0, 0xC6B0, 0xC6E0, 0xC6E0, 0xC6D0, 0xC7A0, 0xC780, 0xC7D0, 0xC810, 0xC820, 0xC850, 0xC830, 0xC810, + 0xC830, 0xC810, 0xC840, 0xC820, 0xC830, 0xC830, 0xC860, 0xC840, 0xC890, 0xC8E0, 0xC8A0, 0xC860, 0xC880, 0xC8C0, 0xC8F0, 0xC8F0, + 0xC910, 0xC910, 0xC960, 0xC8F0, 0xC950, 0xC920, 0xC930, 0xC940, 0xC930, 0xC930, 0xC960, 0xC960, 0xC940, 0xC9B0, 0xC990, 0xC980, + 0xC9D0, 0xC9A0, 0xC990, 0xCA00, 0xCA10, 0xCA20, 0xCA10, 0xC9D0, 0xC9E0, 0xC9F0, 0xC9F0, 0xC9F0, 0xC9F0, 0xCA50, 0xCA30, 0xCA00, + 0xC9E0, 0xC9E0, 0xC980, 0xC940, 0xC990, 0xC980, 0xC900, 0xC9B0, 0xC9D0, 0xCA50, 0xCA20, 0xCA30, 0xCAA0, 0xCA50, 0xCAC0, 0xCAA0, + 0xCAE0, 0xCAD0, 0xCAB0, 0xCB40, 0xCB30, 0xCB30, 0xCB00, 0xCAC0, 0xCAB0, 0xCAB0, 0xCA80, 0xCA80, 0xCA80, 0xCA40, 0xC9D0, 0xC9D0, + 0xCA00, 0xC9E0, 0xC9A0, 0xC990, 0xC9F0, 0xCA40, 0xCAA0, 0xCAE0, 0xCAE0, 0xCAE0, 0xCBB0, 0xCBD0, 0xCB70, 0xCC40, 0xCBE0, 0xCC30, + 0xCC40, 0xCBC0, 0xCC50, 0xCC00, 0xCC60, 0xCC90, 0xCC50, 0xCC50, 0xCC20, 0xCC70, 0xCC40, 0xCC20, 0xCC40, 0xCCC0, 0xCD40, 0xCD70, + 0xCD50, 0xCDB0, 0xCDD0, 0xCDD0, 0xCDE0, 0xCDB0, 0xCDE0, 0xCE10, 0xCDF0, 0xCE00, 0xCDA0, 0xCE30, 0xCE70, 0xCEA0, 0xCE80, 0xCE90, + 0xCEC0, 0xCEB0, 0xCEC0, 0xCE60, 0xCE30, 0xCE60, 0xCE70, 0xCE60, 0xCEF0, 0xCE60, 0xCEE0, 0xCED0, 0xCED0, 0xCF20, 0xCF10, 0xCF70, + 0xCF80, 0xCF40, 0xCF70, 0xCF00, 0xCF70, 0xCF80, 0xCF50, 0xD050, 0xD050, 0xD040, 0xD050, 0xD030, 0xD100, 0xD080, 0xD0D0, 0xD100, + 0xD0E0, 0xD130, 0xD100, 0xD140, 0xD160, 0xD190, 0xD1A0, 0xD190, 0xD180, 0xD180, 0xD110, 0xD190, 0xD160, 0xD190, 0xD1A0, 0xD1B0, + 0xD1F0, 0xD210, 0xD1E0, 0xD1E0, 0xD170, 0xD1F0, 0xD1E0, 0xD180, 0xD190, 0xD180, 0xD1B0, 0xD1C0, 0xD190, 0xD1E0, 0xD1C0, 0xD1F0, + 0xD1F0, 0xD1D0, 0xD240, 0xD260, 0xD2F0, 0xD2D0, 0xD2D0, 0xD300, 0xD310, 0xD370, 0xD320, 0xD2F0, 0xD300, 0xD2D0, 0xD310, 0xD300, + 0xD2D0, 0xD320, 0xD310, 0xD370, 0xD360, 0xD360, 0xD380, 0xD3A0, 0xD3C0, 0xD3D0, 0xD3A0, 0xD440, 0xD450, 0xD450, 0xD490, 0xD470, + 0xD4A0, 0xD470, 0xD430, 0xD480, 0xD3E0, 0xD430, 0xD470, 0xD4F0, 0xD500, 0xD540, 0xD580, 0xD500, 0xD530, 0xD520, 0xD4F0, 0xD580, + 0xD520, 0xD560, 0xD550, 0xD570, 0xD580, 0xD5C0, 0xD570, 0xD5A0, 0xD580, 0xD580, 0xD5F0, 0xD570, 0xD640, 0xD5D0, 0xD600, 0xD600, + 0xD5A0, 0xD5D0, 0xD590, 0xD590, 0xD510, 0xD490, 0xD510, 0xD4E0, 0xD4F0, 0xD4A0, 0xD450, 0xD4C0, 0xD500, 0xD520, 0xD520, 0xD4F0, + 0xD580, 0xD5A0, 0xD580, 0xD5C0, 0xD540, 0xD590, 0xD590, 0xD5A0, 0xD580, 0xD4C0, 0xD510, 0xD4D0, 0xD4F0, 0xD4C0, 0xD4C0, 0xD4D0, + 0xD4B0, 0xD480, 0xD490, 0xD480, 0xD490, 0xD480, 0xD4D0, 0xD4E0, 0xD4A0, 0xD480, 0xD470, 0xD490, 0xD430, 0xD3F0, 0xD440, 0xD3C0, + 0xD3D0, 0xD3B0, 0xD320, 0xD390, 0xD380, 0xD370, 0xD340, 0xD2B0, 0xD2C0, 0xD2A0, 0xD280, 0xD250, 0xD250, 0xD290, 0xD270, 0xD260, + 0xD260, 0xD250, 0xD240, 0xD210, 0xD240, 0xD230, 0xD1D0, 0xD1D0, 0xD180, 0xD150, 0xD180, 0xD100, 0xD0D0, 0xD0C0, 0xD0B0, 0xD0A0, + 0xCFA0, 0xCFC0, 0xCF60, 0xCFE0, 0xCFB0, 0xCF60, 0xD010, 0xD000, 0xCFF0, 0xD010, 0xCF70, 0xCF40, 0xCF20, 0xCEA0, 0xCE50, 0xCE90, + 0xCE90, 0xCE20, 0xCDB0, 0xCDF0, 0xCDD0, 0xCD80, 0xCD50, 0xCDB0, 0xCDA0, 0xCD90, 0xCD90, 0xCD00, 0xCCB0, 0xCCF0, 0xCC90, 0xCC70, + 0xCC90, 0xCC50, 0xCC90, 0xCC90, 0xCCD0, 0xCCB0, 0xCD00, 0xCCF0, 0xCCC0, 0xCC60, 0xCC80, 0xCC30, 0xCC20, 0xCB40, 0xCB20, 0xCAD0, + 0xCA30, 0xCAC0, 0xC9F0, 0xC9C0, 0xC960, 0xC950, 0xC9E0, 0xC990, 0xC9B0, 0xC980, 0xC980, 0xC9F0, 0xC9A0, 0xC9D0, 0xC990, 0xC970, + 0xC9A0, 0xC950, 0xC9B0, 0xC970, 0xC940, 0xC930, 0xC920, 0xC930, 0xC940, 0xC890, 0xC890, 0xC840, 0xC810, 0xC870, 0xC840, 0xC860, + 0xC890, 0xC7D0, 0xC820, 0xC830, 0xC890, 0xC860, 0xC850, 0xC8B0, 0xC880, 0xC8B0, 0xC920, 0xC8D0, 0xC990, 0xC940, 0xC950, 0xC910, + 0xC8F0, 0xC8F0, 0xC8F0, 0xC890, 0xC8C0, 0xC880, 0xC890, 0xC8B0, 0xC8A0, 0xC900, 0xC8B0, 0xC8D0, 0xC8E0, 0xC8C0, 0xC8B0, 0xC880, + 0xC8F0, 0xC8F0, 0xC910, 0xC970, 0xC950, 0xC9B0, 0xC9D0, 0xC9D0, 0xCA20, 0xC9F0, 0xCA80, 0xCA80, 0xCAA0, 0xCB40, 0xCB90, 0xCB90, + 0xCBB0, 0xCC40, 0xCBD0, 0xCBE0, 0xCC00, 0xCC30, 0xCBD0, 0xCC30, 0xCBD0, 0xCC80, 0xCC30, 0xCC00, 0xCC70, 0xCC80, 0xCCD0, 0xCCC0, + 0xCCB0, 0xCDA0, 0xCDA0, 0xCE20, 0xCDF0, 0xCD90, 0xCE00, 0xCE00, 0xCE50, 0xCE10, 0xCE10, 0xCE80, 0xCE70, 0xCEE0, 0xCEE0, 0xCF40, + 0xCFD0, 0xD030, 0xD040, 0xD050, 0xD0B0, 0xD070, 0xD080, 0xD0E0, 0xD0E0, 0xD0F0, 0xD150, 0xD140, 0xD0F0, 0xD110, 0xD170, 0xD180, + 0xD160, 0xD150, 0xD170, 0xD1C0, 0xD1C0, 0xD1D0, 0xD1F0, 0xD2A0, 0xD290, 0xD2E0, 0xD300, 0xD310, 0xD350, 0xD390, 0xD3A0, 0xD3F0, + 0xD3C0, 0xD430, 0xD400, 0xD440, 0xD450, 0xD420, 0xD470, 0xD470, 0xD470, 0xD4A0, 0xD490, 0xD4F0, 0xD530, 0xD520, 0xD510, 0xD520, + 0xD550, 0xD5C0, 0xD5B0, 0xD620, 0xD660, 0xD650, 0xD670, 0xD660, 0xD660, 0xD5F0, 0xD610, 0xD640, 0xD630, 0xD6B0, 0xD690, 0xD6E0, + 0xD740, 0xD710, 0xD7B0, 0xD790, 0xD780, 0xD7D0, 0xD730, 0xD7A0, 0xD7C0, 0xD7E0, 0xD7E0, 0xD830, 0xD870, 0xD8C0, 0xD860, 0xD870, + 0xD810, 0xD7A0, 0xD790, 0xD780, 0xD760, 0xD780, 0xD740, 0xD790, 0xD7D0, 0xD7C0, 0xD790, 0xD750, 0xD730, 0xD720, 0xD7D0, 0xD780, + 0xD7D0, 0xD7C0, 0xD7B0, 0xD7F0, 0xD850, 0xD850, 0xD8C0, 0xD8D0, 0xD920, 0xD960, 0xD970, 0xD930, 0xD9F0, 0xDA00, 0xDA20, 0xDA30, + 0xDA10, 0xDA10, 0xD9E0, 0xD9B0, 0xDA00, 0xDA20, 0xD9E0, 0xDA30, 0xDA20, 0xDA40, 0xDA40, 0xDA50, 0xDA60, 0xDA60, 0xDAB0, 0xDA80, + 0xDAF0, 0xDAE0, 0xDB10, 0xDB30, 0xDB20, 0xDB50, 0xDB40, 0xDBB0, 0xDC50, 0xDC20, 0xDCD0, 0xDD20, 0xDCE0, 0xDCD0, 0xDD40, 0xDD20, + 0xDD20, 0xDD20, 0xDCF0, 0xDCB0, 0xDD00, 0xDCC0, 0xDCC0, 0xDC70, 0xDC90, 0xDCA0, 0xDC50, 0xDC90, 0xDCB0, 0xDC70, 0xDC70, 0xDC70, + 0xDC80, 0xDC90, 0xDC50, 0xDC40, 0xDC70, 0xDC30, 0xDC50, 0xDCA0, 0xDCD0, 0xDD10, 0xDD70, 0xDD80, 0xDD80, 0xDE00, 0xDE00, 0xDE90, + 0xDE50, 0xDEC0, 0xDE60, 0xDE50, 0xDE70, 0xDE80, 0xDE20, 0xDE50, 0xDEA0, 0xDEC0, 0xDEC0, 0xDED0, 0xDEE0, 0xDEF0, 0xDF10, 0xDEA0, + 0xDE60, 0xDEA0, 0xDEE0, 0xDEF0, 0xDF60, 0xDF40, 0xDFA0, 0xDFD0, 0xE000, 0xE020, 0xE030, 0xE080, 0xE0A0, 0xE0C0, 0xE0C0, 0xE110, + 0xE150, 0xE170, 0xE150, 0xE130, 0xE150, 0xE0E0, 0xE100, 0xE110, 0xE0C0, 0xE0F0, 0xE130, 0xE1C0, 0xE1F0, 0xE250, 0xE290, 0xE2A0, + 0xE350, 0xE340, 0xE310, 0xE330, 0xE390, 0xE3A0, 0xE3A0, 0xE3D0, 0xE350, 0xE340, 0xE2F0, 0xE2F0, 0xE2D0, 0xE2E0, 0xE2E0, 0xE2C0, + 0xE300, 0xE360, 0xE340, 0xE340, 0xE340, 0xE380, 0xE390, 0xE390, 0xE3B0, 0xE3E0, 0xE460, 0xE3D0, 0xE3F0, 0xE450, 0xE440, 0xE480, + 0xE4D0, 0xE530, 0xE5C0, 0xE650, 0xE6F0, 0xE7A0, 0xE7E0, 0xE880, 0xE870, 0xE870, 0xE830, 0xE8B0, 0xE860, 0xE860, 0xE870, 0xE7D0, + 0xE7E0, 0xE7E0, 0xE790, 0xE7E0, 0xE7B0, 0xE7D0, 0xE870, 0xE830, 0xE900, 0xE8B0, 0xE870, 0xE8C0, 0xE8A0, 0xE910, 0xE920, 0xE940, + 0xE9B0, 0xE950, 0xE9F0, 0xE9D0, 0xE950, 0xE960, 0xE940, 0xE940, 0xE940, 0xE930, 0xE9A0, 0xE9A0, 0xE9B0, 0xE9A0, 0xE9C0, 0xEA10, + 0xEA20, 0xEA60, 0xEA50, 0xEA80, 0xEB20, 0xEB50, 0xEBF0, 0xEBF0, 0xEC40, 0xEC50, 0xEC00, 0xEBE0, 0xEBA0, 0xEBB0, 0xEBE0, 0xEC20, + 0xEC20, 0xEC70, 0xECA0, 0xEC40, 0xECA0, 0xEC50, 0xEC70, 0xEC70, 0xECD0, 0xECB0, 0xECD0, 0xED60, 0xED00, 0xED90, 0xED80, 0xED90, + 0xEDB0, 0xED60, 0xEDC0, 0xED90, 0xED70, 0xEDA0, 0xEDA0, 0xEDF0, 0xEDF0, 0xEDB0, 0xEE00, 0xEE20, 0xEE70, 0xEEC0, 0xEE90, 0xEF30, + 0xEF30, 0xEF90, 0xEFF0, 0xF010, 0xF050, 0xF080, 0xF0C0, 0xF090, 0xF070, 0xF070, 0xF060, 0xF010, 0xF090, 0xF060, 0xF020, 0xF000, + 0xF020, 0xEFF0, 0xEFE0, 0xF050, 0xEFF0, 0xEFE0, 0xF010, 0xF030, 0xF0A0, 0xF0A0, 0xF090, 0xF060, 0xF0A0, 0xF0F0, 0xF150, 0xF130, + 0xF1B0, 0xF1A0, 0xF250, 0xF250, 0xF1A0, 0xF1C0, 0xF220, 0xF250, 0xF290, 0xF210, 0xF2B0, 0xF210, 0xF260, 0xF210, 0xF1D0, 0xF220, + 0xF220, 0xF250, 0xF280, 0xF250, 0xF2E0, 0xF350, 0xF3B0, 0xF3E0, 0xF3C0, 0xF400, 0xF3B0, 0xF3F0, 0xF420, 0xF3C0, 0xF470, 0xF430, + 0xF3E0, 0xF420, 0xF420, 0xF470, 0xF470, 0xF4A0, 0xF480, 0xF440, 0xF480, 0xF470, 0xF440, 0xF4A0, 0xF480, 0xF4E0, 0xF540, 0xF550, + 0xF5E0, 0xF5B0, 0xF5F0, 0xF5D0, 0xF5B0, 0xF5E0, 0xF5C0, 0xF630, 0xF680, 0xF600, 0xF680, 0xF6B0, 0xF6B0, 0xF680, 0xF650, 0xF670, + 0xF640, 0xF680, 0xF670, 0xF660, 0xF600, 0xF630, 0xF660, 0xF640, 0xF6C0, 0xF6B0, 0xF6C0, 0xF750, 0xF760, 0xF760, 0xF750, 0xF700, + 0xF700, 0xF720, 0xF710, 0xF730, 0xF720, 0xF760, 0xF710, 0xF760, 0xF730, 0xF770, 0xF750, 0xF7A0, 0xF7B0, 0xF7D0, 0xF7A0, 0xF800, + 0xF7F0, 0xF850, 0xF810, 0xF800, 0xF790, 0xF790, 0xF770, 0xF7A0, 0xF730, 0xF7A0, 0xF7A0, 0xF790, 0xF880, 0xF890, 0xF900, 0xF910, + 0xF890, 0xF8E0, 0xF840, 0xF800, 0xF860, 0xF870, 0xF8E0, 0xF900, 0xF900, 0xF920, 0xF8D0, 0xF8F0, 0xF880, 0xF8E0, 0xF890, 0xF860, + 0xF900, 0xF900, 0xF8F0, 0xF900, 0xF820, 0xF890, 0xF870, 0xF850, 0xF860, 0xF840, 0xF8D0, 0xF8D0, 0xF930, 0xF960, 0xF940, 0xF950, + 0xF950, 0xF970, 0xF9C0, 0xF990, 0xFA30, 0xFA20, 0xF9C0, 0xFA30, 0xFA10, 0xFA60, 0xFA20, 0xF9C0, 0xF9E0, 0xF980, 0xF990, 0xF9B0, + 0xF960, 0xFA20, 0xFA00, 0xF9E0, 0xF9B0, 0xF970, 0xF950, 0xF960, 0xF9A0, 0xF950, 0xF950, 0xF9F0, 0xFA60, 0xFA40, 0xFA80, 0xFA50, + 0xFB40, 0xFB00, 0xFB20, 0xFB40, 0xFA40, 0xFAB0, 0xFAA0, 0xFAA0, 0xFA70, 0xFA50, 0xFAD0, 0xFB00, 0xFB20, 0xFB50, 0xFB30, 0xFB60, + 0xFB40, 0xFB70, 0xFB30, 0xFB00, 0xFB00, 0xFB10, 0xFA90, 0xFAB0, 0xFAA0, 0xFB40, 0xFB90, 0xFB60, 0xFBD0, 0xFC30, 0xFC30, 0xFC20, + 0xFC00, 0xFBF0, 0xFBF0, 0xFC00, 0xFC10, 0xFB90, 0xFBE0, 0xFBC0, 0xFB90, 0xFB90, 0xFB60, 0xFB50, 0xFB20, 0xFB30, 0xFB80, 0xFB90, +}; + +#endif // MIC_BLOW_H diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.ui b/src/frontend/qt_sdl/AudioSettingsDialog.ui index b6c215e0..c4e993ee 100644 --- a/src/frontend/qt_sdl/AudioSettingsDialog.ui +++ b/src/frontend/qt_sdl/AudioSettingsDialog.ui @@ -95,7 +95,7 @@ <html><head/><body><p>Noise will be forwarded to the emulated microphone, simulating blowing into the microphone.</p></body></html> - White noise + Blow noise diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index caa78e9f..ffd7d17f 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -12,6 +12,7 @@ SET(SOURCES_QT_SDL ../Util_ROM.cpp ../Util_Audio.cpp ../FrontendUtil.h + ../mic_blow.h ../../../melon.qrc ) From 8f9369beebf60f3b10d75f50507b194f2ccdaceb Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 21 May 2020 18:43:07 +0200 Subject: [PATCH 068/105] add screen layout system --- src/frontend/FrontendUtil.h | 26 +++ src/frontend/Util_Video.cpp | 334 +++++++++++++++++++++++++++++ src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/main.cpp | 213 ++++++++++++++---- src/frontend/qt_sdl/main.h | 17 +- 5 files changed, 545 insertions(+), 46 deletions(-) create mode 100644 src/frontend/Util_Video.cpp diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 6a6f8ea4..1fd73296 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -89,6 +89,32 @@ bool SaveState(const char* filename); void UndoStateLoad(); +// setup the display layout based on the provided display size and parameters +// * screenWidth/screenHeight: size of the host display +// * screenLayout: how the DS screens are laid out +// 0 = natural (top screen above bottom screen always) +// 1 = vertical +// 2 = horizontal +// * rotation: angle at which the DS screens are presented: 0/1/2/3 = 0/90/180/270 +// * sizing: how the display size is shared between the two screens +// 0 = even (both screens get same size) +// 1 = emphasize top screen (make top screen as big as possible, fit bottom screen in remaining space) +// 2 = emphasize bottom screen +// * screenGap: size of the gap between the two screens +// * integerScale: force screens to be scaled up at integer scaling factors +void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale); + +// get a 2x3 transform matrix for the given screen (0=top, 1=bottom) +// note: the transform assumes an origin point at the top left of the display, +// X going left and Y going down +// for each screen the source coordinates should be (0,0) and (256,192) +float* GetScreenTransform(int screen); + +// de-transform the provided host display coordinates to get coordinates +// on the bottom screen +void GetTouchCoords(int& x, int& y); + + // initialize the audio utility void Init_Audio(int outputfreq); diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp new file mode 100644 index 00000000..cd4e21c0 --- /dev/null +++ b/src/frontend/Util_Video.cpp @@ -0,0 +1,334 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include +#include +#include + +#include "FrontendUtil.h" + + +namespace Frontend +{ + +float TopScreenMtx[6]; +float BotScreenMtx[6]; +float TouchMtx[6]; + + +void M23_Identity(float* m) +{ + m[0] = 1; m[1] = 0; + m[2] = 0; m[3] = 1; + m[4] = 0; m[5] = 0; +} + +void M23_Scale(float* m, float s) +{ + m[0] *= s; m[1] *= s; + m[2] *= s; m[3] *= s; + m[4] *= s; m[5] *= s; +} + +void M23_RotateFast(float* m, int angle) +{ + if (angle == 0) return; + + float temp[4]; memcpy(temp, m, sizeof(float)*4); + + switch (angle) + { + case 1: // 90 + m[0] = temp[2]; + m[1] = temp[3]; + m[2] = -temp[0]; + m[3] = -temp[1]; + break; + + case 2: // 180 + m[0] = -temp[0]; + m[1] = -temp[1]; + m[2] = -temp[2]; + m[3] = -temp[3]; + break; + + case 3: // 270 + m[0] = -temp[2]; + m[1] = -temp[3]; + m[2] = temp[0]; + m[3] = temp[1]; + break; + } +} + +void M23_Translate(float* m, float tx, float ty) +{ + m[4] += tx; + m[5] += ty; +} + +void M23_Multiply(float* m, float* _a, float* _b) +{ + float a[6]; memcpy(a, _a, 6*sizeof(float)); + float b[6]; memcpy(b, _b, 6*sizeof(float)); + + m[0] = (a[0] * b[0]) + (a[2] * b[1]); + m[1] = (a[1] * b[0]) + (a[3] * b[1]); + + m[2] = (a[0] * b[2]) + (a[2] * b[3]); + m[3] = (a[1] * b[2]) + (a[3] * b[3]); + + m[4] = (a[0] * b[4]) + (a[2] * b[5]) + a[4]; + m[5] = (a[1] * b[4]) + (a[3] * b[5]) + a[5]; +} + +void M23_Transform(float* m, float& x, float& y) +{ + float vx = x; + float vy = y; + + x = (vx * m[0]) + (vy * m[2]) + m[4]; + y = (vx * m[1]) + (vy * m[3]) + m[5]; +} + + +void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale) +{ + float refpoints[4][2] = + { + {0, 0}, {256, 192}, + {0, 0}, {256, 192} + }; + + int layout = screenLayout == 0 + ? ((rotation % 2 == 0) ? 0 : 1) + : screenLayout - 1; + + float botScale = 1; + float botTrans[4] = {0}; + + M23_Identity(TopScreenMtx); + M23_Identity(BotScreenMtx); + + M23_Translate(TopScreenMtx, -256/2, -192/2); + M23_Translate(BotScreenMtx, -256/2, -192/2); + + // rotation + { + float rotmtx[6]; + M23_Identity(rotmtx); + + M23_RotateFast(rotmtx, rotation); + M23_Multiply(TopScreenMtx, rotmtx, TopScreenMtx); + M23_Multiply(BotScreenMtx, rotmtx, BotScreenMtx); + + M23_Transform(TopScreenMtx, refpoints[0][0], refpoints[0][1]); + M23_Transform(TopScreenMtx, refpoints[1][0], refpoints[1][1]); + M23_Transform(BotScreenMtx, refpoints[2][0], refpoints[2][1]); + M23_Transform(BotScreenMtx, refpoints[3][0], refpoints[3][1]); + } + + // move screens apart + { + int idx = layout == 0 ? 1 : 0; + float offset = + (((layout == 0 && (rotation % 2 == 0)) || (layout == 1 && (rotation % 2 == 1)) + ? 192.f : 256.f) + + screenGap) / 2.f; + if (rotation == 1 || rotation == 2) + offset *= -1.f; + + M23_Translate(TopScreenMtx, (idx==0)?-offset:0, (idx==1)?-offset:0); + M23_Translate(BotScreenMtx, (idx==0)?offset:0, (idx==1)?offset:0); + + refpoints[0][idx] -= offset; + refpoints[1][idx] -= offset; + refpoints[2][idx] += offset; + refpoints[3][idx] += offset; + + botTrans[idx] = offset; + } + + // scale + { + if (sizing == 0) + { + float minX = refpoints[0][0], maxX = minX; + float minY = refpoints[0][1], maxY = minY; + + for (int i = 1; i < 4; i++) + { + minX = std::min(minX, refpoints[i][0]); + minY = std::min(minY, refpoints[i][1]); + maxX = std::max(maxX, refpoints[i][0]); + maxY = std::max(maxY, refpoints[i][1]); + } + + float hSize = maxX - minX; + float vSize = maxY - minY; + + // scale evenly + float scale = std::min(screenWidth / hSize, screenHeight / vSize); + + if (integerScale) + scale = floor(scale); + + M23_Scale(TopScreenMtx, scale); + M23_Scale(BotScreenMtx, scale); + + for (int i = 0; i < 4; i++) + { + refpoints[i][0] *= scale; + refpoints[i][1] *= scale; + } + + botScale = scale; + } + else + { + int primOffset = (sizing == 1) ? 0 : 2; + int secOffset = (sizing == 1) ? 2 : 0; + float* primMtx = (sizing == 1) ? TopScreenMtx : BotScreenMtx; + float* secMtx = (sizing == 1) ? BotScreenMtx : TopScreenMtx; + + float primMinX = refpoints[primOffset][0], primMaxX = primMinX; + float primMinY = refpoints[primOffset][1], primMaxY = primMinY; + float secMinX = refpoints[secOffset][0], secMaxX = secMinX; + float secMinY = refpoints[secOffset][1], secMaxY = secMinY; + + primMinX = std::min(primMinX, refpoints[primOffset+1][0]); + primMinY = std::min(primMinY, refpoints[primOffset+1][1]); + primMaxX = std::max(primMaxX, refpoints[primOffset+1][0]); + primMaxY = std::max(primMaxY, refpoints[primOffset+1][1]); + + secMinX = std::min(secMinX, refpoints[secOffset+1][0]); + secMinY = std::min(secMinY, refpoints[secOffset+1][1]); + secMaxX = std::max(secMaxX, refpoints[secOffset+1][0]); + secMaxY = std::max(secMaxY, refpoints[secOffset+1][1]); + + float primHSize = layout == 1 ? std::max(primMaxX, -primMinX) : primMaxX - primMinX; + float primVSize = layout == 0 ? std::max(primMaxY, -primMinY) : primMaxY - primMinY; + + float secHSize = layout == 1 ? std::max(secMaxX, -secMinX) : secMaxX - secMinX; + float secVSize = layout == 0 ? std::max(secMaxY, -secMinY) : secMaxY - secMinY; + + float primScale = std::min(screenWidth / primHSize, screenHeight / primVSize); + float secScale = 1.f; + + if (layout == 0) + { + if (screenHeight - primVSize * primScale < secVSize) + primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize); + else + secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize); + } + else + { + if (screenWidth - primHSize * primScale < secHSize) + primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize); + else + secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize); + } + + if (integerScale) + { + primScale = floor(primScale); + secScale = floor(secScale); + } + + M23_Scale(primMtx, primScale); + M23_Scale(secMtx, secScale); + + refpoints[primOffset+0][0] *= primScale; + refpoints[primOffset+0][1] *= primScale; + refpoints[primOffset+1][0] *= primScale; + refpoints[primOffset+1][1] *= primScale; + refpoints[secOffset+0][0] *= secScale; + refpoints[secOffset+0][1] *= secScale; + refpoints[secOffset+1][0] *= secScale; + refpoints[secOffset+1][1] *= secScale; + + botScale = (sizing == 1) ? secScale : primScale; + } + } + + // position + { + float minX = refpoints[0][0], maxX = minX; + float minY = refpoints[0][1], maxY = minY; + + for (int i = 1; i < 4; i++) + { + minX = std::min(minX, refpoints[i][0]); + minY = std::min(minY, refpoints[i][1]); + maxX = std::max(maxX, refpoints[i][0]); + maxY = std::max(maxY, refpoints[i][1]); + } + + float width = maxX - minX; + float height = maxY - minY; + + float tx = (screenWidth/2) - (width/2) - minX; + float ty = (screenHeight/2) - (height/2) - minY; + + M23_Translate(TopScreenMtx, tx, ty); + M23_Translate(BotScreenMtx, tx, ty); + + botTrans[2] = tx; botTrans[3] = ty; + } + + // prepare a 'reverse' matrix for the touchscreen + // this matrix undoes the transforms applied to the bottom screen + // and can be used to calculate touchscreen coords from host screen coords + { + M23_Identity(TouchMtx); + + M23_Translate(TouchMtx, -botTrans[2], -botTrans[3]); + M23_Scale(TouchMtx, 1.f / botScale); + M23_Translate(TouchMtx, -botTrans[0], -botTrans[1]); + + float rotmtx[6]; + M23_Identity(rotmtx); + M23_RotateFast(rotmtx, (4-rotation) & 3); + M23_Multiply(TouchMtx, rotmtx, TouchMtx); + + M23_Translate(TouchMtx, 256/2, 192/2); + } +} + +float* GetScreenTransform(int screen) +{ + if (screen == 0) return TopScreenMtx; + else return BotScreenMtx; +} + +void GetTouchCoords(int& x, int& y) +{ + float vx = x; + float vy = y; + + M23_Transform(TouchMtx, vx, vy); + + x = (int)vx; + y = (int)vy; +} + +} + diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index ffd7d17f..7bc81f0a 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -10,6 +10,7 @@ SET(SOURCES_QT_SDL PlatformConfig.cpp ../Util_ROM.cpp + ../Util_Video.cpp ../Util_Audio.cpp ../FrontendUtil.h ../mic_blow.h diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 245324f6..0d10378e 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -62,6 +62,8 @@ bool RunningSomething; MainWindow* mainWindow; EmuThread* emuThread; +int autoScreenSizing = 0; + SDL_AudioDeviceID audioDevice; int audioFreq; SDL_cond* audioSync; @@ -250,16 +252,19 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger())); connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); + connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged())); } void EmuThread::run() { + u32 mainScreenPos[3]; + NDS::Init(); - /*MainScreenPos[0] = 0; - MainScreenPos[1] = 0; - MainScreenPos[2] = 0; - AutoScreenSizing = 0;*/ + mainScreenPos[0] = 0; + mainScreenPos[1] = 0; + mainScreenPos[2] = 0; + autoScreenSizing = 0; /*if (Screen_UseGL) { @@ -333,14 +338,14 @@ void EmuThread::run() }*/ // auto screen layout - /*{ - MainScreenPos[2] = MainScreenPos[1]; - MainScreenPos[1] = MainScreenPos[0]; - MainScreenPos[0] = NDS::PowerControl9 >> 15; + { + mainScreenPos[2] = mainScreenPos[1]; + mainScreenPos[1] = mainScreenPos[0]; + mainScreenPos[0] = NDS::PowerControl9 >> 15; int guess; - if (MainScreenPos[0] == MainScreenPos[2] && - MainScreenPos[0] != MainScreenPos[1]) + if (mainScreenPos[0] == mainScreenPos[2] && + mainScreenPos[0] != mainScreenPos[1]) { // constant flickering, likely displaying 3D on both screens // TODO: when both screens are used for 2D only...??? @@ -348,18 +353,18 @@ void EmuThread::run() } else { - if (MainScreenPos[0] == 1) + if (mainScreenPos[0] == 1) guess = 1; else guess = 2; } - if (guess != AutoScreenSizing) + if (guess != autoScreenSizing) { - AutoScreenSizing = guess; - SetupScreenRects(WindowWidth, WindowHeight); + autoScreenSizing = guess; + emit screenLayoutChange(); } - }*/ + } // emulate u32 nlines = NDS::RunFrame(); @@ -540,6 +545,9 @@ MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) screen[0] = new QImage(256, 192, QImage::Format_RGB32); screen[1] = new QImage(256, 192, QImage::Format_RGB32); + screenTrans[0].reset(); + screenTrans[1].reset(); + touching = false; } @@ -549,6 +557,64 @@ MainWindowPanel::~MainWindowPanel() delete screen[1]; } +void MainWindowPanel::ensureProperMinSize() +{ + bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3); + int gap = Config::ScreenGap; + + int w = 256; + int h = 192; + + if (Config::ScreenLayout == 0) // natural + { + if (isHori) + setMinimumSize(h+gap+h, w); + else + setMinimumSize(w, h+gap+h); + } + else if (Config::ScreenLayout == 1) // vertical + { + if (isHori) + setMinimumSize(h, w+gap+w); + else + setMinimumSize(w, h+gap+h); + } + else // horizontal + { + if (isHori) + setMinimumSize(h+gap+h, w); + else + setMinimumSize(w+gap+w, h); + } +} + +void MainWindowPanel::setupScreenLayout() +{ + int w = width(); + int h = height(); + float* mtx; + + int sizing = Config::ScreenSizing; + if (sizing == 3) sizing = autoScreenSizing; + + Frontend::SetupScreenLayout(w, h, + Config::ScreenLayout, + Config::ScreenRotation, + sizing, + Config::ScreenGap, + Config::IntegerScaling != 0); + + mtx = Frontend::GetScreenTransform(0); + screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f, + mtx[2], mtx[3], 0.f, + mtx[4], mtx[5], 1.f); + + mtx = Frontend::GetScreenTransform(1); + screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f, + mtx[2], mtx[3], 0.f, + mtx[4], mtx[5], 1.f); +} + void MainWindowPanel::paintEvent(QPaintEvent* event) { QPainter painter(this); @@ -562,27 +628,18 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) memcpy(screen[0]->scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4); memcpy(screen[1]->scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4); - QRect src = QRect(0, 0, 256, 192); + QRect screenrc = QRect(0, 0, 256, 192); - QRect dstTop = QRect(0, 0, 256, 192); // TODO - QRect dstBot = QRect(0, 192, 256, 192); // TODO + painter.setTransform(screenTrans[0]); + painter.drawImage(screenrc, *screen[0]); - painter.drawImage(dstTop, *screen[0]); - painter.drawImage(dstBot, *screen[1]); + painter.setTransform(screenTrans[1]); + painter.drawImage(screenrc, *screen[1]); } - -void MainWindowPanel::transformTSCoords(int& x, int& y) +void MainWindowPanel::resizeEvent(QResizeEvent* event) { - // TODO: actual screen de-transform taking screen layout/rotation/etc into account - - y -= 192; - - // clamp to screen range - if (x < 0) x = 0; - else if (x > 255) x = 255; - if (y < 0) y = 0; - else if (y > 191) y = 191; + setupScreenLayout(); } void MainWindowPanel::mousePressEvent(QMouseEvent* event) @@ -593,11 +650,11 @@ void MainWindowPanel::mousePressEvent(QMouseEvent* event) int x = event->pos().x(); int y = event->pos().y(); - if (x >= 0 && x < 256 && y >= 192 && y < 384) + Frontend::GetTouchCoords(x, y); + + if (x >= 0 && x < 256 && y >= 0 && y < 192) { touching = true; - - transformTSCoords(x, y); NDS::TouchScreen(x, y); } } @@ -623,10 +680,22 @@ void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) int x = event->pos().x(); int y = event->pos().y(); - transformTSCoords(x, y); + Frontend::GetTouchCoords(x, y); + + // clamp to screen range + if (x < 0) x = 0; + else if (x > 255) x = 255; + if (y < 0) y = 0; + else if (y > 191) y = 191; + NDS::TouchScreen(x, y); } +void MainWindowPanel::onScreenLayoutChanged() +{ + setupScreenLayout(); +} + MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { @@ -750,7 +819,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) int data = i*90; actScreenRotation[i] = submenu->addAction(QString("%1°").arg(data)); actScreenRotation[i]->setActionGroup(grpScreenRotation); - actScreenRotation[i]->setData(QVariant(data)); + actScreenRotation[i]->setData(QVariant(i)); actScreenRotation[i]->setCheckable(true); } @@ -834,8 +903,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) panel = new MainWindowPanel(this); setCentralWidget(panel); - panel->setMinimumSize(256, 384); + panel->ensureProperMinSize(); + resize(Config::WindowWidth, Config::WindowHeight); for (int i = 0; i < 9; i++) { @@ -877,6 +947,16 @@ MainWindow::~MainWindow() { } +void MainWindow::resizeEvent(QResizeEvent* event) +{ + int w = event->size().width(); + int h = event->size().height(); + + Config::WindowWidth = w; + Config::WindowHeight = h; + + // TODO: detect when the window gets maximized! +} void MainWindow::keyPressEvent(QKeyEvent* event) { @@ -1264,32 +1344,79 @@ void MainWindow::onChangeSavestateSRAMReloc(bool checked) void MainWindow::onChangeScreenSize() { - // + int factor = ((QAction*)sender())->data().toInt(); + + bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3); + int gap = Config::ScreenGap; + + int w = 256*factor; + int h = 192*factor; + + QSize diff = size() - panel->size(); + + if (Config::ScreenLayout == 0) // natural + { + if (isHori) + resize(QSize(h+gap+h, w) + diff); + else + resize(QSize(w, h+gap+h) + diff); + } + else if (Config::ScreenLayout == 1) // vertical + { + if (isHori) + resize(QSize(h, w+gap+w) + diff); + else + resize(QSize(w, h+gap+h) + diff); + } + else // horizontal + { + if (isHori) + resize(QSize(h+gap+h, w) + diff); + else + resize(QSize(w+gap+w, h) + diff); + } } void MainWindow::onChangeScreenRotation(QAction* act) { - // + int rot = act->data().toInt(); + Config::ScreenRotation = rot; + + panel->ensureProperMinSize(); + panel->setupScreenLayout(); } void MainWindow::onChangeScreenGap(QAction* act) { - // + int gap = act->data().toInt(); + Config::ScreenGap = gap; + + panel->ensureProperMinSize(); + panel->setupScreenLayout(); } void MainWindow::onChangeScreenLayout(QAction* act) { - // + int layout = act->data().toInt(); + Config::ScreenLayout = layout; + + panel->ensureProperMinSize(); + panel->setupScreenLayout(); } void MainWindow::onChangeScreenSizing(QAction* act) { - // + int sizing = act->data().toInt(); + Config::ScreenSizing = sizing; + + panel->setupScreenLayout(); } void MainWindow::onChangeIntegerScaling(bool checked) { - // + Config::IntegerScaling = checked?1:0; + + panel->setupScreenLayout(); } void MainWindow::onChangeScreenFiltering(bool checked) diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 7051a088..2d14eeac 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -54,6 +54,8 @@ signals: void windowLimitFPSChange(); + void screenLayoutChange(); + private: volatile int EmuStatus; int PrevEmuStatus; @@ -69,18 +71,25 @@ public: explicit MainWindowPanel(QWidget* parent); ~MainWindowPanel(); + void ensureProperMinSize(); + void setupScreenLayout(); + protected: void paintEvent(QPaintEvent* event) override; + void resizeEvent(QResizeEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; +private slots: + void onScreenLayoutChanged(); + private: QImage* screen[2]; + QTransform screenTrans[2]; bool touching; - - void transformTSCoords(int& x, int& y); }; @@ -93,6 +102,8 @@ public: ~MainWindow(); protected: + void resizeEvent(QResizeEvent* event) override; + void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; @@ -138,9 +149,9 @@ private slots: private: QString loadErrorStr(int error); +public: MainWindowPanel* panel; -public: QAction* actOpenROM; QAction* actBootFirmware; QAction* actSaveState[9]; From 5dcf57e86dc8e768d33406fb446f25bf186eef4d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 21 May 2020 18:49:34 +0200 Subject: [PATCH 069/105] add screen filtering --- src/frontend/qt_sdl/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 0d10378e..36a3b8eb 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -628,6 +628,8 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) memcpy(screen[0]->scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4); memcpy(screen[1]->scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4); + painter.setRenderHint(QPainter::SmoothPixmapTransform, Config::ScreenFilter!=0); + QRect screenrc = QRect(0, 0, 256, 192); painter.setTransform(screenTrans[0]); From ffd9c61bf79852f2364166c4770719146500f4b9 Mon Sep 17 00:00:00 2001 From: RSDuck Date: Thu, 21 May 2020 19:45:33 +0200 Subject: [PATCH 070/105] fix screen layout with emphasis --- src/frontend/Util_Video.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp index cd4e21c0..0f5ff667 100644 --- a/src/frontend/Util_Video.cpp +++ b/src/frontend/Util_Video.cpp @@ -235,14 +235,14 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int if (layout == 0) { if (screenHeight - primVSize * primScale < secVSize) - primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize); + primScale = std::min(screenWidth / primHSize, (screenHeight - secVSize) / primVSize); else secScale = std::min((screenHeight - primVSize * primScale) / secVSize, screenWidth / secHSize); } else { if (screenWidth - primHSize * primScale < secHSize) - primScale = std::min((screenWidth - secHSize) / primHSize, (screenHeight - secVSize) / primVSize); + primScale = std::min((screenWidth - secHSize) / primHSize, screenHeight / primVSize); else secScale = std::min((screenWidth - primHSize * primScale) / secHSize, screenHeight / secVSize); } From f69f3fcb7a6f5eabe07de3db58409aee036348ea Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 22 May 2020 13:54:29 +0200 Subject: [PATCH 071/105] * safer window update * only do auto screen sizing if needed --- src/frontend/qt_sdl/main.cpp | 9 ++++++--- src/frontend/qt_sdl/main.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 36a3b8eb..922206fc 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -247,6 +247,8 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) EmuRunning = 2; RunningSomething = false; + connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(update())); + //connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(repaint())); connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); @@ -338,6 +340,7 @@ void EmuThread::run() }*/ // auto screen layout + if (Config::ScreenSizing == 3) { mainScreenPos[2] = mainScreenPos[1]; mainScreenPos[1] = mainScreenPos[0]; @@ -381,7 +384,7 @@ void EmuThread::run() uiGLEnd(GLContext); } uiAreaQueueRedrawAll(MainDrawArea);*/ - mainWindow->update(); + emit windowUpdate(); bool fastforward = Input::HotkeyDown(HK_FastForward); @@ -461,7 +464,7 @@ void EmuThread::run() uiGLEnd(GLContext); } uiAreaQueueRedrawAll(MainDrawArea);*/ - mainWindow->update(); + emit windowUpdate(); //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); @@ -630,7 +633,7 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) painter.setRenderHint(QPainter::SmoothPixmapTransform, Config::ScreenFilter!=0); - QRect screenrc = QRect(0, 0, 256, 192); + QRect screenrc(0, 0, 256, 192); painter.setTransform(screenTrans[0]); painter.drawImage(screenrc, *screen[0]); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 2d14eeac..c0dc465c 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -45,6 +45,7 @@ public: bool emuIsRunning(); signals: + void windowUpdate(); void windowTitleChange(QString title); void windowEmuStart(); From 16252a85e70feaa1bd10312a357ac74bd677ade3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 24 May 2020 23:16:56 +0200 Subject: [PATCH 072/105] separate screen handling shit to a specialized class --- src/frontend/FrontendUtil.h | 5 +- src/frontend/Util_Video.cpp | 6 +- src/frontend/qt_sdl/main.cpp | 204 ++++++++++++++++++++--------------- src/frontend/qt_sdl/main.h | 22 +++- 4 files changed, 140 insertions(+), 97 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 1fd73296..359018f6 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -104,11 +104,12 @@ void UndoStateLoad(); // * integerScale: force screens to be scaled up at integer scaling factors void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int rotation, int sizing, int screenGap, bool integerScale); -// get a 2x3 transform matrix for the given screen (0=top, 1=bottom) +// get a 2x3 transform matrix for each screen // note: the transform assumes an origin point at the top left of the display, // X going left and Y going down // for each screen the source coordinates should be (0,0) and (256,192) -float* GetScreenTransform(int screen); +// 'top' and 'bot' should point each to an array of 6 floats +void GetScreenTransforms(float* top, float* bot); // de-transform the provided host display coordinates to get coordinates // on the bottom screen diff --git a/src/frontend/Util_Video.cpp b/src/frontend/Util_Video.cpp index 0f5ff667..87cb9b50 100644 --- a/src/frontend/Util_Video.cpp +++ b/src/frontend/Util_Video.cpp @@ -313,10 +313,10 @@ void SetupScreenLayout(int screenWidth, int screenHeight, int screenLayout, int } } -float* GetScreenTransform(int screen) +void GetScreenTransforms(float* top, float* bot) { - if (screen == 0) return TopScreenMtx; - else return BotScreenMtx; + memcpy(top, TopScreenMtx, 6*sizeof(float)); + memcpy(bot, BotScreenMtx, 6*sizeof(float)); } void GetTouchCoords(int& x, int& y) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 922206fc..0e0a21be 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -543,60 +543,8 @@ bool EmuThread::emuIsRunning() } -MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) +void ScreenHandler::screenSetupLayout(int w, int h) { - screen[0] = new QImage(256, 192, QImage::Format_RGB32); - screen[1] = new QImage(256, 192, QImage::Format_RGB32); - - screenTrans[0].reset(); - screenTrans[1].reset(); - - touching = false; -} - -MainWindowPanel::~MainWindowPanel() -{ - delete screen[0]; - delete screen[1]; -} - -void MainWindowPanel::ensureProperMinSize() -{ - bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3); - int gap = Config::ScreenGap; - - int w = 256; - int h = 192; - - if (Config::ScreenLayout == 0) // natural - { - if (isHori) - setMinimumSize(h+gap+h, w); - else - setMinimumSize(w, h+gap+h); - } - else if (Config::ScreenLayout == 1) // vertical - { - if (isHori) - setMinimumSize(h, w+gap+w); - else - setMinimumSize(w, h+gap+h); - } - else // horizontal - { - if (isHori) - setMinimumSize(h+gap+h, w); - else - setMinimumSize(w+gap+w, h); - } -} - -void MainWindowPanel::setupScreenLayout() -{ - int w = width(); - int h = height(); - float* mtx; - int sizing = Config::ScreenSizing; if (sizing == 3) sizing = autoScreenSizing; @@ -607,47 +555,41 @@ void MainWindowPanel::setupScreenLayout() Config::ScreenGap, Config::IntegerScaling != 0); - mtx = Frontend::GetScreenTransform(0); - screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f, - mtx[2], mtx[3], 0.f, - mtx[4], mtx[5], 1.f); - - mtx = Frontend::GetScreenTransform(1); - screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f, - mtx[2], mtx[3], 0.f, - mtx[4], mtx[5], 1.f); + Frontend::GetScreenTransforms(screenMatrix[0], screenMatrix[1]); } -void MainWindowPanel::paintEvent(QPaintEvent* event) +QSize ScreenHandler::screenGetMinSize() { - QPainter painter(this); + bool isHori = (Config::ScreenRotation == 1 || Config::ScreenRotation == 3); + int gap = Config::ScreenGap; - // fill background - painter.fillRect(event->rect(), QColor::fromRgb(0, 0, 0)); + int w = 256; + int h = 192; - int frontbuf = GPU::FrontBuffer; - if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return; - - memcpy(screen[0]->scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4); - memcpy(screen[1]->scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4); - - painter.setRenderHint(QPainter::SmoothPixmapTransform, Config::ScreenFilter!=0); - - QRect screenrc(0, 0, 256, 192); - - painter.setTransform(screenTrans[0]); - painter.drawImage(screenrc, *screen[0]); - - painter.setTransform(screenTrans[1]); - painter.drawImage(screenrc, *screen[1]); + if (Config::ScreenLayout == 0) // natural + { + if (isHori) + return QSize(h+gap+h, w); + else + return QSize(w, h+gap+h); + } + else if (Config::ScreenLayout == 1) // vertical + { + if (isHori) + return QSize(h, w+gap+w); + else + return QSize(w, h+gap+h); + } + else // horizontal + { + if (isHori) + return QSize(h+gap+h, w); + else + return QSize(w+gap+w, h); + } } -void MainWindowPanel::resizeEvent(QResizeEvent* event) -{ - setupScreenLayout(); -} - -void MainWindowPanel::mousePressEvent(QMouseEvent* event) +void ScreenHandler::screenOnMousePress(QMouseEvent* event) { event->accept(); if (event->button() != Qt::LeftButton) return; @@ -664,7 +606,7 @@ void MainWindowPanel::mousePressEvent(QMouseEvent* event) } } -void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event) +void ScreenHandler::screenOnMouseRelease(QMouseEvent* event) { event->accept(); if (event->button() != Qt::LeftButton) return; @@ -676,7 +618,7 @@ void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event) } } -void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) +void ScreenHandler::screenOnMouseMove(QMouseEvent* event) { event->accept(); if (!(event->buttons() & Qt::LeftButton)) return; @@ -696,6 +638,90 @@ void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) NDS::TouchScreen(x, y); } + +MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) +{ + screen[0] = QImage(256, 192, QImage::Format_RGB32); + screen[1] = QImage(256, 192, QImage::Format_RGB32); + + screenTrans[0].reset(); + screenTrans[1].reset(); + + touching = false; +} + +MainWindowPanel::~MainWindowPanel() +{ +} + +void MainWindowPanel::ensureProperMinSize() +{ + setMinimumSize(screenGetMinSize()); +} + +void MainWindowPanel::setupScreenLayout() +{ + int w = width(); + int h = height(); + float* mtx; + + screenSetupLayout(w, h); + + mtx = screenMatrix[0]; + screenTrans[0].setMatrix(mtx[0], mtx[1], 0.f, + mtx[2], mtx[3], 0.f, + mtx[4], mtx[5], 1.f); + + mtx = screenMatrix[1]; + screenTrans[1].setMatrix(mtx[0], mtx[1], 0.f, + mtx[2], mtx[3], 0.f, + mtx[4], mtx[5], 1.f); +} + +void MainWindowPanel::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + + // fill background + painter.fillRect(event->rect(), QColor::fromRgb(0, 0, 0)); + + int frontbuf = GPU::FrontBuffer; + if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return; + + memcpy(screen[0].scanLine(0), GPU::Framebuffer[frontbuf][0], 256*192*4); + memcpy(screen[1].scanLine(0), GPU::Framebuffer[frontbuf][1], 256*192*4); + + painter.setRenderHint(QPainter::SmoothPixmapTransform, Config::ScreenFilter!=0); + + QRect screenrc(0, 0, 256, 192); + + painter.setTransform(screenTrans[0]); + painter.drawImage(screenrc, screen[0]); + + painter.setTransform(screenTrans[1]); + painter.drawImage(screenrc, screen[1]); +} + +void MainWindowPanel::resizeEvent(QResizeEvent* event) +{ + setupScreenLayout(); +} + +void MainWindowPanel::mousePressEvent(QMouseEvent* event) +{ + screenOnMousePress(event); +} + +void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event) +{ + screenOnMouseRelease(event); +} + +void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) +{ + screenOnMouseMove(event); +} + void MainWindowPanel::onScreenLayoutChanged() { setupScreenLayout(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index c0dc465c..1121da1d 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -64,7 +64,24 @@ private: }; -class MainWindowPanel : public QWidget +class ScreenHandler +{ +protected: + void screenSetupLayout(int w, int h); + + QSize screenGetMinSize(); + + void screenOnMousePress(QMouseEvent* event); + void screenOnMouseRelease(QMouseEvent* event); + void screenOnMouseMove(QMouseEvent* event); + + float screenMatrix[2][6]; + + bool touching; +}; + + +class MainWindowPanel : public QWidget, public ScreenHandler { Q_OBJECT @@ -88,9 +105,8 @@ private slots: void onScreenLayoutChanged(); private: - QImage* screen[2]; + QImage screen[2]; QTransform screenTrans[2]; - bool touching; }; From bc4a83abca991effe082f76f81cd6b4eef6ef0ba Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 24 May 2020 23:47:11 +0200 Subject: [PATCH 073/105] make frontend-util audio module config-agnostic --- src/frontend/FrontendUtil.h | 4 ++-- src/frontend/Util_Audio.cpp | 7 +------ src/frontend/qt_sdl/main.cpp | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 359018f6..6b83cbc8 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -124,9 +124,9 @@ void Init_Audio(int outputfreq); int AudioOut_GetNumSamples(int outlen); // resample audio from the core audio output to match the frontend's -// output frequency, and apply user-specified volume +// output frequency, and apply specified volume // note: this assumes the output buffer is interleaved stereo -void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen); +void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume); // feed silence to the microphone input void Mic_FeedSilence(); diff --git a/src/frontend/Util_Audio.cpp b/src/frontend/Util_Audio.cpp index d4c33332..fc80c902 100644 --- a/src/frontend/Util_Audio.cpp +++ b/src/frontend/Util_Audio.cpp @@ -22,9 +22,6 @@ #include #include "FrontendUtil.h" -#include "Config.h" -#include "qt_sdl/PlatformConfig.h" // FIXME!!! -#include "Platform.h" #include "NDS.h" @@ -63,14 +60,12 @@ int AudioOut_GetNumSamples(int outlen) return len_in; } -void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen) +void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume) { float res_incr = inlen / (float)outlen; float res_timer = 0; int res_pos = 0; - int volume = Config::AudioVolume; - for (int i = 0; i < outlen; i++) { outbuf[i*2 ] = (inbuf[res_pos*2 ] * volume) >> 8; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 0e0a21be..fac4709f 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -110,7 +110,7 @@ void audioCallback(void* data, Uint8* stream, int len) num_in = len_in-margin; } - Frontend::AudioOut_Resample(buf_in, num_in, (s16*)stream, len); + Frontend::AudioOut_Resample(buf_in, num_in, (s16*)stream, len, Config::AudioVolume); } From 4e34359a80833c21ef6a8fabd35c4d26babcaaab Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 25 May 2020 03:12:09 +0200 Subject: [PATCH 074/105] get the GL shit going --- src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/main.cpp | 91 +++++++++++++++------ src/frontend/qt_sdl/main.h | 49 ++++++++++-- src/frontend/qt_sdl/main_shaders.h | 124 +++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 31 deletions(-) create mode 100644 src/frontend/qt_sdl/main_shaders.h diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 7bc81f0a..5778b403 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -2,6 +2,7 @@ project(qt_sdl) SET(SOURCES_QT_SDL main.cpp + main_shaders.h EmuSettingsDialog.cpp InputConfigDialog.cpp AudioSettingsDialog.cpp diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index fac4709f..b11dd10c 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -639,7 +639,7 @@ void ScreenHandler::screenOnMouseMove(QMouseEvent* event) } -MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) +ScreenPanelNative::ScreenPanelNative(QWidget* parent) : QWidget(parent) { screen[0] = QImage(256, 192, QImage::Format_RGB32); screen[1] = QImage(256, 192, QImage::Format_RGB32); @@ -650,16 +650,11 @@ MainWindowPanel::MainWindowPanel(QWidget* parent) : QWidget(parent) touching = false; } -MainWindowPanel::~MainWindowPanel() +ScreenPanelNative::~ScreenPanelNative() { } -void MainWindowPanel::ensureProperMinSize() -{ - setMinimumSize(screenGetMinSize()); -} - -void MainWindowPanel::setupScreenLayout() +void ScreenPanelNative::setupScreenLayout() { int w = width(); int h = height(); @@ -678,7 +673,7 @@ void MainWindowPanel::setupScreenLayout() mtx[4], mtx[5], 1.f); } -void MainWindowPanel::paintEvent(QPaintEvent* event) +void ScreenPanelNative::paintEvent(QPaintEvent* event) { QPainter painter(this); @@ -702,28 +697,78 @@ void MainWindowPanel::paintEvent(QPaintEvent* event) painter.drawImage(screenrc, screen[1]); } -void MainWindowPanel::resizeEvent(QResizeEvent* event) +void ScreenPanelNative::resizeEvent(QResizeEvent* event) { setupScreenLayout(); } -void MainWindowPanel::mousePressEvent(QMouseEvent* event) +void ScreenPanelNative::mousePressEvent(QMouseEvent* event) { screenOnMousePress(event); } -void MainWindowPanel::mouseReleaseEvent(QMouseEvent* event) +void ScreenPanelNative::mouseReleaseEvent(QMouseEvent* event) { screenOnMouseRelease(event); } -void MainWindowPanel::mouseMoveEvent(QMouseEvent* event) +void ScreenPanelNative::mouseMoveEvent(QMouseEvent* event) { screenOnMouseMove(event); } -void MainWindowPanel::onScreenLayoutChanged() +void ScreenPanelNative::onScreenLayoutChanged() { + setMinimumSize(screenGetMinSize()); + setupScreenLayout(); +} + + +ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) +{ + // +} + +ScreenPanelGL::~ScreenPanelGL() +{ +} + +void ScreenPanelGL::setupScreenLayout() +{ + int w = width(); + int h = height(); + + screenSetupLayout(w, h); +} + +void ScreenPanelGL::paintEvent(QPaintEvent* event) +{ + // TODO? +} + +void ScreenPanelGL::resizeEvent(QResizeEvent* event) +{ + setupScreenLayout(); +} + +void ScreenPanelGL::mousePressEvent(QMouseEvent* event) +{ + screenOnMousePress(event); +} + +void ScreenPanelGL::mouseReleaseEvent(QMouseEvent* event) +{ + screenOnMouseRelease(event); +} + +void ScreenPanelGL::mouseMoveEvent(QMouseEvent* event) +{ + screenOnMouseMove(event); +} + +void ScreenPanelGL::onScreenLayoutChanged() +{ + setMinimumSize(screenGetMinSize()); setupScreenLayout(); } @@ -932,9 +977,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) } setMenuBar(menubar); - panel = new MainWindowPanel(this); + panel = new ScreenPanelNative(this); setCentralWidget(panel); - panel->ensureProperMinSize(); + connect(this, SIGNAL(screenLayoutChange()), panel, SLOT(onScreenLayoutChanged())); + emit screenLayoutChange(); resize(Config::WindowWidth, Config::WindowHeight); @@ -1413,8 +1459,7 @@ void MainWindow::onChangeScreenRotation(QAction* act) int rot = act->data().toInt(); Config::ScreenRotation = rot; - panel->ensureProperMinSize(); - panel->setupScreenLayout(); + emit screenLayoutChange(); } void MainWindow::onChangeScreenGap(QAction* act) @@ -1422,8 +1467,7 @@ void MainWindow::onChangeScreenGap(QAction* act) int gap = act->data().toInt(); Config::ScreenGap = gap; - panel->ensureProperMinSize(); - panel->setupScreenLayout(); + emit screenLayoutChange(); } void MainWindow::onChangeScreenLayout(QAction* act) @@ -1431,8 +1475,7 @@ void MainWindow::onChangeScreenLayout(QAction* act) int layout = act->data().toInt(); Config::ScreenLayout = layout; - panel->ensureProperMinSize(); - panel->setupScreenLayout(); + emit screenLayoutChange(); } void MainWindow::onChangeScreenSizing(QAction* act) @@ -1440,14 +1483,14 @@ void MainWindow::onChangeScreenSizing(QAction* act) int sizing = act->data().toInt(); Config::ScreenSizing = sizing; - panel->setupScreenLayout(); + emit screenLayoutChange(); } void MainWindow::onChangeIntegerScaling(bool checked) { Config::IntegerScaling = checked?1:0; - panel->setupScreenLayout(); + emit screenLayoutChange(); } void MainWindow::onChangeScreenFiltering(bool checked) diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 1121da1d..a244907c 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -24,6 +24,7 @@ #include #include #include +#include class EmuThread : public QThread @@ -66,6 +67,11 @@ private: class ScreenHandler { + Q_GADGET + +public: + virtual ~ScreenHandler() {} + protected: void screenSetupLayout(int w, int h); @@ -81,16 +87,13 @@ protected: }; -class MainWindowPanel : public QWidget, public ScreenHandler +class ScreenPanelNative : public QWidget, public ScreenHandler { Q_OBJECT public: - explicit MainWindowPanel(QWidget* parent); - ~MainWindowPanel(); - - void ensureProperMinSize(); - void setupScreenLayout(); + explicit ScreenPanelNative(QWidget* parent); + ~ScreenPanelNative(); protected: void paintEvent(QPaintEvent* event) override; @@ -105,11 +108,40 @@ private slots: void onScreenLayoutChanged(); private: + void setupScreenLayout(); + QImage screen[2]; QTransform screenTrans[2]; }; +class ScreenPanelGL : public QOpenGLWidget, public ScreenHandler +{ + Q_OBJECT + +public: + explicit ScreenPanelGL(QWidget* parent); + ~ScreenPanelGL(); + +protected: + void paintEvent(QPaintEvent* event) override; + + void resizeEvent(QResizeEvent* event) override; + + void mousePressEvent(QMouseEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; + +private slots: + void onScreenLayoutChanged(); + +private: + void setupScreenLayout(); + + // +}; + + class MainWindow : public QMainWindow { Q_OBJECT @@ -127,6 +159,9 @@ protected: void dragEnterEvent(QDragEnterEvent* event) override; void dropEvent(QDropEvent* event) override; +signals: + void screenLayoutChange(); + private slots: void onOpenFile(); void onBootFirmware(); @@ -167,7 +202,7 @@ private: QString loadErrorStr(int error); public: - MainWindowPanel* panel; + QWidget* panel; QAction* actOpenROM; QAction* actBootFirmware; diff --git a/src/frontend/qt_sdl/main_shaders.h b/src/frontend/qt_sdl/main_shaders.h new file mode 100644 index 00000000..7c4feec8 --- /dev/null +++ b/src/frontend/qt_sdl/main_shaders.h @@ -0,0 +1,124 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef MAIN_SHADERS_H +#define MAIN_SHADERS_H + +const char* kScreenVS = R"(#version 140 + +layout(std140) uniform uConfig +{ + vec2 uScreenSize; + uint u3DScale; + uint uFilterMode; +}; + +in vec2 vPosition; +in vec2 vTexcoord; + +smooth out vec2 fTexcoord; + +void main() +{ + vec4 fpos; + fpos.xy = ((vPosition * 2.0) / uScreenSize) - 1.0; + fpos.y *= -1; + fpos.z = 0.0; + fpos.w = 1.0; + + gl_Position = fpos; + fTexcoord = vTexcoord; +} +)"; + +const char* kScreenFS = R"(#version 140 + +layout(std140) uniform uConfig +{ + vec2 uScreenSize; + uint u3DScale; + uint uFilterMode; +}; + +uniform usampler2D ScreenTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +void main() +{ + ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); + + // TODO: filters + + oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0); +} +)"; + + + +const char* kScreenVS_OSD = R"(#version 140 + +layout(std140) uniform uConfig +{ + vec2 uScreenSize; + uint u3DScale; + uint uFilterMode; +}; + +uniform ivec2 uOSDPos; +uniform ivec2 uOSDSize; + +in vec2 vPosition; + +smooth out vec2 fTexcoord; + +void main() +{ + vec4 fpos; + + vec2 osdpos = (vPosition * vec2(uOSDSize)); + fTexcoord = osdpos; + osdpos += uOSDPos; + + fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0; + fpos.y *= -1; + fpos.z = 0.0; + fpos.w = 1.0; + + gl_Position = fpos; +} +)"; + +const char* kScreenFS_OSD = R"(#version 140 + +uniform sampler2D OSDTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +void main() +{ + vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0); + oColor = pixel.bgra; +} +)"; + +#endif // MAIN_SHADERS_H From 10f9eda58a7bbc9becb186ea2bdf1c9b7d2c1bc1 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 25 May 2020 14:59:26 +0200 Subject: [PATCH 075/105] get the whole OpenGL shit going --- src/frontend/qt_sdl/main.cpp | 127 +++++++++++++++++++++++++++-- src/frontend/qt_sdl/main.h | 17 +++- src/frontend/qt_sdl/main_shaders.h | 28 ++----- 3 files changed, 145 insertions(+), 27 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index b11dd10c..bb08a87e 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -54,6 +54,8 @@ #include "Savestate.h" +#include "main_shaders.h" + // TODO: uniform variable spelling @@ -247,7 +249,8 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) EmuRunning = 2; RunningSomething = false; - connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(update())); + //connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(update())); + connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(update())); //connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(repaint())); connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); @@ -726,11 +729,18 @@ void ScreenPanelNative::onScreenLayoutChanged() ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) { - // + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + format.setVersion(3, 2); + format.setProfile(QSurfaceFormat::CoreProfile); + setFormat(format); } ScreenPanelGL::~ScreenPanelGL() { + // CHECKME!!!! + delete screenShader; } void ScreenPanelGL::setupScreenLayout() @@ -741,14 +751,120 @@ void ScreenPanelGL::setupScreenLayout() screenSetupLayout(w, h); } -void ScreenPanelGL::paintEvent(QPaintEvent* event) +void ScreenPanelGL::initializeGL() { - // TODO? + initializeOpenGLFunctions(); + + glClearColor(0, 0, 0, 1); + + screenShader = new QOpenGLShaderProgram(this); + screenShader->addShaderFromSourceCode(QOpenGLShader::Vertex, kScreenVS); + screenShader->addShaderFromSourceCode(QOpenGLShader::Fragment, kScreenFS); + + GLuint pid = screenShader->programId(); + printf("program: %d\n", pid); + glBindAttribLocation(pid, 0, "vPosition"); + glBindAttribLocation(pid, 1, "vTexcoord"); + glBindFragDataLocation(pid, 0, "oColor"); + + screenShader->link(); + + screenShader->bind(); + screenShader->setUniformValue("ScreenTex", (GLint)0); + screenShader->release(); + + + float vertices[] = + { + 0, 0, 0, 0, + 0, 192, 0, 0.5, + 256, 192, 1, 0.5, + 0, 0, 0, 0, + 256, 192, 1, 0.5, + 256, 0, 1, 0, + + 0, 0, 0, 0.5, + 0, 192, 0, 1, + 256, 192, 1, 1, + 0, 0, 0, 0.5, + 256, 192, 1, 1, + 256, 0, 1, 0.5 + }; + + glGenBuffers(1, &screenVertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glGenVertexArrays(1, &screenVertexArray); + glBindVertexArray(screenVertexArray); + glEnableVertexAttribArray(0); // position + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0)); + glEnableVertexAttribArray(1); // texcoord + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4)); + + glGenTextures(1, &screenTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, screenTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); +} + +void ScreenPanelGL::paintGL() +{ + int w = width(); + int h = height(); + + glClear(GL_COLOR_BUFFER_BIT); + + // TODO: check hiDPI compliance of this + glViewport(0, 0, w, h); + + screenShader->bind(); + + screenShader->setUniformValue("uScreenSize", (float)w, (float)h); + + int frontbuf = GPU::FrontBuffer; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, screenTexture); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } + + GLint filter = Config::ScreenFilter ? GL_LINEAR : GL_NEAREST; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + + glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer); + glBindVertexArray(screenVertexArray); + + GLint transloc = screenShader->uniformLocation("uTransform"); + + glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[0]); + glDrawArrays(GL_TRIANGLES, 0, 2*3); + + glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[1]); + glDrawArrays(GL_TRIANGLES, 2*3, 2*3); + + screenShader->release(); } void ScreenPanelGL::resizeEvent(QResizeEvent* event) { setupScreenLayout(); + + QOpenGLWidget::resizeEvent(event); +} + +void ScreenPanelGL::resizeGL(int w, int h) +{ } void ScreenPanelGL::mousePressEvent(QMouseEvent* event) @@ -977,7 +1093,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) } setMenuBar(menubar); - panel = new ScreenPanelNative(this); + //panel = new ScreenPanelNative(this); + panel = new ScreenPanelGL(this); setCentralWidget(panel); connect(this, SIGNAL(screenLayoutChange()), panel, SLOT(onScreenLayoutChanged())); emit screenLayoutChange(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index a244907c..8a8c0417 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -24,7 +24,12 @@ #include #include #include + #include +#include +#include +#include +#include class EmuThread : public QThread @@ -115,7 +120,7 @@ private: }; -class ScreenPanelGL : public QOpenGLWidget, public ScreenHandler +class ScreenPanelGL : public QOpenGLWidget, public ScreenHandler, protected QOpenGLFunctions_3_2_Core { Q_OBJECT @@ -124,9 +129,12 @@ public: ~ScreenPanelGL(); protected: - void paintEvent(QPaintEvent* event) override; + void initializeGL() override; + + void paintGL() override; void resizeEvent(QResizeEvent* event) override; + void resizeGL(int w, int h) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; @@ -138,7 +146,10 @@ private slots: private: void setupScreenLayout(); - // + QOpenGLShaderProgram* screenShader; + GLuint screenVertexBuffer; + GLuint screenVertexArray; + GLuint screenTexture; }; diff --git a/src/frontend/qt_sdl/main_shaders.h b/src/frontend/qt_sdl/main_shaders.h index 7c4feec8..2e57e591 100644 --- a/src/frontend/qt_sdl/main_shaders.h +++ b/src/frontend/qt_sdl/main_shaders.h @@ -21,12 +21,8 @@ const char* kScreenVS = R"(#version 140 -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; +uniform vec2 uScreenSize; +uniform mat2x3 uTransform; in vec2 vPosition; in vec2 vTexcoord; @@ -36,7 +32,10 @@ smooth out vec2 fTexcoord; void main() { vec4 fpos; - fpos.xy = ((vPosition * 2.0) / uScreenSize) - 1.0; + + fpos.xy = vec3(vPosition, 1.0) * uTransform; + + fpos.xy = ((fpos.xy * 2.0) / uScreenSize) - 1.0; fpos.y *= -1; fpos.z = 0.0; fpos.w = 1.0; @@ -48,14 +47,7 @@ void main() const char* kScreenFS = R"(#version 140 -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; - -uniform usampler2D ScreenTex; +uniform sampler2D ScreenTex; smooth in vec2 fTexcoord; @@ -63,11 +55,9 @@ out vec4 oColor; void main() { - ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); + vec4 pixel = texture2D(ScreenTex, fTexcoord); - // TODO: filters - - oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0); + oColor = vec4(pixel.bgr, 1.0); } )"; From 36f4cdbbbf1904c1a0455bf45d9720f03872e1bd Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 25 May 2020 18:25:50 +0200 Subject: [PATCH 076/105] get the OpenGL renderer going. sorta. (also make the blackmagic_II branch obsolete in the process) --- src/CMakeLists.txt | 2 + src/GPU.cpp | 2 + src/GPU.h | 14 + src/GPU2D.cpp | 2 + src/GPU3D.cpp | 2 +- src/GPU3D_OpenGL.cpp | 31 +- src/GPU_OpenGL.cpp | 207 ++++++++ src/GPU_OpenGL_shaders.h | 867 +++++++++++++++++++++++++++++++ src/OpenGLSupport.cpp | 14 +- src/OpenGLSupport.h | 32 +- src/frontend/qt_sdl/Platform.cpp | 3 +- src/frontend/qt_sdl/main.cpp | 96 +++- src/frontend/qt_sdl/main.h | 11 + 13 files changed, 1241 insertions(+), 42 deletions(-) create mode 100644 src/GPU_OpenGL.cpp create mode 100644 src/GPU_OpenGL_shaders.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 245e6a2a..56bb3cb5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,8 @@ add_library(core STATIC FIFO.h GBACart.cpp GPU.cpp + GPU_OpenGL.cpp + GPU_OpenGL_shaders.h GPU2D.cpp GPU3D.cpp GPU3D_OpenGL.cpp diff --git a/src/GPU.cpp b/src/GPU.cpp index 42bfc566..993086eb 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -985,6 +985,8 @@ void StartScanline(u32 line) GPU2D_A->VBlank(); GPU2D_B->VBlank(); GPU3D::VBlank(); + + if (Accelerated) GLCompositor::RenderFrame(); } else if (VCount == 144) { diff --git a/src/GPU.h b/src/GPU.h index 661a7d91..e85a5b4c 100644 --- a/src/GPU.h +++ b/src/GPU.h @@ -422,6 +422,20 @@ void SetDispStat(u32 cpu, u16 val); void SetVCount(u16 val); +namespace GLCompositor +{ + +bool Init(); +void DeInit(); +void Reset(); + +void UpdateDisplaySettings(); + +void RenderFrame(); +void BindOutputTexture(); + +} + } #endif diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 1c6cf0cf..6f950b73 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -728,6 +728,8 @@ u32 GPU2D::ColorComposite(int i, u32 val1, u32 val2) case 3: return ColorBrightnessDown(val1, EVY); case 4: return ColorBlend5(val1, val2); } + + return val1; } diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 4f146ae7..e687e37d 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -616,7 +616,7 @@ int InitRenderer(bool hasGL) if (!GLRenderer::Init()) renderer = 0; } - +printf("renderer: %d\n", renderer); if (renderer == 0) SoftRenderer::Init(); Renderer = renderer; diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index b1bcaa11..dcc4b6b2 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -29,6 +29,8 @@ namespace GPU3D namespace GLRenderer { +using namespace OpenGL; + // GL version requirements // * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS) // * UBO: 3.1 @@ -142,7 +144,7 @@ bool BuildRenderShader(u32 flags, const char* vs, const char* fs) strcpy(&fsbuf[headerlen], kRenderFSCommon); strcpy(&fsbuf[headerlen + fsclen], fs); - bool ret = OpenGL_BuildShaderProgram(vsbuf, fsbuf, RenderShader[flags], shadername); + bool ret = OpenGL::BuildShaderProgram(vsbuf, fsbuf, RenderShader[flags], shadername); delete[] vsbuf; delete[] fsbuf; @@ -158,7 +160,7 @@ bool BuildRenderShader(u32 flags, const char* vs, const char* fs) glBindFragDataLocation(prog, 0, "oColor"); glBindFragDataLocation(prog, 1, "oAttr"); - if (!OpenGL_LinkShaderProgram(RenderShader[flags])) + if (!OpenGL::LinkShaderProgram(RenderShader[flags])) return false; GLint uni_id = glGetUniformBlockIndex(prog, "uConfig"); @@ -202,14 +204,14 @@ bool Init() glClearDepth(1.0); - if (!OpenGL_BuildShaderProgram(kClearVS, kClearFS, ClearShaderPlain, "ClearShader")) + if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, ClearShaderPlain, "ClearShader")) return false; glBindAttribLocation(ClearShaderPlain[2], 0, "vPosition"); glBindFragDataLocation(ClearShaderPlain[2], 0, "oColor"); glBindFragDataLocation(ClearShaderPlain[2], 1, "oAttr"); - if (!OpenGL_LinkShaderProgram(ClearShaderPlain)) + if (!OpenGL::LinkShaderProgram(ClearShaderPlain)) return false; ClearUniformLoc[0] = glGetUniformLocation(ClearShaderPlain[2], "uColor"); @@ -237,15 +239,15 @@ bool Init() kRenderVS_W, kRenderFS_WSM)) return false; - if (!OpenGL_BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, FinalPassEdgeShader, "FinalPassEdgeShader")) + if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, FinalPassEdgeShader, "FinalPassEdgeShader")) return false; - if (!OpenGL_BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, FinalPassFogShader, "FinalPassFogShader")) + if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, FinalPassFogShader, "FinalPassFogShader")) return false; glBindAttribLocation(FinalPassEdgeShader[2], 0, "vPosition"); glBindFragDataLocation(FinalPassEdgeShader[2], 0, "oColor"); - if (!OpenGL_LinkShaderProgram(FinalPassEdgeShader)) + if (!OpenGL::LinkShaderProgram(FinalPassEdgeShader)) return false; uni_id = glGetUniformBlockIndex(FinalPassEdgeShader[2], "uConfig"); @@ -261,7 +263,7 @@ bool Init() glBindAttribLocation(FinalPassFogShader[2], 0, "vPosition"); glBindFragDataLocation(FinalPassFogShader[2], 0, "oColor"); - if (!OpenGL_LinkShaderProgram(FinalPassFogShader)) + if (!OpenGL::LinkShaderProgram(FinalPassFogShader)) return false; uni_id = glGetUniformBlockIndex(FinalPassFogShader[2], "uConfig"); @@ -371,11 +373,19 @@ bool Init() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 1024, 48, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL); + if (!GPU::GLCompositor::Init()) + { + // TODO: clean up things? fail more gracefully?? + return false; + } + return true; } void DeInit() { + GPU::GLCompositor::DeInit(); + glDeleteTextures(1, &TexMemID); glDeleteTextures(1, &TexPalMemID); @@ -392,12 +402,13 @@ void DeInit() for (int i = 0; i < 16; i++) { if (!RenderShader[i][2]) continue; - OpenGL_DeleteShaderProgram(RenderShader[i]); + OpenGL::DeleteShaderProgram(RenderShader[i]); } } void Reset() { + GPU::GLCompositor::Reset(); } void UpdateDisplaySettings() @@ -480,6 +491,8 @@ void UpdateDisplaySettings() //glLineWidth(scale); //glLineWidth(1.5); + + GPU::GLCompositor::UpdateDisplaySettings(); } diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp new file mode 100644 index 00000000..c9d31f10 --- /dev/null +++ b/src/GPU_OpenGL.cpp @@ -0,0 +1,207 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "NDS.h" +#include "GPU.h" +#include "Config.h" +#include "OpenGLSupport.h" +#include "GPU_OpenGL_shaders.h" + +namespace GPU +{ +namespace GLCompositor +{ + +using namespace OpenGL; + +int Scale; +int ScreenH, ScreenW; + +GLuint CompShader[1][3]; +GLuint CompScaleLoc[1]; + +GLuint CompVertexBufferID; +GLuint CompVertexArrayID; +float CompVertices[2 * 3*2 * 2]; // position + +GLuint CompScreenInputTex; +GLuint CompScreenOutputTex; +GLuint CompScreenOutputFB; + + +bool Init() +{ + if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, CompShader[0], "CompositorShader")) + //if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Linear, CompShader[0], "CompositorShader")) + //if (!OpenGL::BuildShaderProgram(kCompositorVS_xBRZ, kCompositorFS_xBRZ, CompShader[0], "CompositorShader")) + return false; + + for (int i = 0; i < 1; i++) + { + GLint uni_id; + + glBindAttribLocation(CompShader[i][2], 0, "vPosition"); + glBindFragDataLocation(CompShader[i][2], 0, "oColor"); + + if (!OpenGL::LinkShaderProgram(CompShader[i])) + return false; + + CompScaleLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DScale"); + + glUseProgram(CompShader[i][2]); + uni_id = glGetUniformLocation(CompShader[i][2], "ScreenTex"); + glUniform1i(uni_id, 0); + uni_id = glGetUniformLocation(CompShader[i][2], "_3DTex"); + glUniform1i(uni_id, 1); + } + +#define SETVERTEX(i, x, y) \ + CompVertices[2*(i) + 0] = x; \ + CompVertices[2*(i) + 1] = y; + + // top screen + SETVERTEX(0, -1, 1); + SETVERTEX(1, 1, 0); + SETVERTEX(2, 1, 1); + SETVERTEX(3, -1, 1); + SETVERTEX(4, -1, 0); + SETVERTEX(5, 1, 0); + + // bottom screen + SETVERTEX(6, -1, 0); + SETVERTEX(7, 1, -1); + SETVERTEX(8, 1, 0); + SETVERTEX(9, -1, 0); + SETVERTEX(10, -1, -1); + SETVERTEX(11, 1, -1); + +#undef SETVERTEX + + glGenBuffers(1, &CompVertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); + glBufferData(GL_ARRAY_BUFFER, sizeof(CompVertices), CompVertices, GL_STATIC_DRAW); + + glGenVertexArrays(1, &CompVertexArrayID); + glBindVertexArray(CompVertexArrayID); + glEnableVertexAttribArray(0); // position + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*4, (void*)(0)); + + glGenFramebuffers(1, &CompScreenOutputFB); + + glGenTextures(1, &CompScreenInputTex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 256*3 + 1, 192*2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL); + + glGenTextures(1, &CompScreenOutputTex); + glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + return true; +} + +void DeInit() +{ + glDeleteFramebuffers(1, &CompScreenOutputFB); + glDeleteTextures(1, &CompScreenInputTex); + glDeleteTextures(1, &CompScreenOutputTex); + + glDeleteVertexArrays(1, &CompVertexArrayID); + glDeleteBuffers(1, &CompVertexBufferID); + + for (int i = 0; i < 1; i++) + OpenGL::DeleteShaderProgram(CompShader[i]); +} + +void Reset() +{ +} + + +void UpdateDisplaySettings() +{ + int scale = Config::GL_ScaleFactor; + + Scale = scale; + ScreenW = 256 * scale; + ScreenH = 384 * scale; + + glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + GLenum fbassign[] = {GL_COLOR_ATTACHMENT0}; + glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CompScreenOutputTex, 0); + glDrawBuffers(1, fbassign); +} + + +void RenderFrame() +{ + glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glViewport(0, 0, ScreenW, ScreenH); + + // TODO: select more shaders (filtering, etc) + OpenGL::UseShaderProgram(CompShader[0]); + glUniform1ui(CompScaleLoc[0], Scale); + + //if (RunningSomething) + { + int frontbuf = GPU::FrontBuffer; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } + + glActiveTexture(GL_TEXTURE1); + GPU3D::GLRenderer::SetupAccelFrame(); + + glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); + glBindVertexArray(CompVertexArrayID); + glDrawArrays(GL_TRIANGLES, 0, 4*3); + } +} + +void BindOutputTexture() +{ + glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); +} + +} +} diff --git a/src/GPU_OpenGL_shaders.h b/src/GPU_OpenGL_shaders.h new file mode 100644 index 00000000..ec975edb --- /dev/null +++ b/src/GPU_OpenGL_shaders.h @@ -0,0 +1,867 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef GPU_OPENGL_SHADERS_H +#define GPU_OPENGL_SHADERS_H + +const char* kCompositorVS = R"(#version 140 + +in vec2 vPosition; + +smooth out vec2 fTexcoord; + +void main() +{ + vec4 fpos; + fpos.xy = vPosition; + fpos.z = 0.0; + fpos.w = 1.0; + + gl_Position = fpos; + fTexcoord = (vPosition + vec2(1.0, 1.0)) * (vec2(256.0, 384.0) / 2.0); +} +)"; + +const char* kCompositorFS_Nearest = R"(#version 140 + +uniform uint u3DScale; + +uniform usampler2D ScreenTex; +uniform sampler2D _3DTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +void main() +{ + ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); + + ivec4 mbright = ivec4(texelFetch(ScreenTex, ivec2(256*3, int(fTexcoord.y)), 0)); + int dispmode = mbright.b & 0x3; + + if (dispmode == 1) + { + ivec4 val1 = pixel; + ivec4 val2 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(256,0), 0)); + ivec4 val3 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(512,0), 0)); + + int compmode = val3.a & 0xF; + int eva, evb, evy; + + if (compmode == 4) + { + // 3D on top, blending + + float xpos = val3.r + fract(fTexcoord.x); + float ypos = mod(fTexcoord.y, 192); + ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra + * vec4(63,63,63,31)); + + if (_3dpix.a > 0) + { + eva = (_3dpix.a & 0x1F) + 1; + evb = 32 - eva; + + val1 = ((_3dpix * eva) + (val1 * evb)) >> 5; + if (eva <= 16) val1 += ivec4(1,1,1,0); + val1 = min(val1, 0x3F); + } + else + val1 = val2; + } + else if (compmode == 1) + { + // 3D on bottom, blending + + float xpos = val3.r + fract(fTexcoord.x); + float ypos = mod(fTexcoord.y, 192); + ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra + * vec4(63,63,63,31)); + + if (_3dpix.a > 0) + { + eva = val3.g; + evb = val3.b; + + val1 = ((val1 * eva) + (_3dpix * evb)) >> 4; + val1 = min(val1, 0x3F); + } + else + val1 = val2; + } + else if (compmode <= 3) + { + // 3D on top, normal/fade + + float xpos = val3.r + fract(fTexcoord.x); + float ypos = mod(fTexcoord.y, 192); + ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra + * vec4(63,63,63,31)); + + if (_3dpix.a > 0) + { + evy = val3.g; + + val1 = _3dpix; + if (compmode == 2) val1 += ((ivec4(0x3F,0x3F,0x3F,0) - val1) * evy) >> 4; + else if (compmode == 3) val1 -= (val1 * evy) >> 4; + } + else + val1 = val2; + } + + pixel = val1; + } + + if (dispmode != 0) + { + int brightmode = mbright.g >> 6; + if (brightmode == 1) + { + // up + int evy = mbright.r & 0x1F; + if (evy > 16) evy = 16; + + pixel += ((ivec4(0x3F,0x3F,0x3F,0) - pixel) * evy) >> 4; + } + else if (brightmode == 2) + { + // down + int evy = mbright.r & 0x1F; + if (evy > 16) evy = 16; + + pixel -= (pixel * evy) >> 4; + } + } + + pixel.rgb <<= 2; + pixel.rgb |= (pixel.rgb >> 6); + + // TODO: filters + + oColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); +} +)"; + + + +const char* kCompositorFS_Linear = R"(#version 140 + +uniform uint u3DScale; + +uniform usampler2D ScreenTex; +uniform sampler2D _3DTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +ivec4 Get3DPixel(vec2 pos) +{ + return ivec4(texelFetch(_3DTex, ivec2(pos*u3DScale), 0).bgra + * vec4(63,63,63,31)); +} + +ivec4 GetFullPixel(ivec4 val1, ivec4 val2, ivec4 val3, ivec4 _3dpix) +{ + int compmode = val3.a & 0xF; + int eva, evb, evy; + + if (compmode == 4) + { + // 3D on top, blending + + if (_3dpix.a > 0) + { + eva = (_3dpix.a & 0x1F) + 1; + evb = 32 - eva; + + val1 = ((_3dpix * eva) + (val1 * evb)) >> 5; + if (eva <= 16) val1 += ivec4(1,1,1,0); + val1 = min(val1, 0x3F); + } + else + val1 = val2; + } + else if (compmode == 1) + { + // 3D on bottom, blending + + if (_3dpix.a > 0) + { + eva = val3.g; + evb = val3.b; + + val1 = ((val1 * eva) + (_3dpix * evb)) >> 4; + val1 = min(val1, 0x3F); + } + else + val1 = val2; + } + else if (compmode <= 3) + { + // 3D on top, normal/fade + + if (_3dpix.a > 0) + { + evy = val3.g; + + val1 = _3dpix; + if (compmode == 2) val1 += ((ivec4(0x3F,0x3F,0x3F,0) - val1) * evy) >> 4; + else if (compmode == 3) val1 -= (val1 * evy) >> 4; + } + else + val1 = val2; + } + + return val1; +} + +ivec4 imix(ivec4 a, ivec4 b, float x) +{ + return ivec4(vec4(a)*(1-x) + vec4(b)*x); +} + +void main() +{ + ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); + + ivec4 mbright = ivec4(texelFetch(ScreenTex, ivec2(256*3, int(fTexcoord.y)), 0)); + int dispmode = mbright.b & 0x3; + + if (dispmode == 1) + { + ivec4 val1 = pixel; + ivec4 val2 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(256,0), 0)); + ivec4 val3 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(512,0), 0)); + + float xfract = fract(fTexcoord.x); + float yfract = fract(fTexcoord.y); + + float xpos = val3.r + xfract; + float ypos = mod(fTexcoord.y, 192); + ivec4 _3dpix = Get3DPixel(vec2(xpos,ypos)); + + ivec4 p00 = GetFullPixel(val1, val2, val3, _3dpix); + + int xdisp = 1 - int(step(255, fTexcoord.x)); + int ydisp = 1 - int(step(191, ypos)); + + ivec4 p01 = GetFullPixel(ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(xdisp+0 ,0), 0)), + ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(xdisp+256,0), 0)), + ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(xdisp+512,0), 0)), + _3dpix); + + ivec4 p10 = GetFullPixel(ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(0+0 ,ydisp), 0)), + ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(0+256,ydisp), 0)), + ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(0+512,ydisp), 0)), + _3dpix); + + ivec4 p11 = GetFullPixel(ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(xdisp+0 ,ydisp), 0)), + ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(xdisp+256,ydisp), 0)), + ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(xdisp+512,ydisp), 0)), + _3dpix); + + ivec4 pa = imix(p00, p01, xfract); + ivec4 pb = imix(p10, p11, xfract); + + pixel = imix(pa, pb, yfract); + } + + if (dispmode != 0) + { + int brightmode = mbright.g >> 6; + if (brightmode == 1) + { + // up + int evy = mbright.r & 0x1F; + if (evy > 16) evy = 16; + + pixel += ((ivec4(0x3F,0x3F,0x3F,0) - pixel) * evy) >> 4; + } + else if (brightmode == 2) + { + // down + int evy = mbright.r & 0x1F; + if (evy > 16) evy = 16; + + pixel -= (pixel * evy) >> 4; + } + } + + pixel.rgb <<= 2; + pixel.rgb |= (pixel.rgb >> 6); + + // TODO: filters + + oColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); +} +)"; + + + + + + +// HUGE TEST ZONE ARRLGD + +const char* kCompositorVS_xBRZ = R"(#version 140 + +#define BLEND_NONE 0 +#define BLEND_NORMAL 1 +#define BLEND_DOMINANT 2 +#define LUMINANCE_WEIGHT 1.0 +#define EQUAL_COLOR_TOLERANCE 30.0/255.0 +#define STEEP_DIRECTION_THRESHOLD 2.2 +#define DOMINANT_DIRECTION_THRESHOLD 3.6 + +#if __VERSION__ >= 130 +#define COMPAT_VARYING out +#define COMPAT_ATTRIBUTE in +#define COMPAT_TEXTURE texture +#else +#define COMPAT_VARYING varying +#define COMPAT_ATTRIBUTE attribute +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +COMPAT_ATTRIBUTE vec2 vPosition; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 t1; +COMPAT_VARYING vec4 t2; +COMPAT_VARYING vec4 t3; +COMPAT_VARYING vec4 t4; +COMPAT_VARYING vec4 t5; +COMPAT_VARYING vec4 t6; +COMPAT_VARYING vec4 t7; + +uniform COMPAT_PRECISION int FrameDirection; +uniform COMPAT_PRECISION int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; + +// vertex compatibility #defines +#define vTexCoord TEX0.xy +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + +void main() +{ + vec4 fpos; + fpos.xy = vPosition; + fpos.z = 0.0; + fpos.w = 1.0; + + gl_Position = fpos; + vec2 TexCoord = (vPosition + vec2(1.0, 1.0)) * (vec2(256.0, 384.0) / 2.0); + + + //gl_Position = MVPMatrix * VertexCoord; + //COL0 = COLOR; + TEX0.xy = TexCoord.xy; + vec2 ps = vec2(1,1);//vec2(SourceSize.z, SourceSize.w); + float dx = ps.x; + float dy = ps.y; + + // A1 B1 C1 + // A0 A B C C4 + // D0 D E F F4 + // G0 G H I I4 + // G5 H5 I5 + + t1 = vTexCoord.xxxy + vec4( -dx, 0.0, dx,-2.0*dy); // A1 B1 C1 + t2 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, -dy); // A B C + t3 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, 0.0); // D E F + t4 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, dy); // G H I + t5 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, 2.0*dy); // G5 H5 I5 + t6 = vTexCoord.xyyy + vec4(-2.0*dx,-dy, 0.0, dy); // A0 D0 G0 + t7 = vTexCoord.xyyy + vec4( 2.0*dx,-dy, 0.0, dy); // C4 F4 I4 +} +)"; + +const char* kCompositorFS_xBRZ = R"(#version 140 + +#define BLEND_NONE 0 +#define BLEND_NORMAL 1 +#define BLEND_DOMINANT 2 +#define LUMINANCE_WEIGHT 1.0 +#define EQUAL_COLOR_TOLERANCE 30.0/255.0 +#define STEEP_DIRECTION_THRESHOLD 2.2 +#define DOMINANT_DIRECTION_THRESHOLD 3.6 + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +//#define COMPAT_TEXTURE texture +#define FragColor oColor +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +//#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +uniform uint u3DScale; + +uniform usampler2D ScreenTex; +uniform sampler2D _3DTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +//uniform COMPAT_PRECISION vec2 OutputSize; +//uniform COMPAT_PRECISION vec2 TextureSize; +#define TextureSize vec2(256,384) +//uniform COMPAT_PRECISION vec2 InputSize; +//uniform sampler2D Texture; +#define Texture 1312 +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING vec4 t1; +COMPAT_VARYING vec4 t2; +COMPAT_VARYING vec4 t3; +COMPAT_VARYING vec4 t4; +COMPAT_VARYING vec4 t5; +COMPAT_VARYING vec4 t6; +COMPAT_VARYING vec4 t7; + +// fragment compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy + +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define outsize vec4(OutputSize, 1.0 / OutputSize) + + const float one_sixth = 1.0 / 6.0; + const float two_sixth = 2.0 / 6.0; + const float four_sixth = 4.0 / 6.0; + const float five_sixth = 5.0 / 6.0; + +vec4 Get2DPixel(vec2 texcoord, int level) +{ + ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(texcoord) + ivec2(level*256,0), 0)); + + return vec4(pixel) / vec4(63.0, 63.0, 63.0, 31.0); +} + +ivec4 Get3DPixel(vec2 pos) +{ + return ivec4(texelFetch(_3DTex, ivec2(pos*u3DScale), 0).bgra + * vec4(63,63,63,31)); +} + +float reduce(const vec3 color) +{ + return dot(color, vec3(65536.0, 256.0, 1.0)); +} + +float DistYCbCr(const vec3 pixA, const vec3 pixB) +{ + const vec3 w = vec3(0.2627, 0.6780, 0.0593); + const float scaleB = 0.5 / (1.0 - w.b); + const float scaleR = 0.5 / (1.0 - w.r); + vec3 diff = pixA - pixB; + float Y = dot(diff, w); + float Cb = scaleB * (diff.b - Y); + float Cr = scaleR * (diff.r - Y); + + return sqrt( ((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr) ); +} + +bool IsPixEqual(const vec3 pixA, const vec3 pixB) +{ + return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE); +} + +bool IsBlendingNeeded(const ivec4 blend) +{ + return any(notEqual(blend, ivec4(BLEND_NONE))); +} + +//--------------------------------------- +// Input Pixel Mapping: --|21|22|23|-- +// 19|06|07|08|09 +// 18|05|00|01|10 +// 17|04|03|02|11 +// --|15|14|13|-- +// +// Output Pixel Mapping: 20|21|22|23|24|25 +// 19|06|07|08|09|26 +// 18|05|00|01|10|27 +// 17|04|03|02|11|28 +// 16|15|14|13|12|29 +// 35|34|33|32|31|30 + +ivec4 GetFiltered2DPixel(int level) +{ + vec2 f = fract(vTexCoord.xy);// * SourceSize.xy); + + //--------------------------------------- + // Input Pixel Mapping: 20|21|22|23|24 + // 19|06|07|08|09 + // 18|05|00|01|10 + // 17|04|03|02|11 + // 16|15|14|13|12 + + vec3 src[25]; + + src[21] = Get2DPixel(t1.xw, level).rgb; + src[22] = Get2DPixel(t1.yw, level).rgb; + src[23] = Get2DPixel(t1.zw, level).rgb; + src[ 6] = Get2DPixel(t2.xw, level).rgb; + src[ 7] = Get2DPixel(t2.yw, level).rgb; + src[ 8] = Get2DPixel(t2.zw, level).rgb; + src[ 5] = Get2DPixel(t3.xw, level).rgb; + src[ 0] = Get2DPixel(t3.yw, level).rgb; + src[ 1] = Get2DPixel(t3.zw, level).rgb; + src[ 4] = Get2DPixel(t4.xw, level).rgb; + src[ 3] = Get2DPixel(t4.yw, level).rgb; + src[ 2] = Get2DPixel(t4.zw, level).rgb; + src[15] = Get2DPixel(t5.xw, level).rgb; + src[14] = Get2DPixel(t5.yw, level).rgb; + src[13] = Get2DPixel(t5.zw, level).rgb; + src[19] = Get2DPixel(t6.xy, level).rgb; + src[18] = Get2DPixel(t6.xz, level).rgb; + src[17] = Get2DPixel(t6.xw, level).rgb; + src[ 9] = Get2DPixel(t7.xy, level).rgb; + src[10] = Get2DPixel(t7.xz, level).rgb; + src[11] = Get2DPixel(t7.xw, level).rgb; + + float v[9]; + v[0] = reduce(src[0]); + v[1] = reduce(src[1]); + v[2] = reduce(src[2]); + v[3] = reduce(src[3]); + v[4] = reduce(src[4]); + v[5] = reduce(src[5]); + v[6] = reduce(src[6]); + v[7] = reduce(src[7]); + v[8] = reduce(src[8]); + + ivec4 blendResult = ivec4(BLEND_NONE); + + // Preprocess corners + // Pixel Tap Mapping: --|--|--|--|-- + // --|--|07|08|-- + // --|05|00|01|10 + // --|04|03|02|11 + // --|--|14|13|-- + // Corner (1, 1) + if ( ((v[0] == v[1] && v[3] == v[2]) || (v[0] == v[3] && v[1] == v[2])) == false) + { + float dist_03_01 = DistYCbCr(src[ 4], src[ 0]) + DistYCbCr(src[ 0], src[ 8]) + DistYCbCr(src[14], src[ 2]) + DistYCbCr(src[ 2], src[10]) + (4.0 * DistYCbCr(src[ 3], src[ 1])); + float dist_00_02 = DistYCbCr(src[ 5], src[ 3]) + DistYCbCr(src[ 3], src[13]) + DistYCbCr(src[ 7], src[ 1]) + DistYCbCr(src[ 1], src[11]) + (4.0 * DistYCbCr(src[ 0], src[ 2])); + bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_03_01) < dist_00_02; + blendResult[2] = ((dist_03_01 < dist_00_02) && (v[0] != v[1]) && (v[0] != v[3])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; + } + + // Pixel Tap Mapping: --|--|--|--|-- + // --|06|07|--|-- + // 18|05|00|01|-- + // 17|04|03|02|-- + // --|15|14|--|-- + // Corner (0, 1) + if ( ((v[5] == v[0] && v[4] == v[3]) || (v[5] == v[4] && v[0] == v[3])) == false) + { + float dist_04_00 = DistYCbCr(src[17], src[ 5]) + DistYCbCr(src[ 5], src[ 7]) + DistYCbCr(src[15], src[ 3]) + DistYCbCr(src[ 3], src[ 1]) + (4.0 * DistYCbCr(src[ 4], src[ 0])); + float dist_05_03 = DistYCbCr(src[18], src[ 4]) + DistYCbCr(src[ 4], src[14]) + DistYCbCr(src[ 6], src[ 0]) + DistYCbCr(src[ 0], src[ 2]) + (4.0 * DistYCbCr(src[ 5], src[ 3])); + bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_05_03) < dist_04_00; + blendResult[3] = ((dist_04_00 > dist_05_03) && (v[0] != v[5]) && (v[0] != v[3])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; + } + + // Pixel Tap Mapping: --|--|22|23|-- + // --|06|07|08|09 + // --|05|00|01|10 + // --|--|03|02|-- + // --|--|--|--|-- + // Corner (1, 0) + if ( ((v[7] == v[8] && v[0] == v[1]) || (v[7] == v[0] && v[8] == v[1])) == false) + { + float dist_00_08 = DistYCbCr(src[ 5], src[ 7]) + DistYCbCr(src[ 7], src[23]) + DistYCbCr(src[ 3], src[ 1]) + DistYCbCr(src[ 1], src[ 9]) + (4.0 * DistYCbCr(src[ 0], src[ 8])); + float dist_07_01 = DistYCbCr(src[ 6], src[ 0]) + DistYCbCr(src[ 0], src[ 2]) + DistYCbCr(src[22], src[ 8]) + DistYCbCr(src[ 8], src[10]) + (4.0 * DistYCbCr(src[ 7], src[ 1])); + bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_07_01) < dist_00_08; + blendResult[1] = ((dist_00_08 > dist_07_01) && (v[0] != v[7]) && (v[0] != v[1])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; + } + + // Pixel Tap Mapping: --|21|22|--|-- + // 19|06|07|08|-- + // 18|05|00|01|-- + // --|04|03|--|-- + // --|--|--|--|-- + // Corner (0, 0) + if ( ((v[6] == v[7] && v[5] == v[0]) || (v[6] == v[5] && v[7] == v[0])) == false) + { + float dist_05_07 = DistYCbCr(src[18], src[ 6]) + DistYCbCr(src[ 6], src[22]) + DistYCbCr(src[ 4], src[ 0]) + DistYCbCr(src[ 0], src[ 8]) + (4.0 * DistYCbCr(src[ 5], src[ 7])); + float dist_06_00 = DistYCbCr(src[19], src[ 5]) + DistYCbCr(src[ 5], src[ 3]) + DistYCbCr(src[21], src[ 7]) + DistYCbCr(src[ 7], src[ 1]) + (4.0 * DistYCbCr(src[ 6], src[ 0])); + bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_05_07) < dist_06_00; + blendResult[0] = ((dist_05_07 < dist_06_00) && (v[0] != v[5]) && (v[0] != v[7])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE; + } + + vec3 dst[16]; + dst[ 0] = src[0]; + dst[ 1] = src[0]; + dst[ 2] = src[0]; + dst[ 3] = src[0]; + dst[ 4] = src[0]; + dst[ 5] = src[0]; + dst[ 6] = src[0]; + dst[ 7] = src[0]; + dst[ 8] = src[0]; + dst[ 9] = src[0]; + dst[10] = src[0]; + dst[11] = src[0]; + dst[12] = src[0]; + dst[13] = src[0]; + dst[14] = src[0]; + dst[15] = src[0]; + + // Scale pixel + if (IsBlendingNeeded(blendResult) == true) + { + float dist_01_04 = DistYCbCr(src[1], src[4]); + float dist_03_08 = DistYCbCr(src[3], src[8]); + bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[4]) && (v[5] != v[4]); + bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[8]) && (v[7] != v[8]); + bool needBlend = (blendResult[2] != BLEND_NONE); + bool doLineBlend = ( blendResult[2] >= BLEND_DOMINANT || + ((blendResult[1] != BLEND_NONE && !IsPixEqual(src[0], src[4])) || + (blendResult[3] != BLEND_NONE && !IsPixEqual(src[0], src[8])) || + (IsPixEqual(src[4], src[3]) && IsPixEqual(src[3], src[2]) && IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[0], src[2]) == false) ) == false ); + + vec3 blendPix = ( DistYCbCr(src[0], src[1]) <= DistYCbCr(src[0], src[3]) ) ? src[1] : src[3]; + dst[ 2] = mix(dst[ 2], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00); + dst[ 9] = mix(dst[ 9], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00); + dst[10] = mix(dst[10], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00); + dst[11] = mix(dst[11], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[12] = mix(dst[12], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00); + dst[13] = mix(dst[13], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[14] = mix(dst[14], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00); + dst[15] = mix(dst[15], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00); + + dist_01_04 = DistYCbCr(src[7], src[2]); + dist_03_08 = DistYCbCr(src[1], src[6]); + haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[2]) && (v[3] != v[2]); + haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[6]) && (v[5] != v[6]); + needBlend = (blendResult[1] != BLEND_NONE); + doLineBlend = ( blendResult[1] >= BLEND_DOMINANT || + !((blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) || + (blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) || + (IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && !IsPixEqual(src[0], src[8])) ) ); + + blendPix = ( DistYCbCr(src[0], src[7]) <= DistYCbCr(src[0], src[1]) ) ? src[7] : src[1]; + dst[ 1] = mix(dst[ 1], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00); + dst[ 6] = mix(dst[ 6], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00); + dst[ 7] = mix(dst[ 7], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00); + dst[ 8] = mix(dst[ 8], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[ 9] = mix(dst[ 9], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00); + dst[10] = mix(dst[10], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[11] = mix(dst[11], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00); + dst[12] = mix(dst[12], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00); + + dist_01_04 = DistYCbCr(src[5], src[8]); + dist_03_08 = DistYCbCr(src[7], src[4]); + haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[8]) && (v[1] != v[8]); + haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[4]) && (v[3] != v[4]); + needBlend = (blendResult[0] != BLEND_NONE); + doLineBlend = ( blendResult[0] >= BLEND_DOMINANT || + !((blendResult[3] != BLEND_NONE && !IsPixEqual(src[0], src[8])) || + (blendResult[1] != BLEND_NONE && !IsPixEqual(src[0], src[4])) || + (IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && IsPixEqual(src[6], src[5]) && IsPixEqual(src[5], src[4]) && !IsPixEqual(src[0], src[6])) ) ); + + blendPix = ( DistYCbCr(src[0], src[5]) <= DistYCbCr(src[0], src[7]) ) ? src[5] : src[7]; + dst[ 0] = mix(dst[ 0], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00); + dst[15] = mix(dst[15], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00); + dst[ 4] = mix(dst[ 4], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00); + dst[ 5] = mix(dst[ 5], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[ 6] = mix(dst[ 6], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00); + dst[ 7] = mix(dst[ 7], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[ 8] = mix(dst[ 8], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00); + dst[ 9] = mix(dst[ 9], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00); + + + dist_01_04 = DistYCbCr(src[3], src[6]); + dist_03_08 = DistYCbCr(src[5], src[2]); + haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[6]) && (v[7] != v[6]); + haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[2]) && (v[1] != v[2]); + needBlend = (blendResult[3] != BLEND_NONE); + doLineBlend = ( blendResult[3] >= BLEND_DOMINANT || + !((blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) || + (blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) || + (IsPixEqual(src[6], src[5]) && IsPixEqual(src[5], src[4]) && IsPixEqual(src[4], src[3]) && IsPixEqual(src[3], src[2]) && !IsPixEqual(src[0], src[4])) ) ); + + blendPix = ( DistYCbCr(src[0], src[3]) <= DistYCbCr(src[0], src[5]) ) ? src[3] : src[5]; + dst[ 3] = mix(dst[ 3], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? ((haveSteepLine) ? 1.0/3.0 : 0.25) : ((haveSteepLine) ? 0.25 : 0.00)) : 0.00); + dst[12] = mix(dst[12], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.25 : 0.00); + dst[13] = mix(dst[13], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.75 : 0.00); + dst[14] = mix(dst[14], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.00 : ((haveShallowLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[15] = mix(dst[15], blendPix, (needBlend) ? ((doLineBlend) ? 1.00 : 0.6848532563) : 0.00); + dst[ 4] = mix(dst[ 4], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.00 : ((haveSteepLine) ? 0.75 : 0.50)) : 0.08677704501) : 0.00); + dst[ 5] = mix(dst[ 5], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.75 : 0.00); + dst[ 6] = mix(dst[ 6], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.25 : 0.00); + } + + vec3 res = mix( mix( mix( mix(dst[ 6], dst[ 7], step(0.25, f.x)), mix(dst[ 8], dst[ 9], step(0.75, f.x)), step(0.50, f.x)), + mix( mix(dst[ 5], dst[ 0], step(0.25, f.x)), mix(dst[ 1], dst[10], step(0.75, f.x)), step(0.50, f.x)), step(0.25, f.y)), + mix( mix( mix(dst[ 4], dst[ 3], step(0.25, f.x)), mix(dst[ 2], dst[11], step(0.75, f.x)), step(0.50, f.x)), + mix( mix(dst[15], dst[14], step(0.25, f.x)), mix(dst[13], dst[12], step(0.75, f.x)), step(0.50, f.x)), step(0.75, f.y)), + step(0.50, f.y)); + + return ivec4(res * vec3(63,63,63), 0); +} + + +void main() +{ + vec2 fTexcoord = vTexCoord.xy; + + ivec4 pixel;// = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0)); + + ivec4 mbright = ivec4(texelFetch(ScreenTex, ivec2(256*3, int(fTexcoord.y)), 0)); + int dispmode = mbright.b & 0x3; + + if (dispmode == 1) + { + ivec4 val1;// = pixel; + //ivec4 val2 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(256,0), 0)); + ivec4 val3 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(512,0), 0)); + + int compmode = val3.a & 0xF; + int eva, evb, evy; + + float xpos = val3.r + fract(fTexcoord.x); + float ypos = mod(fTexcoord.y, 192); + ivec4 _3dpix = Get3DPixel(vec2(xpos, ypos)); + + if (compmode == 4) + { + // 3D on top, blending + + if (_3dpix.a > 0) + { + eva = (_3dpix.a & 0x1F) + 1; + if (eva == 32) + { + val1 = _3dpix; + } + else + { + evb = 32 - eva; + + val1 = GetFiltered2DPixel(0); + + val1 = ((_3dpix * eva) + (val1 * evb)) >> 5; + if (eva <= 16) val1 += ivec4(1,1,1,0); + val1 = min(val1, 0x3F); + } + } + else + val1 = GetFiltered2DPixel(1); + } + else if (compmode == 1) + { + // 3D on bottom, blending + + if (_3dpix.a > 0) + { + eva = val3.g; + evb = val3.b; + + val1 = GetFiltered2DPixel(0); + + val1 = ((val1 * eva) + (_3dpix * evb)) >> 4; + val1 = min(val1, 0x3F); + } + else + val1 = GetFiltered2DPixel(1); + } + else if (compmode <= 3) + { + // 3D on top, normal/fade + + if (_3dpix.a > 0) + { + evy = val3.g; + + val1 = _3dpix; + if (compmode == 2) val1 += ((ivec4(0x3F,0x3F,0x3F,0) - val1) * evy) >> 4; + else if (compmode == 3) val1 -= (val1 * evy) >> 4; + } + else + val1 = GetFiltered2DPixel(1); + } + else + val1 = GetFiltered2DPixel(0); + + pixel = val1; + } + else + { + pixel = GetFiltered2DPixel(0); + } + + if (dispmode != 0) + { + int brightmode = mbright.g >> 6; + if (brightmode == 1) + { + // up + int evy = mbright.r & 0x1F; + if (evy > 16) evy = 16; + + pixel += ((ivec4(0x3F,0x3F,0x3F,0) - pixel) * evy) >> 4; + } + else if (brightmode == 2) + { + // down + int evy = mbright.r & 0x1F; + if (evy > 16) evy = 16; + + pixel -= (pixel * evy) >> 4; + } + } + + pixel.rgb <<= 2; + pixel.rgb |= (pixel.rgb >> 6); + + FragColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); +} +)"; + + + + + + +#endif // GPU_OPENGL_SHADERS_H diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp index f91af9bf..27b14803 100644 --- a/src/OpenGLSupport.cpp +++ b/src/OpenGLSupport.cpp @@ -19,18 +19,20 @@ #include "OpenGLSupport.h" +namespace OpenGL +{ DO_PROCLIST(DECLPROC); -bool OpenGL_Init() +bool Init() { DO_PROCLIST(LOADPROC); return true; } -bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name) +bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name) { int len; int res; @@ -89,7 +91,7 @@ bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, cons return true; } -bool OpenGL_LinkShaderProgram(GLuint* ids) +bool LinkShaderProgram(GLuint* ids) { int res; @@ -115,14 +117,16 @@ bool OpenGL_LinkShaderProgram(GLuint* ids) return true; } -void OpenGL_DeleteShaderProgram(GLuint* ids) +void DeleteShaderProgram(GLuint* ids) { glDeleteShader(ids[0]); glDeleteShader(ids[1]); glDeleteProgram(ids[2]); } -void OpenGL_UseShaderProgram(GLuint* ids) +void UseShaderProgram(GLuint* ids) { glUseProgram(ids[2]); } + +} diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h index 5f92580b..360d2156 100644 --- a/src/OpenGLSupport.h +++ b/src/OpenGLSupport.h @@ -21,6 +21,8 @@ #include #include + +// TODO: different includes for each platform #include #include @@ -45,23 +47,11 @@ // if you need more OpenGL functions, add them to the macronator here -// TODO: handle conditionally loading certain functions for different GL versions - -#ifndef __WIN32__ - -#define DO_PROCLIST_1_3(func) - -#else - -#define DO_PROCLIST_1_3(func) \ - func(GLACTIVETEXTURE, glActiveTexture); \ - func(GLBLENDCOLOR, glBlendColor); \ - -#endif #define DO_PROCLIST(func) \ - DO_PROCLIST_1_3(func) \ + func(GLACTIVETEXTURE, glActiveTexture); \ + func(GLBLENDCOLOR, glBlendColor); \ \ func(GLGENFRAMEBUFFERS, glGenFramebuffers); \ func(GLDELETEFRAMEBUFFERS, glDeleteFramebuffers); \ @@ -122,14 +112,18 @@ func(GLGETSTRINGI, glGetStringi); \ +namespace OpenGL +{ + DO_PROCLIST(DECLPROC_EXT); +bool Init(); -bool OpenGL_Init(); +bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name); +bool LinkShaderProgram(GLuint* ids); +void DeleteShaderProgram(GLuint* ids); +void UseShaderProgram(GLuint* ids); -bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name); -bool OpenGL_LinkShaderProgram(GLuint* ids); -void OpenGL_DeleteShaderProgram(GLuint* ids); -void OpenGL_UseShaderProgram(GLuint* ids); +} #endif // OPENGLSUPPORT_H diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index dd838d75..6b256e02 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -56,6 +56,7 @@ char* EmuDirectory; void emuStop(); +void* oglGetProcAddress(const char* proc); namespace Platform @@ -418,7 +419,7 @@ void Semaphore_Post(void* sema) void* GL_GetProcAddress(const char* proc) { - return NULL;//uiGLGetProcAddress(proc); + return oglGetProcAddress(proc); } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index bb08a87e..096b91ce 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -45,6 +45,7 @@ #include "NDS.h" #include "GBACart.h" +#include "OpenGLSupport.h" #include "GPU.h" #include "SPU.h" #include "Wifi.h" @@ -258,6 +259,54 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowEmuPause()), mainWindow->actPause, SLOT(trigger())); connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged())); + + initOpenGL(); +} + +void EmuThread::initOpenGL() +{ + QOpenGLContext* windowctx = mainWindow->getOGLContext(); + QSurfaceFormat format = windowctx->format(); + + oglSurface = new QOffscreenSurface(); + oglSurface->setFormat(format); + oglSurface->create(); + if (!oglSurface->isValid()) + { + // TODO handle this! + printf("oglSurface shat itself :(\n"); + delete oglSurface; + return; + } + + oglContext = new QOpenGLContext();//oglSurface); + oglContext->setFormat(oglSurface->format()); + oglContext->setShareContext(windowctx); + if (!oglContext->create()) + { + // TODO handle this! + printf("oglContext shat itself :(\n"); + delete oglContext; + delete oglSurface; + return; + } + + oglContext->moveToThread(this); +} + +void deinitOpenGL() +{ + // TODO!! +} + +void* oglGetProcAddress(const char* proc) +{ + return emuThread->oglGetProcAddress(proc); +} + +void* EmuThread::oglGetProcAddress(const char* proc) +{ + return (void*)oglContext->getProcAddress(proc); } void EmuThread::run() @@ -279,7 +328,11 @@ void EmuThread::run() } else*/ { - GPU3D::InitRenderer(false); + //GPU3D::InitRenderer(false); + bool res = oglContext->makeCurrent(oglSurface); + printf("good? %d\n", res); + OpenGL::Init(); + GPU3D::InitRenderer(res); } Input::Init(); @@ -755,6 +808,11 @@ void ScreenPanelGL::initializeGL() { initializeOpenGLFunctions(); + const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string + const GLubyte* version = glGetString(GL_VERSION); // version as a string + printf("OpenGL: renderer: %s\n", renderer); + printf("OpenGL: version: %s\n", version); + glClearColor(0, 0, 0, 1); screenShader = new QOpenGLShaderProgram(this); @@ -828,14 +886,24 @@ void ScreenPanelGL::paintGL() int frontbuf = GPU::FrontBuffer; glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, screenTexture); - if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + if (true) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + // hardware-accelerated render + GPU::GLCompositor::BindOutputTexture(); + } + else + { + // regular render + glBindTexture(GL_TEXTURE_2D, screenTexture); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } } GLint filter = Config::ScreenFilter ? GL_LINEAR : GL_NEAREST; @@ -1141,6 +1209,13 @@ MainWindow::~MainWindow() { } +QOpenGLContext* MainWindow::getOGLContext() +{ + // TODO: check whether we can actually pull this! + QOpenGLWidget* glpanel = (QOpenGLWidget*)panel; + return glpanel->context(); +} + void MainWindow::resizeEvent(QResizeEvent* event) { int w = event->size().width(); @@ -1755,6 +1830,13 @@ int main(int argc, char** argv) } #endif + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + format.setVersion(3, 2); + format.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(format); + audioSync = SDL_CreateCond(); audioSyncLock = SDL_CreateMutex(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 8a8c0417..67c93d03 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,11 @@ class EmuThread : public QThread public: explicit EmuThread(QObject* parent = nullptr); + void initOpenGL(); + void deinitOpenGL(); + + void* oglGetProcAddress(const char* proc); + void changeWindowTitle(char* title); // to be called from the UI thread @@ -67,6 +73,9 @@ private: volatile int EmuStatus; int PrevEmuStatus; int EmuRunning; + + QOffscreenSurface* oglSurface; + QOpenGLContext* oglContext; }; @@ -161,6 +170,8 @@ public: explicit MainWindow(QWidget* parent = nullptr); ~MainWindow(); + QOpenGLContext* getOGLContext(); + protected: void resizeEvent(QResizeEvent* event) override; From 24de8de5030c3a5a69c4df3c27db8076d3d0275d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 25 May 2020 18:28:11 +0200 Subject: [PATCH 077/105] flushing the john makes it a bit better --- src/GPU_OpenGL.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp index c9d31f10..99eb845e 100644 --- a/src/GPU_OpenGL.cpp +++ b/src/GPU_OpenGL.cpp @@ -196,6 +196,8 @@ void RenderFrame() glBindVertexArray(CompVertexArrayID); glDrawArrays(GL_TRIANGLES, 0, 4*3); } + + glFlush(); } void BindOutputTexture() From 4135ea374b37577694e2fe1b1346523d9255158c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 25 May 2020 18:38:10 +0200 Subject: [PATCH 078/105] fix colors --- src/GPU_OpenGL_shaders.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GPU_OpenGL_shaders.h b/src/GPU_OpenGL_shaders.h index ec975edb..20ac7673 100644 --- a/src/GPU_OpenGL_shaders.h +++ b/src/GPU_OpenGL_shaders.h @@ -155,7 +155,7 @@ void main() // TODO: filters - oColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); + oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0); } )"; @@ -310,7 +310,7 @@ void main() // TODO: filters - oColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); + oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0); } )"; @@ -855,7 +855,7 @@ void main() pixel.rgb <<= 2; pixel.rgb |= (pixel.rgb >> 6); - FragColor = vec4(vec3(pixel.rgb) / 255.0, 1.0); + FragColor = vec4(vec3(pixel.bgr) / 255.0, 1.0); } )"; From 256360aebba709d7b8565cd35bd9d42473219fd5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 27 May 2020 19:18:45 +0200 Subject: [PATCH 079/105] texture2D -> texture Intel driver threw a fit about it --- src/frontend/qt_sdl/main_shaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/qt_sdl/main_shaders.h b/src/frontend/qt_sdl/main_shaders.h index 2e57e591..96b9ecd0 100644 --- a/src/frontend/qt_sdl/main_shaders.h +++ b/src/frontend/qt_sdl/main_shaders.h @@ -55,7 +55,7 @@ out vec4 oColor; void main() { - vec4 pixel = texture2D(ScreenTex, fTexcoord); + vec4 pixel = texture(ScreenTex, fTexcoord); oColor = vec4(pixel.bgr, 1.0); } From ef2802ae31c4af965457216a190535b41efe749d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 27 May 2020 21:29:47 +0200 Subject: [PATCH 080/105] * use GL shim window instead of offscreen surface * disable vsync by default (we'll take care of it later) --- src/frontend/qt_sdl/main.cpp | 19 +++++++++++++++++-- src/frontend/qt_sdl/main.h | 13 ++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 096b91ce..8f2a61e8 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -268,7 +268,7 @@ void EmuThread::initOpenGL() QOpenGLContext* windowctx = mainWindow->getOGLContext(); QSurfaceFormat format = windowctx->format(); - oglSurface = new QOffscreenSurface(); + /*oglSurface = new QOffscreenSurface(); oglSurface->setFormat(format); oglSurface->create(); if (!oglSurface->isValid()) @@ -277,7 +277,8 @@ void EmuThread::initOpenGL() printf("oglSurface shat itself :(\n"); delete oglSurface; return; - } + }*/ + oglSurface = new GLShim(format); oglContext = new QOpenGLContext();//oglSurface); oglContext->setFormat(oglSurface->format()); @@ -957,6 +958,19 @@ void ScreenPanelGL::onScreenLayoutChanged() } +GLShim::GLShim(QSurfaceFormat& format) : QWindow() +{ + setSurfaceType(QSurface::OpenGLSurface); + setFormat(format); + create(); + hide(); +} + +GLShim::~GLShim() +{ +} + + MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("melonDS " MELONDS_VERSION); @@ -1835,6 +1849,7 @@ int main(int argc, char** argv) format.setStencilBufferSize(8); format.setVersion(3, 2); format.setProfile(QSurfaceFormat::CoreProfile); + format.setSwapInterval(0); QSurfaceFormat::setDefaultFormat(format); audioSync = SDL_CreateCond(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 67c93d03..2a249606 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,7 @@ private: int PrevEmuStatus; int EmuRunning; - QOffscreenSurface* oglSurface; + QSurface* oglSurface; QOpenGLContext* oglContext; }; @@ -162,6 +163,16 @@ private: }; +class GLShim : public QWindow +{ + Q_OBJECT + +public: + explicit GLShim(QSurfaceFormat& format); + ~GLShim(); +}; + + class MainWindow : public QMainWindow { Q_OBJECT From e8849db78abe4db518c7f324323b88f478acc69a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 27 May 2020 21:40:02 +0200 Subject: [PATCH 081/105] we don't need a GLShim. blarg. I don't understand this anymore. --- src/GPU3D_OpenGL.cpp | 1 - src/frontend/qt_sdl/main.cpp | 18 ++---------------- src/frontend/qt_sdl/main.h | 12 +----------- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index dcc4b6b2..74760e5b 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -199,7 +199,6 @@ bool Init() glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); - glDepthRange(0, 1); glClearDepth(1.0); diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 8f2a61e8..f282310e 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -268,7 +268,7 @@ void EmuThread::initOpenGL() QOpenGLContext* windowctx = mainWindow->getOGLContext(); QSurfaceFormat format = windowctx->format(); - /*oglSurface = new QOffscreenSurface(); + oglSurface = new QOffscreenSurface(); oglSurface->setFormat(format); oglSurface->create(); if (!oglSurface->isValid()) @@ -277,8 +277,7 @@ void EmuThread::initOpenGL() printf("oglSurface shat itself :(\n"); delete oglSurface; return; - }*/ - oglSurface = new GLShim(format); + } oglContext = new QOpenGLContext();//oglSurface); oglContext->setFormat(oglSurface->format()); @@ -958,19 +957,6 @@ void ScreenPanelGL::onScreenLayoutChanged() } -GLShim::GLShim(QSurfaceFormat& format) : QWindow() -{ - setSurfaceType(QSurface::OpenGLSurface); - setFormat(format); - create(); - hide(); -} - -GLShim::~GLShim() -{ -} - - MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("melonDS " MELONDS_VERSION); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 2a249606..8759e95d 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -75,7 +75,7 @@ private: int PrevEmuStatus; int EmuRunning; - QSurface* oglSurface; + QOffscreenSurface* oglSurface; QOpenGLContext* oglContext; }; @@ -163,16 +163,6 @@ private: }; -class GLShim : public QWindow -{ - Q_OBJECT - -public: - explicit GLShim(QSurfaceFormat& format); - ~GLShim(); -}; - - class MainWindow : public QMainWindow { Q_OBJECT From 0a68eb78039a7a27b16d389844beeebed139f864 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 11:52:12 +0200 Subject: [PATCH 082/105] make it hiDPI compliant (I hope) also misc tweaks --- src/GPU3D_OpenGL.cpp | 2 +- src/OpenGLSupport.h | 5 +++++ src/frontend/qt_sdl/AudioSettingsDialog.ui | 7 +++++-- src/frontend/qt_sdl/main.cpp | 6 +++--- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index 74760e5b..9a78504d 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -1236,7 +1236,7 @@ void RenderFrame() glBlitFramebuffer(0, 0, ScreenW, ScreenH, 0, 0, ScreenW/2, ScreenH/2, GL_COLOR_BUFFER_BIT, GL_LINEAR); } - glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[FrontBuffer]); + //glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[FrontBuffer]); FrontBuffer = FrontBuffer ? 0 : 1; } diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h index 360d2156..edf7edad 100644 --- a/src/OpenGLSupport.h +++ b/src/OpenGLSupport.h @@ -102,6 +102,11 @@ func(GLGETUNIFORMLOCATION, glGetUniformLocation); \ func(GLGETUNIFORMBLOCKINDEX, glGetUniformBlockIndex); \ \ + func(GLFENCESYNC, glFenceSync); \ + func(GLDELETESYNC, glDeleteSync); \ + func(GLWAITSYNC, glWaitSync); \ + func(GLCLIENTWAITSYNC, glClientWaitSync); \ + \ func(GLDRAWBUFFERS, glDrawBuffers); \ \ func(GLBLENDFUNCSEPARATE, glBlendFuncSeparate); \ diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.ui b/src/frontend/qt_sdl/AudioSettingsDialog.ui index c4e993ee..9ae8baad 100644 --- a/src/frontend/qt_sdl/AudioSettingsDialog.ui +++ b/src/frontend/qt_sdl/AudioSettingsDialog.ui @@ -60,12 +60,15 @@ 0 + + <html><head/><body><p>Forward a WAV file to the emulated microphone.</p><p>This input mode is activated by holding the microphone hotkey (see Input and Hotkeys).</p></body></html> + - <html><head/><body><p>Forward a WAV file to the emulated microphone.</p></body></html> + <html><head/><body><p>Forward a WAV file to the emulated microphone.</p><p>This input mode is activated by holding the microphone hotkey (see Input and Hotkeys).</p></body></html> WAV file: @@ -92,7 +95,7 @@ - <html><head/><body><p>Noise will be forwarded to the emulated microphone, simulating blowing into the microphone.</p></body></html> + <html><head/><body><p>Noise will be forwarded to the emulated microphone, simulating blowing into the microphone.</p><p>This input mode is activated by holding the microphone hotkey (see Input and Hotkeys).</p></body></html> Blow noise diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index f282310e..20084ff7 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -874,15 +874,15 @@ void ScreenPanelGL::paintGL() { int w = width(); int h = height(); + float factor = devicePixelRatioF(); glClear(GL_COLOR_BUFFER_BIT); - // TODO: check hiDPI compliance of this - glViewport(0, 0, w, h); + glViewport(0, 0, w*factor, h*factor); screenShader->bind(); - screenShader->setUniformValue("uScreenSize", (float)w, (float)h); + screenShader->setUniformValue("uScreenSize", (float)w*factor, (float)h*factor); int frontbuf = GPU::FrontBuffer; glActiveTexture(GL_TEXTURE0); From 695839bb0ef8173ad2a549dd7766186fa65e949a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 12:32:50 +0200 Subject: [PATCH 083/105] lay base for video settings dialog --- src/frontend/qt_sdl/CMakeLists.txt | 1 + src/frontend/qt_sdl/VideoSettingsDialog.cpp | 67 ++++++ src/frontend/qt_sdl/VideoSettingsDialog.h | 67 ++++++ src/frontend/qt_sdl/VideoSettingsDialog.ui | 220 ++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 3 +- 5 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 src/frontend/qt_sdl/VideoSettingsDialog.cpp create mode 100644 src/frontend/qt_sdl/VideoSettingsDialog.h create mode 100644 src/frontend/qt_sdl/VideoSettingsDialog.ui diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 5778b403..a4bb5f53 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -5,6 +5,7 @@ SET(SOURCES_QT_SDL main_shaders.h EmuSettingsDialog.cpp InputConfigDialog.cpp + VideoSettingsDialog.cpp AudioSettingsDialog.cpp Input.cpp Platform.cpp diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp new file mode 100644 index 00000000..c0ec42a9 --- /dev/null +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -0,0 +1,67 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include + +#include "types.h" +#include "Platform.h" +#include "Config.h" +#include "PlatformConfig.h" + +#include "VideoSettingsDialog.h" +#include "ui_VideoSettingsDialog.h" + + +VideoSettingsDialog* VideoSettingsDialog::currentDlg = nullptr; + + +VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::VideoSettingsDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + // + + grp3DRenderer = new QButtonGroup(this); + grp3DRenderer->addButton(ui->rb3DSoftware, 0); + grp3DRenderer->addButton(ui->rb3DOpenGL, 1); + //connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int))); +} + +VideoSettingsDialog::~VideoSettingsDialog() +{ + delete ui; +} + +void VideoSettingsDialog::on_VideoSettingsDialog_accepted() +{ + // + Config::Save(); + + closeDlg(); +} + +void VideoSettingsDialog::on_VideoSettingsDialog_rejected() +{ + // + + closeDlg(); +} + +// diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.h b/src/frontend/qt_sdl/VideoSettingsDialog.h new file mode 100644 index 00000000..d64cee27 --- /dev/null +++ b/src/frontend/qt_sdl/VideoSettingsDialog.h @@ -0,0 +1,67 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef VIDEOSETTINGSDIALOG_H +#define VIDEOSETTINGSDIALOG_H + +#include +#include + +namespace Ui { class VideoSettingsDialog; } +class VideoSettingsDialog; + +class VideoSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit VideoSettingsDialog(QWidget* parent); + ~VideoSettingsDialog(); + + static VideoSettingsDialog* currentDlg; + static VideoSettingsDialog* openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return currentDlg; + } + + currentDlg = new VideoSettingsDialog(parent); + currentDlg->show(); + return currentDlg; + } + static void closeDlg() + { + currentDlg = nullptr; + } + +private slots: + void on_VideoSettingsDialog_accepted(); + void on_VideoSettingsDialog_rejected(); + + // + +private: + Ui::VideoSettingsDialog* ui; + + QButtonGroup* grp3DRenderer; +}; + +#endif // VIDEOSETTINGSDIALOG_H + diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.ui b/src/frontend/qt_sdl/VideoSettingsDialog.ui new file mode 100644 index 00000000..06670e5a --- /dev/null +++ b/src/frontend/qt_sdl/VideoSettingsDialog.ui @@ -0,0 +1,220 @@ + + + VideoSettingsDialog + + + + 0 + 0 + 482 + 237 + + + + Video settings - melonDS + + + + + + OpenGL renderer + + + + + + Internal resolution: + + + + + + + <html><head/><body><p>The resolution at which the 3D graphics will be rendered. Higher resolutions improve graphics quality when the main window is enlarged, but may also cause glitches.</p></body></html> + + + + + + + + + + Software renderer + + + + + + <html><head/><body><p>Run the software renderer on a separate thread. Yields better performance on multi-core CPUs.</p></body></html> + + + Use separate thread + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Display settings + + + + + + + 0 + 0 + + + + <html><head/><body><p>The interval at which to synchronize to the monitor's refresh rate. Set to 1 for a 60Hz monitor, 2 for 120Hz, ...</p></body></html> + + + VSync interval: + + + + + + + <html><head/><body><p>The interval at which to synchronize to the monitor's refresh rate. Set to 1 for a 60Hz monitor, 2 for 120Hz, ...</p></body></html> + + + 1 + + + 20 + + + + + + + <html><head/><body><p>Use OpenGL to draw the DS screens to the main window. May result in better frame pacing. Mandatory when using the OpenGL 3D renderer.</p></body></html> + + + OpenGL display + + + + + + + <html><head/><body><p>When using OpenGL, synchronize the video output to your monitor's refresh rate.</p></body></html> + + + VSync + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + <html><head/><body><p>The OpenGL renderer may be faster than software and supports graphical enhancements, but is more prone to glitches.</p></body></html> + + + OpenGL + + + + + + + <html><head/><body><p>The software renderer is more accurate and less prone to rendering glitches, but requires more CPU power.</p></body></html> + + + Software + + + + + + + 3D renderer: + + + + + + + + + + + + buttonBox + accepted() + VideoSettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + VideoSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 20084ff7..ae4bcf3c 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -36,6 +36,7 @@ #include "Input.h" #include "EmuSettingsDialog.h" #include "InputConfigDialog.h" +#include "VideoSettingsDialog.h" #include "AudioSettingsDialog.h" #include "types.h" @@ -1573,7 +1574,7 @@ void MainWindow::onInputConfigFinished(int res) void MainWindow::onOpenVideoSettings() { - // + VideoSettingsDialog* dlg = VideoSettingsDialog::openDlg(this); } void MainWindow::onOpenAudioSettings() From 5005a7c3f0f78c4684dbdcde0d88ae48050ab6fe Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 13:21:25 +0200 Subject: [PATCH 084/105] populate the dialog. also add setting for vsync interval. --- src/frontend/qt_sdl/PlatformConfig.cpp | 6 ++++-- src/frontend/qt_sdl/PlatformConfig.h | 1 + src/frontend/qt_sdl/VideoSettingsDialog.cpp | 19 ++++++++++++++++++- src/frontend/qt_sdl/VideoSettingsDialog.h | 7 +++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/frontend/qt_sdl/PlatformConfig.cpp b/src/frontend/qt_sdl/PlatformConfig.cpp index 28c224d5..03fd2ac0 100644 --- a/src/frontend/qt_sdl/PlatformConfig.cpp +++ b/src/frontend/qt_sdl/PlatformConfig.cpp @@ -45,6 +45,7 @@ int ScreenFilter; int ScreenUseGL; int ScreenVSync; +int ScreenVSyncInterval; int LimitFPS; int AudioSync; @@ -124,8 +125,9 @@ ConfigEntry PlatformConfigFile[] = {"IntegerScaling", 0, &IntegerScaling, 0, NULL, 0}, {"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0}, - {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, - {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, + {"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0}, + {"ScreenVSync", 0, &ScreenVSync, 0, NULL, 0}, + {"ScreenVSyncInterval", 0, &ScreenVSyncInterval, 1, NULL, 0}, {"LimitFPS", 0, &LimitFPS, 0, NULL, 0}, {"AudioSync", 0, &AudioSync, 1, NULL, 0}, diff --git a/src/frontend/qt_sdl/PlatformConfig.h b/src/frontend/qt_sdl/PlatformConfig.h index 539f9a45..cc288b65 100644 --- a/src/frontend/qt_sdl/PlatformConfig.h +++ b/src/frontend/qt_sdl/PlatformConfig.h @@ -58,6 +58,7 @@ extern int ScreenFilter; extern int ScreenUseGL; extern int ScreenVSync; +extern int ScreenVSyncInterval; extern int LimitFPS; extern int AudioSync; diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index c0ec42a9..0aeb1548 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -36,12 +36,29 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - // + oldRenderer = Config::_3DRenderer; + oldGLDisplay = Config::ScreenUseGL; + oldVSync = Config::ScreenVSync; + oldVSyncInterval = Config::ScreenVSyncInterval; + oldSoftThreaded = Config::Threaded3D; + oldGLScale = Config::GL_ScaleFactor; grp3DRenderer = new QButtonGroup(this); grp3DRenderer->addButton(ui->rb3DSoftware, 0); grp3DRenderer->addButton(ui->rb3DOpenGL, 1); //connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int))); + grp3DRenderer->button(Config::_3DRenderer)->setChecked(true); + + ui->cbGLDisplay->setChecked(Config::ScreenUseGL != 0); + + ui->cbVSync->setChecked(Config::ScreenVSync != 0); + ui->sbVSyncInterval->setValue(Config::ScreenVSyncInterval); + + ui->cbSoftwareThreaded->setChecked(Config::Threaded3D != 0); + + for (int i = 1; i <= 16; i++) + ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i), QVariant(i)); + ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor); } VideoSettingsDialog::~VideoSettingsDialog() diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.h b/src/frontend/qt_sdl/VideoSettingsDialog.h index d64cee27..05dfecbf 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.h +++ b/src/frontend/qt_sdl/VideoSettingsDialog.h @@ -61,6 +61,13 @@ private: Ui::VideoSettingsDialog* ui; QButtonGroup* grp3DRenderer; + + int oldRenderer; + int oldGLDisplay; + int oldVSync; + int oldVSyncInterval; + int oldSoftThreaded; + int oldGLScale; }; #endif // VIDEOSETTINGSDIALOG_H From 0804ab3c783363e28229a2028dc70b4238cb1802 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 15:53:32 +0200 Subject: [PATCH 085/105] * rework GPU's settings interface, make it config-agnostic * make video settings dialog functional, sorta * fix dialogs that were resizable --- src/GPU.cpp | 78 +++++++++- src/GPU.h | 22 ++- src/GPU2D.cpp | 14 +- src/GPU2D.h | 2 +- src/GPU3D.cpp | 57 +------- src/GPU3D.h | 7 +- src/GPU3D_OpenGL.cpp | 17 +-- src/GPU3D_Soft.cpp | 10 +- src/GPU_OpenGL.cpp | 39 +++-- src/frontend/qt_sdl/AudioSettingsDialog.ui | 9 ++ src/frontend/qt_sdl/VideoSettingsDialog.cpp | 79 +++++++++- src/frontend/qt_sdl/VideoSettingsDialog.h | 9 +- src/frontend/qt_sdl/VideoSettingsDialog.ui | 9 ++ src/frontend/qt_sdl/main.cpp | 152 ++++++++++++++------ src/frontend/qt_sdl/main.h | 5 + 15 files changed, 342 insertions(+), 167 deletions(-) diff --git a/src/GPU.cpp b/src/GPU.cpp index 993086eb..56db0e27 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -78,6 +78,7 @@ u8* VRAMPtr_BOBJ[0x8]; int FrontBuffer; u32* Framebuffer[2][2]; +int Renderer; bool Accelerated; GPU2D* GPU2D_A; @@ -93,8 +94,8 @@ bool Init() FrontBuffer = 0; Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL; Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL; + Renderer = 0; Accelerated = false; - SetDisplaySettings(false); return true; } @@ -182,6 +183,8 @@ void Reset() int backbuf = FrontBuffer ? 0 : 1; GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]); GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]); + + ResetRenderer(); } void Stop() @@ -274,8 +277,65 @@ void AssignFramebuffers() } } -void SetDisplaySettings(bool accel) +void InitRenderer(int renderer) { + if (renderer == 1) + { + if (!GLCompositor::Init()) + { + renderer = 0; + } + else if (!GPU3D::GLRenderer::Init()) + { + GLCompositor::DeInit(); + renderer = 0; + } + } + + if (renderer == 0) + { + GPU3D::SoftRenderer::Init(); + } + + Renderer = renderer; + Accelerated = renderer != 0; +} + +void DeInitRenderer() +{ + if (Renderer == 0) + { + GPU3D::SoftRenderer::DeInit(); + } + else + { + GPU3D::GLRenderer::DeInit(); + GLCompositor::DeInit(); + } +} + +void ResetRenderer() +{ + if (Renderer == 0) + { + GPU3D::SoftRenderer::Reset(); + } + else + { + GLCompositor::Reset(); + GPU3D::GLRenderer::Reset(); + } +} + +void SetRenderSettings(int renderer, RenderSettings& settings) +{ + if (renderer != Renderer) + { + DeInitRenderer(); + InitRenderer(renderer); + } + + bool accel = Accelerated; int fbsize; if (accel) fbsize = (256*3 + 1) * 192; else fbsize = 256 * 192; @@ -296,10 +356,18 @@ void SetDisplaySettings(bool accel) AssignFramebuffers(); - GPU2D_A->SetDisplaySettings(accel); - GPU2D_B->SetDisplaySettings(accel); + GPU2D_A->SetRenderSettings(accel); + GPU2D_B->SetRenderSettings(accel); - Accelerated = accel; + if (Renderer == 0) + { + GPU3D::SoftRenderer::SetRenderSettings(settings); + } + else + { + GLCompositor::SetRenderSettings(settings); + GPU3D::GLRenderer::SetRenderSettings(settings); + } } diff --git a/src/GPU.h b/src/GPU.h index e85a5b4c..039e0651 100644 --- a/src/GPU.h +++ b/src/GPU.h @@ -20,7 +20,6 @@ #define GPU_H #include "GPU2D.h" -#include "GPU3D.h" namespace GPU { @@ -72,6 +71,17 @@ extern u32* Framebuffer[2][2]; extern GPU2D* GPU2D_A; extern GPU2D* GPU2D_B; +extern int Renderer; + + +typedef struct +{ + bool Soft_Threaded; + + int GL_ScaleFactor; + +} RenderSettings; + bool Init(); void DeInit(); @@ -80,7 +90,11 @@ void Stop(); void DoSavestate(Savestate* file); -void SetDisplaySettings(bool accel); +void InitRenderer(int renderer); +void DeInitRenderer(); +void ResetRenderer(); + +void SetRenderSettings(int renderer, RenderSettings& settings); u8* GetUniqueBankPtr(u32 mask, u32 offset); @@ -429,7 +443,7 @@ bool Init(); void DeInit(); void Reset(); -void UpdateDisplaySettings(); +void SetRenderSettings(RenderSettings& settings); void RenderFrame(); void BindOutputTexture(); @@ -438,4 +452,6 @@ void BindOutputTexture(); } +#include "GPU3D.h" + #endif diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 6f950b73..604a4eef 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -202,16 +202,8 @@ void GPU2D::DoSavestate(Savestate* file) file->Var32(&CaptureCnt); } - if (file->IsAtleastVersion(2, 1)) - { - file->Var32(&Win0Active); - file->Var32(&Win1Active); - } - else - { - Win0Active = 0; - Win1Active = 0; - } + file->Var32(&Win0Active); + file->Var32(&Win1Active); if (!file->Saving) { @@ -232,7 +224,7 @@ void GPU2D::SetFramebuffer(u32* buf) Framebuffer = buf; } -void GPU2D::SetDisplaySettings(bool accel) +void GPU2D::SetRenderSettings(bool accel) { Accelerated = accel; diff --git a/src/GPU2D.h b/src/GPU2D.h index c4bd2f92..521adf01 100644 --- a/src/GPU2D.h +++ b/src/GPU2D.h @@ -31,7 +31,7 @@ public: void SetEnabled(bool enable) { Enabled = enable; } void SetFramebuffer(u32* buf); - void SetDisplaySettings(bool accel); + void SetRenderSettings(bool accel); u8 Read8(u32 addr); u16 Read16(u32 addr); diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index e687e37d..bd277838 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -157,8 +157,6 @@ u32 NumCommands, CurCommand, ParamCount, TotalParams; bool GeometryEnabled; bool RenderingEnabled; -int Renderer; - u32 DispCnt; u8 AlphaRefVal, AlphaRef; @@ -280,17 +278,11 @@ bool Init() CmdStallQueue = new FIFO(64); - Renderer = -1; - // SetRenderer() will be called to set it up later - return true; } void DeInit() { - if (Renderer == 0) SoftRenderer::DeInit(); - else GLRenderer::DeInit(); - delete CmdFIFO; delete CmdPIPE; @@ -391,8 +383,6 @@ void Reset() FlushAttributes = 0; ResetRenderingState(); - if (Renderer == 0) SoftRenderer::Reset(); - else GLRenderer::Reset(); } void DoSavestate(Savestate* file) @@ -607,43 +597,6 @@ void SetEnabled(bool geometry, bool rendering) } -int InitRenderer(bool hasGL) -{ - int renderer = hasGL ? Config::_3DRenderer : 0; - - if (renderer == 1) - { - if (!GLRenderer::Init()) - renderer = 0; - } -printf("renderer: %d\n", renderer); - if (renderer == 0) SoftRenderer::Init(); - - Renderer = renderer; - UpdateRendererConfig(); - GPU::SetDisplaySettings(Renderer != 0); - return renderer; -} - -void DeInitRenderer() -{ - if (Renderer == 0) SoftRenderer::DeInit(); - else GLRenderer::DeInit(); -} - -void UpdateRendererConfig() -{ - if (Renderer == 0) - { - SoftRenderer::SetupRenderThread(); - } - else - { - GLRenderer::UpdateDisplaySettings(); - } -} - - void MatrixLoadIdentity(s32* m) { @@ -2470,7 +2423,7 @@ void CheckFIFODMA() void VCount144() { - if (Renderer == 0) SoftRenderer::VCount144(); + if (GPU::Renderer == 0) SoftRenderer::VCount144(); } @@ -2552,14 +2505,14 @@ void VBlank() void VCount215() { - if (Renderer == 0) SoftRenderer::RenderFrame(); - else GLRenderer::RenderFrame(); + if (GPU::Renderer == 0) SoftRenderer::RenderFrame(); + else GLRenderer::RenderFrame(); } u32* GetLine(int line) { - if (Renderer == 0) return SoftRenderer::GetLine(line); - else return GLRenderer::GetLine(line); + if (GPU::Renderer == 0) return SoftRenderer::GetLine(line); + else return GLRenderer::GetLine(line); } diff --git a/src/GPU3D.h b/src/GPU3D.h index 1fd3383e..71f069d0 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -102,10 +102,6 @@ void DoSavestate(Savestate* file); void SetEnabled(bool geometry, bool rendering); -int InitRenderer(bool hasGL); -void DeInitRenderer(); -void UpdateRendererConfig(); - void ExecuteCommand(); s32 CyclesToRunFor(); @@ -134,6 +130,7 @@ bool Init(); void DeInit(); void Reset(); +void SetRenderSettings(GPU::RenderSettings& settings); void SetupRenderThread(); void VCount144(); @@ -149,7 +146,7 @@ bool Init(); void DeInit(); void Reset(); -void UpdateDisplaySettings(); +void SetRenderSettings(GPU::RenderSettings& settings); void RenderFrame(); void PrepareCaptureFrame(); diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp index 9a78504d..8a068741 100644 --- a/src/GPU3D_OpenGL.cpp +++ b/src/GPU3D_OpenGL.cpp @@ -372,19 +372,11 @@ bool Init() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 1024, 48, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL); - if (!GPU::GLCompositor::Init()) - { - // TODO: clean up things? fail more gracefully?? - return false; - } - return true; } void DeInit() { - GPU::GLCompositor::DeInit(); - glDeleteTextures(1, &TexMemID); glDeleteTextures(1, &TexPalMemID); @@ -407,13 +399,12 @@ void DeInit() void Reset() { - GPU::GLCompositor::Reset(); } -void UpdateDisplaySettings() +void SetRenderSettings(GPU::RenderSettings& settings) { - int scale = Config::GL_ScaleFactor; - bool antialias = false; //Config::GL_Antialias; + int scale = settings.GL_ScaleFactor; + bool antialias = false; // REMOVE ME! if (antialias) scale *= 2; @@ -490,8 +481,6 @@ void UpdateDisplaySettings() //glLineWidth(scale); //glLineWidth(1.5); - - GPU::GLCompositor::UpdateDisplaySettings(); } diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 8397898d..e9d8e75f 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -60,6 +60,7 @@ bool Enabled; // threading +bool Threaded; void* RenderThread; bool RenderThreadRunning; bool RenderThreadRendering; @@ -83,7 +84,7 @@ void StopRenderThread() void SetupRenderThread() { - if (Config::Threaded3D) + if (Threaded) { if (!RenderThreadRunning) { @@ -112,6 +113,7 @@ bool Init() Sema_RenderDone = Platform::Semaphore_Create(); Sema_ScanlineCount = Platform::Semaphore_Create(); + Threaded = false; RenderThreadRunning = false; RenderThreadRendering = false; @@ -138,6 +140,12 @@ void Reset() SetupRenderThread(); } +void SetRenderSettings(GPU::RenderSettings& settings) +{ + Threaded = settings.Soft_Threaded; + SetupRenderThread(); +} + // Notes on the interpolator: diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp index 99eb845e..1cb68640 100644 --- a/src/GPU_OpenGL.cpp +++ b/src/GPU_OpenGL.cpp @@ -142,9 +142,9 @@ void Reset() } -void UpdateDisplaySettings() +void SetRenderSettings(RenderSettings& settings) { - int scale = Config::GL_ScaleFactor; + int scale = settings.GL_ScaleFactor; Scale = scale; ScreenW = 256 * scale; @@ -175,28 +175,25 @@ void RenderFrame() OpenGL::UseShaderProgram(CompShader[0]); glUniform1ui(CompScaleLoc[0], Scale); - //if (RunningSomething) + int frontbuf = GPU::FrontBuffer; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) { - int frontbuf = GPU::FrontBuffer; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); - - if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) - { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); - } - - glActiveTexture(GL_TEXTURE1); - GPU3D::GLRenderer::SetupAccelFrame(); - - glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); - glBindVertexArray(CompVertexArrayID); - glDrawArrays(GL_TRIANGLES, 0, 4*3); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); } + glActiveTexture(GL_TEXTURE1); + GPU3D::GLRenderer::SetupAccelFrame(); + + glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); + glBindVertexArray(CompVertexArrayID); + glDrawArrays(GL_TRIANGLES, 0, 4*3); + glFlush(); } diff --git a/src/frontend/qt_sdl/AudioSettingsDialog.ui b/src/frontend/qt_sdl/AudioSettingsDialog.ui index 9ae8baad..bcaf937c 100644 --- a/src/frontend/qt_sdl/AudioSettingsDialog.ui +++ b/src/frontend/qt_sdl/AudioSettingsDialog.ui @@ -10,10 +10,19 @@ 230 + + + 0 + 0 + + Audio settings - melonDS + + QLayout::SetFixedSize + diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index 0aeb1548..09f1ab45 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -46,7 +46,7 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( grp3DRenderer = new QButtonGroup(this); grp3DRenderer->addButton(ui->rb3DSoftware, 0); grp3DRenderer->addButton(ui->rb3DOpenGL, 1); - //connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int))); + connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int))); grp3DRenderer->button(Config::_3DRenderer)->setChecked(true); ui->cbGLDisplay->setChecked(Config::ScreenUseGL != 0); @@ -57,8 +57,21 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( ui->cbSoftwareThreaded->setChecked(Config::Threaded3D != 0); for (int i = 1; i <= 16; i++) - ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i), QVariant(i)); - ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor); + ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i)); + ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1); + + if (Config::_3DRenderer == 0) + { + ui->cbGLDisplay->setEnabled(true); + ui->cbSoftwareThreaded->setEnabled(true); + ui->cbxGLResolution->setEnabled(false); + } + else + { + ui->cbGLDisplay->setEnabled(false); + ui->cbSoftwareThreaded->setEnabled(false); + ui->cbxGLResolution->setEnabled(true); + } } VideoSettingsDialog::~VideoSettingsDialog() @@ -68,7 +81,6 @@ VideoSettingsDialog::~VideoSettingsDialog() void VideoSettingsDialog::on_VideoSettingsDialog_accepted() { - // Config::Save(); closeDlg(); @@ -76,9 +88,64 @@ void VideoSettingsDialog::on_VideoSettingsDialog_accepted() void VideoSettingsDialog::on_VideoSettingsDialog_rejected() { - // + bool old_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + + Config::_3DRenderer = oldRenderer; + Config::ScreenUseGL = oldGLDisplay; + Config::ScreenVSync = oldVSync; + Config::ScreenVSyncInterval = oldVSyncInterval; + Config::Threaded3D = oldSoftThreaded; + Config::GL_ScaleFactor = oldGLScale; + + bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + emit updateVideoSettings(old_gl != new_gl); closeDlg(); } -// +void VideoSettingsDialog::onChange3DRenderer(int renderer) +{ + bool old_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + + Config::_3DRenderer = renderer; + + if (renderer == 0) + { + ui->cbGLDisplay->setEnabled(true); + ui->cbSoftwareThreaded->setEnabled(true); + ui->cbxGLResolution->setEnabled(false); + } + else + { + ui->cbGLDisplay->setEnabled(false); + ui->cbSoftwareThreaded->setEnabled(false); + ui->cbxGLResolution->setEnabled(true); + } + + bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + emit updateVideoSettings(old_gl != new_gl); +} + +void VideoSettingsDialog::on_cbGLDisplay_stateChanged(int state) +{ + bool old_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + + Config::ScreenUseGL = (state != 0); + + bool new_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + emit updateVideoSettings(old_gl != new_gl); +} + +void VideoSettingsDialog::on_cbSoftwareThreaded_stateChanged(int state) +{ + Config::Threaded3D = (state != 0); + + emit updateVideoSettings(false); +} + +void VideoSettingsDialog::on_cbxGLResolution_currentIndexChanged(int idx) +{ + Config::GL_ScaleFactor = idx+1; + + emit updateVideoSettings(false); +} diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.h b/src/frontend/qt_sdl/VideoSettingsDialog.h index 05dfecbf..2f6d17cc 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.h +++ b/src/frontend/qt_sdl/VideoSettingsDialog.h @@ -51,11 +51,18 @@ public: currentDlg = nullptr; } +signals: + void updateVideoSettings(bool glchange); + private slots: void on_VideoSettingsDialog_accepted(); void on_VideoSettingsDialog_rejected(); - // + void onChange3DRenderer(int renderer); + void on_cbGLDisplay_stateChanged(int state); + void on_cbxGLResolution_currentIndexChanged(int idx); + + void on_cbSoftwareThreaded_stateChanged(int state); private: Ui::VideoSettingsDialog* ui; diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.ui b/src/frontend/qt_sdl/VideoSettingsDialog.ui index 06670e5a..6cdd5d82 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.ui +++ b/src/frontend/qt_sdl/VideoSettingsDialog.ui @@ -10,10 +10,19 @@ 237 + + + 0 + 0 + + Video settings - melonDS + + QLayout::SetFixedSize + diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index ae4bcf3c..658ae8bf 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -68,6 +68,10 @@ EmuThread* emuThread; int autoScreenSizing = 0; +int videoRenderer; +GPU::RenderSettings videoSettings; +bool videoSettingsDirty; + SDL_AudioDeviceID audioDevice; int audioFreq; SDL_cond* audioSync; @@ -251,9 +255,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) EmuRunning = 2; RunningSomething = false; - //connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(update())); connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(update())); - //connect(this, SIGNAL(windowUpdate()), mainWindow, SLOT(repaint())); connect(this, SIGNAL(windowTitleChange(QString)), mainWindow, SLOT(onTitleUpdate(QString))); connect(this, SIGNAL(windowEmuStart()), mainWindow, SLOT(onEmuStart())); connect(this, SIGNAL(windowEmuStop()), mainWindow, SLOT(onEmuStop())); @@ -312,6 +314,7 @@ void* EmuThread::oglGetProcAddress(const char* proc) void EmuThread::run() { + bool hasOGL = mainWindow->hasOGL; u32 mainScreenPos[3]; NDS::Init(); @@ -321,20 +324,20 @@ void EmuThread::run() mainScreenPos[2] = 0; autoScreenSizing = 0; - /*if (Screen_UseGL) + videoSettingsDirty = false; + videoSettings.Soft_Threaded = Config::Threaded3D != 0; + videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor; + + if (hasOGL) { - uiGLMakeContextCurrent(GLContext); - GPU3D::InitRenderer(true); - uiGLMakeContextCurrent(NULL); - } - else*/ - { - //GPU3D::InitRenderer(false); - bool res = oglContext->makeCurrent(oglSurface); - printf("good? %d\n", res); - OpenGL::Init(); - GPU3D::InitRenderer(res); + oglContext->makeCurrent(oglSurface); + videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0; } + else + videoRenderer = 0; + + GPU::InitRenderer(videoRenderer); + GPU::SetRenderSettings(videoRenderer, videoSettings); Input::Init(); @@ -377,6 +380,29 @@ void EmuThread::run() { EmuStatus = 1; + // update render settings if needed + if (videoSettingsDirty) + { + if (hasOGL != mainWindow->hasOGL) + { + hasOGL = mainWindow->hasOGL; + if (hasOGL) + { + oglContext->makeCurrent(oglSurface); + videoRenderer = OpenGL::Init() ? Config::_3DRenderer : 0; + } + else + videoRenderer = 0; + } + else + videoRenderer = hasOGL ? Config::_3DRenderer : 0; + + videoSettingsDirty = false; + videoSettings.Soft_Threaded = Config::Threaded3D != 0; + videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor; + GPU::SetRenderSettings(videoRenderer, videoSettings); + } + // process input and hotkeys NDS::SetKeyMask(Input::InputMask); @@ -390,12 +416,6 @@ void EmuThread::run() // microphone input micProcess(); - /*if (Screen_UseGL) - { - uiGLBegin(GLContext); - uiGLMakeContextCurrent(GLContext); - }*/ - // auto screen layout if (Config::ScreenSizing == 3) { @@ -435,12 +455,6 @@ void EmuThread::run() if (EmuRunning == 0) break; - /*if (Screen_UseGL) - { - GLScreen_DrawScreen(); - uiGLEnd(GLContext); - } - uiAreaQueueRedrawAll(MainDrawArea);*/ emit windowUpdate(); bool fastforward = Input::HotkeyDown(HK_FastForward); @@ -513,18 +527,8 @@ void EmuThread::run() lastmeasuretick = lasttick; fpslimitcount = 0; - /*if (Screen_UseGL) - { - uiGLBegin(GLContext); - uiGLMakeContextCurrent(GLContext); - GLScreen_DrawScreen(); - uiGLEnd(GLContext); - } - uiAreaQueueRedrawAll(MainDrawArea);*/ emit windowUpdate(); - //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); - EmuStatus = EmuRunning; sprintf(melontitle, "melonDS " MELONDS_VERSION); @@ -536,8 +540,7 @@ void EmuThread::run() EmuStatus = 0; - //if (Screen_UseGL) uiGLMakeContextCurrent(GLContext); - + GPU::DeInitRenderer(); NDS::DeInit(); //Platform::LAN_DeInit(); @@ -549,7 +552,8 @@ void EmuThread::run() else OSD::DeInit(false);*/ - //if (Screen_UseGL) uiGLMakeContextCurrent(NULL); + if (hasOGL) + oglContext->doneCurrent(); } void EmuThread::changeWindowTitle(char* title) @@ -794,6 +798,7 @@ ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) ScreenPanelGL::~ScreenPanelGL() { // CHECKME!!!! + // ALSO TODO: CLEANUP delete screenShader; } @@ -888,7 +893,7 @@ void ScreenPanelGL::paintGL() int frontbuf = GPU::FrontBuffer; glActiveTexture(GL_TEXTURE0); - if (true) + if (GPU::Renderer != 0) { // hardware-accelerated render GPU::GLCompositor::BindOutputTexture(); @@ -1162,11 +1167,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) } setMenuBar(menubar); - //panel = new ScreenPanelNative(this); - panel = new ScreenPanelGL(this); - setCentralWidget(panel); - connect(this, SIGNAL(screenLayoutChange()), panel, SLOT(onScreenLayoutChanged())); - emit screenLayoutChange(); + show(); + createScreenPanel(); resize(Config::WindowWidth, Config::WindowHeight); @@ -1210,9 +1212,45 @@ MainWindow::~MainWindow() { } +void MainWindow::createScreenPanel() +{ + hasOGL = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); + + if (hasOGL) + { + ScreenPanelGL* panelGL = new ScreenPanelGL(this); + panelGL->show(); + + if (!panelGL->isValid()) + hasOGL = false; + else + { + QSurfaceFormat fmt = panelGL->format(); + if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 2)) + hasOGL = false; + } + + if (!hasOGL) + delete panelGL; + else + panel = panelGL; + } + + if (!hasOGL) + { + panel = new ScreenPanelNative(this); + panel->show(); + } + + setCentralWidget(panel); + connect(this, SIGNAL(screenLayoutChange()), panel, SLOT(onScreenLayoutChanged())); + emit screenLayoutChange(); +} + QOpenGLContext* MainWindow::getOGLContext() { - // TODO: check whether we can actually pull this! + if (!hasOGL) return nullptr; + QOpenGLWidget* glpanel = (QOpenGLWidget*)panel; return glpanel->context(); } @@ -1575,6 +1613,7 @@ void MainWindow::onInputConfigFinished(int res) void MainWindow::onOpenVideoSettings() { VideoSettingsDialog* dlg = VideoSettingsDialog::openDlg(this); + connect(dlg, &VideoSettingsDialog::updateVideoSettings, this, &MainWindow::onUpdateVideoSettings); } void MainWindow::onOpenAudioSettings() @@ -1745,6 +1784,23 @@ void MainWindow::onEmuStop() actStop->setEnabled(false); } +void MainWindow::onUpdateVideoSettings(bool glchange) +{ + if (glchange) + { + emuThread->emuPause(); + + delete panel; + createScreenPanel(); + connect(emuThread, SIGNAL(windowUpdate()), panel, SLOT(update())); + } + + videoSettingsDirty = true; + + if (glchange) + emuThread->emuUnpause(); +} + void emuStop() { @@ -1790,6 +1846,9 @@ int main(int argc, char** argv) Config::Load(); #define SANITIZE(var, min, max) { if (var < min) var = min; else if (var > max) var = max; } + SANITIZE(Config::_3DRenderer, 0, 1); + SANITIZE(Config::ScreenVSyncInterval, 1, 20); + SANITIZE(Config::GL_ScaleFactor, 1, 16); SANITIZE(Config::AudioVolume, 0, 256); SANITIZE(Config::MicInputType, 0, 3); SANITIZE(Config::ScreenRotation, 0, 3); @@ -1900,7 +1959,6 @@ int main(int argc, char** argv) Input::OpenJoystick(); mainWindow = new MainWindow(); - mainWindow->show(); emuThread = new EmuThread(); emuThread->start(); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 8759e95d..ef51158e 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -171,6 +171,7 @@ public: explicit MainWindow(QWidget* parent = nullptr); ~MainWindow(); + bool hasOGL; QOpenGLContext* getOGLContext(); protected: @@ -221,7 +222,11 @@ private slots: void onEmuStart(); void onEmuStop(); + void onUpdateVideoSettings(bool glchange); + private: + void createScreenPanel(); + QString loadErrorStr(int error); public: From f7e53c6f71c3bf6f082d1e5857f474f79f992602 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 15:58:18 +0200 Subject: [PATCH 086/105] so you can't resize() before show()ing?? bullshit. --- src/frontend/qt_sdl/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 658ae8bf..b6282fef 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1167,11 +1167,11 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) } setMenuBar(menubar); + resize(Config::WindowWidth, Config::WindowHeight); + show(); createScreenPanel(); - resize(Config::WindowWidth, Config::WindowHeight); - for (int i = 0; i < 9; i++) { actSaveState[i]->setEnabled(false); From d25dc40e70e9a1c25966db8e16a5efd5284fd336 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 16:04:22 +0200 Subject: [PATCH 087/105] make it a bit better --- src/frontend/qt_sdl/VideoSettingsDialog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index 09f1ab45..9645a3d6 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -59,7 +59,7 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( for (int i = 1; i <= 16; i++) ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i)); ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1); - +printf("GL scale = %d\n", Config::GL_ScaleFactor); if (Config::_3DRenderer == 0) { ui->cbGLDisplay->setEnabled(true); @@ -145,6 +145,9 @@ void VideoSettingsDialog::on_cbSoftwareThreaded_stateChanged(int state) void VideoSettingsDialog::on_cbxGLResolution_currentIndexChanged(int idx) { + // prevent a spurious change + if (ui->cbxGLResolution->count() < 16) return; + Config::GL_ScaleFactor = idx+1; emit updateVideoSettings(false); From d1d572210fdcef0932aaa2f0c6df71f6f2161c75 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 16:07:34 +0200 Subject: [PATCH 088/105] fix that bug here too --- src/frontend/qt_sdl/InputConfigDialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/frontend/qt_sdl/InputConfigDialog.cpp b/src/frontend/qt_sdl/InputConfigDialog.cpp index 2c0afc44..81baa658 100644 --- a/src/frontend/qt_sdl/InputConfigDialog.cpp +++ b/src/frontend/qt_sdl/InputConfigDialog.cpp @@ -199,6 +199,9 @@ void InputConfigDialog::on_InputConfigDialog_rejected() void InputConfigDialog::on_cbxJoystick_currentIndexChanged(int id) { + // prevent a spurious change + if (ui->cbxJoystick->count() < 2) return; + Input::JoystickID = id; Input::OpenJoystick(); } From 2912a07b8babb602aaf315e62667044a07adf8e7 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 17:00:25 +0200 Subject: [PATCH 089/105] fix bugs, clean up some of the shit --- src/GPU.cpp | 8 ++++---- src/frontend/qt_sdl/VideoSettingsDialog.cpp | 2 +- src/frontend/qt_sdl/main.cpp | 14 +++++++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/GPU.cpp b/src/GPU.cpp index 56db0e27..60f863e0 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -339,10 +339,10 @@ void SetRenderSettings(int renderer, RenderSettings& settings) int fbsize; if (accel) fbsize = (256*3 + 1) * 192; else fbsize = 256 * 192; - if (Framebuffer[0][0]) delete[] Framebuffer[0][0]; - if (Framebuffer[1][0]) delete[] Framebuffer[1][0]; - if (Framebuffer[0][1]) delete[] Framebuffer[0][1]; - if (Framebuffer[1][1]) delete[] Framebuffer[1][1]; + if (Framebuffer[0][0]) { delete[] Framebuffer[0][0]; Framebuffer[0][0] = nullptr; } + if (Framebuffer[1][0]) { delete[] Framebuffer[1][0]; Framebuffer[1][0] = nullptr; } + if (Framebuffer[0][1]) { delete[] Framebuffer[0][1]; Framebuffer[0][1] = nullptr; } + if (Framebuffer[1][1]) { delete[] Framebuffer[1][1]; Framebuffer[1][1] = nullptr; } Framebuffer[0][0] = new u32[fbsize]; Framebuffer[1][0] = new u32[fbsize]; diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index 9645a3d6..efb50518 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -59,7 +59,7 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( for (int i = 1; i <= 16; i++) ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i)); ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1); -printf("GL scale = %d\n", Config::GL_ScaleFactor); + if (Config::_3DRenderer == 0) { ui->cbGLDisplay->setEnabled(true); diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index b6282fef..de71da9e 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -282,7 +282,7 @@ void EmuThread::initOpenGL() return; } - oglContext = new QOpenGLContext();//oglSurface); + oglContext = new QOpenGLContext(); oglContext->setFormat(oglSurface->format()); oglContext->setShareContext(windowctx); if (!oglContext->create()) @@ -797,9 +797,16 @@ ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) ScreenPanelGL::~ScreenPanelGL() { - // CHECKME!!!! - // ALSO TODO: CLEANUP + makeCurrent(); + + glDeleteTextures(1, &screenTexture); + + glDeleteVertexArrays(1, &screenVertexArray); + glDeleteBuffers(1, &screenVertexBuffer); + delete screenShader; + + doneCurrent(); } void ScreenPanelGL::setupScreenLayout() @@ -1793,6 +1800,7 @@ void MainWindow::onUpdateVideoSettings(bool glchange) delete panel; createScreenPanel(); connect(emuThread, SIGNAL(windowUpdate()), panel, SLOT(update())); + if (hasOGL) emuThread->initOpenGL(); } videoSettingsDirty = true; From 79d4183ccdac6d0b2a82f99ad169b7fe6349febc Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 18:11:41 +0200 Subject: [PATCH 090/105] re-add OSD system --- src/frontend/qt_sdl/CMakeLists.txt | 3 + src/frontend/qt_sdl/OSD.cpp | 474 +++++++++++++++++++++++++++++ src/frontend/qt_sdl/OSD.h | 36 +++ src/frontend/qt_sdl/OSD_shaders.h | 65 ++++ src/frontend/qt_sdl/font.h | 135 ++++++++ src/frontend/qt_sdl/main.cpp | 18 +- src/frontend/qt_sdl/main_shaders.h | 50 --- 7 files changed, 730 insertions(+), 51 deletions(-) create mode 100644 src/frontend/qt_sdl/OSD.cpp create mode 100644 src/frontend/qt_sdl/OSD.h create mode 100644 src/frontend/qt_sdl/OSD_shaders.h create mode 100644 src/frontend/qt_sdl/font.h diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index a4bb5f53..0b7fa547 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -8,6 +8,9 @@ SET(SOURCES_QT_SDL VideoSettingsDialog.cpp AudioSettingsDialog.cpp Input.cpp + OSD.cpp + OSD_shaders.h + font.h Platform.cpp PlatformConfig.cpp diff --git a/src/frontend/qt_sdl/OSD.cpp b/src/frontend/qt_sdl/OSD.cpp new file mode 100644 index 00000000..4e4e40fe --- /dev/null +++ b/src/frontend/qt_sdl/OSD.cpp @@ -0,0 +1,474 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include +#include +#include "../types.h" + +#include "main.h" +#include + +#include "OSD.h" +#include "OSD_shaders.h" +#include "font.h" + +#include "PlatformConfig.h" + +extern MainWindow* mainWindow; + +namespace OSD +{ + +const u32 kOSDMargin = 6; + +struct Item +{ + Uint32 Timestamp; + char Text[256]; + u32 Color; + + u32 Width, Height; + u32* Bitmap; + + bool NativeBitmapLoaded; + QImage NativeBitmap; + + bool GLTextureLoaded; + GLuint GLTexture; + +}; + +std::deque ItemQueue; + +QOpenGLShaderProgram* Shader; +GLint uScreenSize, uOSDPos, uOSDSize; +GLuint OSDVertexArray; +GLuint OSDVertexBuffer; + +volatile bool Rendering; + + +bool Init(QOpenGLFunctions_3_2_Core* f) +{ + if (f) + { + Shader = new QOpenGLShaderProgram(); + Shader->addShaderFromSourceCode(QOpenGLShader::Vertex, kScreenVS_OSD); + Shader->addShaderFromSourceCode(QOpenGLShader::Fragment, kScreenFS_OSD); + + GLuint pid = Shader->programId(); + f->glBindAttribLocation(pid, 0, "vPosition"); + f->glBindFragDataLocation(pid, 0, "oColor"); + + Shader->link(); + + Shader->bind(); + Shader->setUniformValue("OSDTex", (GLint)0); + Shader->release(); + + uScreenSize = Shader->uniformLocation("uScreenSize"); + uOSDPos = Shader->uniformLocation("uOSDPos"); + uOSDSize = Shader->uniformLocation("uOSDSize"); + + float vertices[6*2] = + { + 0, 0, + 1, 1, + 1, 0, + 0, 0, + 0, 1, + 1, 1 + }; + + f->glGenBuffers(1, &OSDVertexBuffer); + f->glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer); + f->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + f->glGenVertexArrays(1, &OSDVertexArray); + f->glBindVertexArray(OSDVertexArray); + f->glEnableVertexAttribArray(0); // position + f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0)); + } + + return true; +} + +void DeInit(QOpenGLFunctions_3_2_Core* f) +{ + for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) + { + Item& item = *it; + + if (item.GLTextureLoaded && f) f->glDeleteTextures(1, &item.GLTexture); + if (item.Bitmap) delete[] item.Bitmap; + + it = ItemQueue.erase(it); + } + + if (f) delete Shader; +} + + +int FindBreakPoint(const char* text, int i) +{ + // i = character that went out of bounds + + for (int j = i; j >= 0; j--) + { + if (text[j] == ' ') + return j; + } + + return i; +} + +void LayoutText(const char* text, u32* width, u32* height, int* breaks) +{ + u32 w = 0; + u32 h = 14; + u32 totalw = 0; + u32 maxw = mainWindow->panel->width() - (kOSDMargin*2); + int lastbreak = -1; + int numbrk = 0; + u16* ptr; + + memset(breaks, 0, sizeof(int)*64); + + for (int i = 0; text[i] != '\0'; ) + { + int glyphsize; + if (text[i] == ' ') + { + glyphsize = 6; + } + else + { + u32 ch = text[i]; + if (ch < 0x10 || ch > 0x7E) ch = 0x7F; + + ptr = &font[(ch-0x10) << 4]; + glyphsize = ptr[0]; + if (!glyphsize) glyphsize = 6; + else glyphsize += 2; // space around the character + } + + w += glyphsize; + if (w > maxw) + { + // wrap shit as needed + if (text[i] == ' ') + { + if (numbrk >= 64) break; + breaks[numbrk++] = i; + i++; + } + else + { + int brk = FindBreakPoint(text, i); + if (brk != lastbreak) i = brk; + + if (numbrk >= 64) break; + breaks[numbrk++] = i; + + lastbreak = brk; + } + + w = 0; + h += 14; + } + else + i++; + + if (w > totalw) totalw = w; + } + + *width = totalw; + *height = h; +} + +u32 RainbowColor(u32 inc) +{ + // inspired from Acmlmboard + + if (inc < 100) return 0xFFFF9B9B + (inc << 8); + else if (inc < 200) return 0xFFFFFF9B - ((inc-100) << 16); + else if (inc < 300) return 0xFF9BFF9B + (inc-200); + else if (inc < 400) return 0xFF9BFFFF - ((inc-300) << 8); + else if (inc < 500) return 0xFF9B9BFF + ((inc-400) << 16); + else return 0xFFFF9BFF - (inc-500); +} + +void RenderText(u32 color, const char* text, Item* item) +{ + u32 w, h; + int breaks[64]; + + bool rainbow = (color == 0); + u32 rainbowinc = ((text[0] * 17) + (SDL_GetTicks() * 13)) % 600; + + color |= 0xFF000000; + const u32 shadow = 0xE0000000; + + LayoutText(text, &w, &h, breaks); + + item->Width = w; + item->Height = h; + item->Bitmap = new u32[w*h]; + memset(item->Bitmap, 0, w*h*sizeof(u32)); + + u32 x = 0, y = 1; + u32 maxw = mainWindow->panel->width() - (kOSDMargin*2); + int curline = 0; + u16* ptr; + + for (int i = 0; text[i] != '\0'; ) + { + int glyphsize; + if (text[i] == ' ') + { + x += 6; + } + else + { + u32 ch = text[i]; + if (ch < 0x10 || ch > 0x7E) ch = 0x7F; + + ptr = &font[(ch-0x10) << 4]; + int glyphsize = ptr[0]; + if (!glyphsize) x += 6; + else + { + x++; + + if (rainbow) + { + color = RainbowColor(rainbowinc); + rainbowinc = (rainbowinc + 30) % 600; + } + + // draw character + for (int cy = 0; cy < 12; cy++) + { + u16 val = ptr[4+cy]; + + for (int cx = 0; cx < glyphsize; cx++) + { + if (val & (1<Bitmap[((y+cy) * w) + x+cx] = color; + } + } + + x += glyphsize; + x++; + } + } + + i++; + if (breaks[curline] && i >= breaks[curline]) + { + i = breaks[curline++]; + if (text[i] == ' ') i++; + + x = 0; + y += 14; + } + } + + // shadow + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + u32 val; + + val = item->Bitmap[(y * w) + x]; + if ((val >> 24) == 0xFF) continue; + + if (x > 0) val = item->Bitmap[(y * w) + x-1]; + if (x < w-1) val |= item->Bitmap[(y * w) + x+1]; + if (y > 0) + { + if (x > 0) val |= item->Bitmap[((y-1) * w) + x-1]; + val |= item->Bitmap[((y-1) * w) + x]; + if (x < w-1) val |= item->Bitmap[((y-1) * w) + x+1]; + } + if (y < h-1) + { + if (x > 0) val |= item->Bitmap[((y+1) * w) + x-1]; + val |= item->Bitmap[((y+1) * w) + x]; + if (x < w-1) val |= item->Bitmap[((y+1) * w) + x+1]; + } + + if ((val >> 24) == 0xFF) + item->Bitmap[(y * w) + x] = shadow; + } + } +} + + +void AddMessage(u32 color, const char* text) +{ + if (!Config::ShowOSD) return; + + while (Rendering); + + Item item; + + item.Timestamp = SDL_GetTicks(); + strncpy(item.Text, text, 255); item.Text[255] = '\0'; + item.Color = color; + item.Bitmap = nullptr; + + item.NativeBitmapLoaded = false; + item.GLTextureLoaded = false; + + ItemQueue.push_back(item); +} + +void Update(QOpenGLFunctions_3_2_Core* f) +{ + if (!Config::ShowOSD) + { + Rendering = true; + for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) + { + Item& item = *it; + + if (item.GLTextureLoaded && f) f->glDeleteTextures(1, &item.GLTexture); + if (item.Bitmap) delete[] item.Bitmap; + + it = ItemQueue.erase(it); + } + Rendering = false; + return; + } + + Rendering = true; + + Uint32 tick_now = SDL_GetTicks(); + Uint32 tick_min = tick_now - 2500; + + for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) + { + Item& item = *it; + + if (item.Timestamp < tick_min) + { + if (item.GLTextureLoaded) f->glDeleteTextures(1, &item.GLTexture); + if (item.Bitmap) delete[] item.Bitmap; + + it = ItemQueue.erase(it); + continue; + } + + if (!item.Bitmap) + { + RenderText(item.Color, item.Text, &item); + } + + it++; + } + + Rendering = false; +} + +void DrawNative(QPainter& painter) +{ + if (!Config::ShowOSD) return; + + Rendering = true; + + u32 y = kOSDMargin; + + painter.resetTransform(); + + for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) + { + Item& item = *it; + + if (!item.NativeBitmapLoaded) + { + item.NativeBitmap = QImage((const uchar*)item.Bitmap, item.Width, item.Height, QImage::Format_ARGB32_Premultiplied); + item.NativeBitmapLoaded = true; + } + + painter.drawImage(kOSDMargin, y, item.NativeBitmap); + + y += item.Height; + it++; + } + + Rendering = false; +} + +void DrawGL(QOpenGLFunctions_3_2_Core* f, float w, float h) +{ + if (!Config::ShowOSD) return; + if (!mainWindow || !mainWindow->panel) return; + + Rendering = true; + + u32 y = kOSDMargin; + + Shader->bind(); + + f->glUniform2f(uScreenSize, w, h); + + f->glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer); + f->glBindVertexArray(OSDVertexArray); + + f->glActiveTexture(GL_TEXTURE0); + + f->glEnable(GL_BLEND); + f->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + for (auto it = ItemQueue.begin(); it != ItemQueue.end(); ) + { + Item& item = *it; + + if (!item.GLTextureLoaded) + { + f->glGenTextures(1, &item.GLTexture); + f->glBindTexture(GL_TEXTURE_2D, item.GLTexture); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, item.Width, item.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, item.Bitmap); + + item.GLTextureLoaded = true; + } + + f->glBindTexture(GL_TEXTURE_2D, item.GLTexture); + f->glUniform2i(uOSDPos, kOSDMargin, y); + f->glUniform2i(uOSDSize, item.Width, item.Height); + f->glDrawArrays(GL_TRIANGLES, 0, 2*3); + + y += item.Height; + it++; + } + + f->glDisable(GL_BLEND); + Shader->release(); + + Rendering = false; +} + +} diff --git a/src/frontend/qt_sdl/OSD.h b/src/frontend/qt_sdl/OSD.h new file mode 100644 index 00000000..79d9df01 --- /dev/null +++ b/src/frontend/qt_sdl/OSD.h @@ -0,0 +1,36 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef OSD_H +#define OSD_H + +namespace OSD +{ + +bool Init(QOpenGLFunctions_3_2_Core* f); +void DeInit(QOpenGLFunctions_3_2_Core* f); + +void AddMessage(u32 color, const char* text); + +void Update(QOpenGLFunctions_3_2_Core* f); +void DrawNative(QPainter& painter); +void DrawGL(QOpenGLFunctions_3_2_Core* f, float w, float h); + +} + +#endif // OSD_H diff --git a/src/frontend/qt_sdl/OSD_shaders.h b/src/frontend/qt_sdl/OSD_shaders.h new file mode 100644 index 00000000..5a64f66f --- /dev/null +++ b/src/frontend/qt_sdl/OSD_shaders.h @@ -0,0 +1,65 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef OSD_SHADERS_H +#define OSD_SHADERS_H + +const char* kScreenVS_OSD = R"(#version 140 + +uniform vec2 uScreenSize; + +uniform ivec2 uOSDPos; +uniform ivec2 uOSDSize; + +in vec2 vPosition; + +smooth out vec2 fTexcoord; + +void main() +{ + vec4 fpos; + + vec2 osdpos = (vPosition * vec2(uOSDSize)); + fTexcoord = osdpos; + osdpos += uOSDPos; + + fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0; + fpos.y *= -1; + fpos.z = 0.0; + fpos.w = 1.0; + + gl_Position = fpos; +} +)"; + +const char* kScreenFS_OSD = R"(#version 140 + +uniform sampler2D OSDTex; + +smooth in vec2 fTexcoord; + +out vec4 oColor; + +void main() +{ + vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0); + oColor = pixel.bgra; +} +)"; + +#endif // OSD_SHADERS_H diff --git a/src/frontend/qt_sdl/font.h b/src/frontend/qt_sdl/font.h new file mode 100644 index 00000000..f2e4f878 --- /dev/null +++ b/src/frontend/qt_sdl/font.h @@ -0,0 +1,135 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef FONT_H +#define FONT_H +unsigned short font[] = { + 12, 0, 0, 0,0x0C03, 0x0E07, 0x070E, 0x039C, 0x01F8, 0x00F0, 0x00F0, 0x01F8, 0x039C, 0x070E, 0x0E07, 0x0C03, + 12, 0, 0, 0,0x01C0, 0x00E0, 0x0060, 0x0860, 0x0C60, 0x0FE0, 0x07F0, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0000, 0x0000, + 9, 0, 0, 0,0x01EF, 0x01EF, 0x018C, 0x01CE, 0x00E7, 0x0063, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 10, 0, 0, 0,0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x0000, 0x0000, + 8, 0, 0, 0,0x0018, 0x00FE, 0x00FF, 0x001B, 0x007F, 0x00FE, 0x00D8, 0x00FF, 0x007F, 0x0018, 0x0000, 0x0000, + 10, 0, 0, 0,0x0306, 0x038F, 0x01CF, 0x00E6, 0x0070, 0x0038, 0x019C, 0x03CE, 0x03C7, 0x0183, 0x0000, 0x0000, + 10, 0, 0, 0,0x007C, 0x00FE, 0x00C6, 0x00EE, 0x007C, 0x037E, 0x03E7, 0x01F3, 0x03BF, 0x031E, 0x0000, 0x0000, + 4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 4, 0, 0, 0,0x000C, 0x000E, 0x0007, 0x0003, 0x0003, 0x0003, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000, + 4, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x000C, 0x000C, 0x000C, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, + 10, 0, 0, 0,0x0030, 0x0333, 0x03B7, 0x01FE, 0x00FC, 0x00FC, 0x01FE, 0x03B7, 0x0333, 0x0030, 0x0000, 0x0000, + 10, 0, 0, 0,0x0030, 0x0030, 0x0030, 0x0030, 0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, + 4, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003, + 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 3, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0007, 0x0000, 0x0000, + 10, 0, 0, 0,0x0300, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, + 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, + 4, 0, 0, 0,0x0006, 0x0007, 0x0007, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x000F, 0x000F, 0x0000, 0x0000, + 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C0, 0x00FE, 0x007F, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0000, 0x0000, + 8, 0, 0, 0,0x007F, 0x00FF, 0x00C0, 0x00C0, 0x007C, 0x00FC, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000, + 8, 0, 0, 0,0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x00FF, 0x00FE, 0x0060, 0x0060, 0x0000, 0x0000, + 8, 0, 0, 0,0x00FF, 0x00FF, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000, + 8, 0, 0, 0,0x007E, 0x007F, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, + 8, 0, 0, 0,0x00FF, 0x00FF, 0x00C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000C, 0x000C, 0x000C, 0x0000, 0x0000, + 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, + 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x00FE, 0x00C0, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000, + 3, 0, 0, 0,0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000, + 4, 0, 0, 0,0x0000, 0x0000, 0x000E, 0x000E, 0x0000, 0x0000, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, + 6, 0, 0, 0,0x0030, 0x0038, 0x001C, 0x000E, 0x0007, 0x0007, 0x000E, 0x001C, 0x0038, 0x0030, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x0000, + 6, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, + 8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00F0, 0x0078, 0x0018, 0x0000, 0x0018, 0x0018, 0x0000, 0x0000, + 10, 0, 0, 0,0x00FC, 0x01FE, 0x0387, 0x0333, 0x037B, 0x03FB, 0x01F3, 0x0007, 0x03FE, 0x03FC, 0x0000, 0x0000, + 9, 0, 0, 0,0x00FE, 0x01FF, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000, + 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0000, 0x0000, + 8, 0, 0, 0,0x00FE, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00FF, 0x00FE, 0x0000, 0x0000, + 9, 0, 0, 0,0x007F, 0x00FF, 0x01C3, 0x0183, 0x0183, 0x0183, 0x0183, 0x01C3, 0x00FF, 0x007F, 0x0000, 0x0000, + 9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x01FF, 0x01FF, 0x0000, 0x0000, + 9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, + 9, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01F3, 0x01F3, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000, + 9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000, + 6, 0, 0, 0,0x003F, 0x003F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x003F, 0x003F, 0x0000, 0x0000, + 9, 0, 0, 0,0x01F0, 0x01F0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, + 9, 0, 0, 0,0x0183, 0x01C3, 0x00E3, 0x0073, 0x003F, 0x003F, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000, + 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007F, 0x0000, 0x0000, + 10, 0, 0, 0,0x0303, 0x0387, 0x03CF, 0x03FF, 0x037B, 0x0333, 0x0303, 0x0303, 0x0303, 0x0303, 0x0000, 0x0000, + 10, 0, 0, 0,0x0303, 0x0307, 0x030F, 0x031F, 0x033B, 0x0373, 0x03E3, 0x03C3, 0x0383, 0x0303, 0x0000, 0x0000, + 10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x03FF, 0x01FE, 0x0000, 0x0000, + 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, + 10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0333, 0x0373, 0x03E3, 0x01C3, 0x03FF, 0x037E, 0x0000, 0x0000, + 9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000, + 10, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01FF, 0x03FE, 0x0300, 0x0300, 0x03FE, 0x01FE, 0x0000, 0x0000, + 10, 0, 0, 0,0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, + 9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000, + 10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000, + 10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000, + 10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0078, 0x00FC, 0x01CE, 0x0387, 0x0303, 0x0000, 0x0000, + 10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, + 10, 0, 0, 0,0x03FF, 0x03FF, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x03FF, 0x03FF, 0x0000, 0x0000, + 4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000F, 0x0000, 0x0000, + 10, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0300, 0x0000, 0x0000, + 4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000F, 0x000F, 0x0000, 0x0000, + 8, 0, 0, 0,0x0018, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF, + 4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007E, 0x0060, 0x007E, 0x007F, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000, + 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x003F, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007E, 0x0000, 0x0000, + 7, 0, 0, 0,0x0060, 0x0060, 0x0060, 0x007E, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007F, 0x0063, 0x007F, 0x003F, 0x0003, 0x003F, 0x003E, 0x0000, 0x0000, + 6, 0, 0, 0,0x003C, 0x003E, 0x0006, 0x0006, 0x001F, 0x001F, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x007E, 0x003E, + 7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000, + 2, 0, 0, 0,0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, + 7, 0, 0, 0,0x0060, 0x0060, 0x0000, 0x0000, 0x0060, 0x0060, 0x0060, 0x0060, 0x0060, 0x0063, 0x007F, 0x003E, + 8, 0, 0, 0,0x0003, 0x0003, 0x00E3, 0x0073, 0x003B, 0x001F, 0x001F, 0x003B, 0x0073, 0x00E3, 0x0000, 0x0000, + 4, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000E, 0x0000, 0x0000, + 10, 0, 0, 0,0x0000, 0x0000, 0x01FF, 0x03FF, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000, + 8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x007F, 0x003F, 0x0003, 0x0003, 0x0003, 0x0003, + 7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x0060, 0x0060, + 7, 0, 0, 0,0x0000, 0x0000, 0x003B, 0x007F, 0x0067, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, + 8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x007F, 0x00FE, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000, + 6, 0, 0, 0,0x0006, 0x0006, 0x003F, 0x003F, 0x0006, 0x0006, 0x0006, 0x0006, 0x003E, 0x003C, 0x0000, 0x0000, + 7, 0, 0, 0,0x0000, 0x0000, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000, + 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000, + 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000, + 8, 0, 0, 0,0x0000, 0x0000, 0x00C3, 0x00E7, 0x007E, 0x003C, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000, + 10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0307, 0x038E, 0x01DC, 0x00F8, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006, + 8, 0, 0, 0,0x0000, 0x0000, 0x00FF, 0x00FF, 0x0070, 0x0038, 0x001C, 0x000E, 0x00FF, 0x00FF, 0x0000, 0x0000, + 6, 0, 0, 0,0x0038, 0x003C, 0x000C, 0x000C, 0x000F, 0x000F, 0x000C, 0x000C, 0x003C, 0x0038, 0x0000, 0x0000, + 2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, + 6, 0, 0, 0,0x0007, 0x000F, 0x000C, 0x000C, 0x003C, 0x003C, 0x000C, 0x000C, 0x000F, 0x0007, 0x0000, 0x0000, + 10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x031C, 0x03BE, 0x01F7, 0x00E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 11, 0, 0, 0,0x0555, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0555, 0x0000, +}; +#endif diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index de71da9e..78f64f66 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -43,6 +43,7 @@ #include "version.h" #include "FrontendUtil.h" +#include "OSD.h" #include "NDS.h" #include "GBACart.h" @@ -263,7 +264,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowEmuReset()), mainWindow->actReset, SLOT(trigger())); connect(this, SIGNAL(screenLayoutChange()), mainWindow->panel, SLOT(onScreenLayoutChanged())); - initOpenGL(); + if (mainWindow->hasOGL) initOpenGL(); } void EmuThread::initOpenGL() @@ -709,10 +710,13 @@ ScreenPanelNative::ScreenPanelNative(QWidget* parent) : QWidget(parent) screenTrans[1].reset(); touching = false; + + OSD::Init(nullptr); } ScreenPanelNative::~ScreenPanelNative() { + OSD::DeInit(nullptr); } void ScreenPanelNative::setupScreenLayout() @@ -756,6 +760,9 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event) painter.setTransform(screenTrans[1]); painter.drawImage(screenrc, screen[1]); + + OSD::Update(nullptr); + OSD::DrawNative(painter); } void ScreenPanelNative::resizeEvent(QResizeEvent* event) @@ -793,12 +800,16 @@ ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) format.setVersion(3, 2); format.setProfile(QSurfaceFormat::CoreProfile); setFormat(format); + + touching = false; } ScreenPanelGL::~ScreenPanelGL() { makeCurrent(); + OSD::DeInit(this); + glDeleteTextures(1, &screenTexture); glDeleteVertexArrays(1, &screenVertexArray); @@ -881,6 +892,8 @@ void ScreenPanelGL::initializeGL() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + OSD::Init(this); } void ScreenPanelGL::paintGL() @@ -935,6 +948,9 @@ void ScreenPanelGL::paintGL() glDrawArrays(GL_TRIANGLES, 2*3, 2*3); screenShader->release(); + + OSD::Update(this); + OSD::DrawGL(this, w*factor, h*factor); } void ScreenPanelGL::resizeEvent(QResizeEvent* event) diff --git a/src/frontend/qt_sdl/main_shaders.h b/src/frontend/qt_sdl/main_shaders.h index 96b9ecd0..c55f79e9 100644 --- a/src/frontend/qt_sdl/main_shaders.h +++ b/src/frontend/qt_sdl/main_shaders.h @@ -61,54 +61,4 @@ void main() } )"; - - -const char* kScreenVS_OSD = R"(#version 140 - -layout(std140) uniform uConfig -{ - vec2 uScreenSize; - uint u3DScale; - uint uFilterMode; -}; - -uniform ivec2 uOSDPos; -uniform ivec2 uOSDSize; - -in vec2 vPosition; - -smooth out vec2 fTexcoord; - -void main() -{ - vec4 fpos; - - vec2 osdpos = (vPosition * vec2(uOSDSize)); - fTexcoord = osdpos; - osdpos += uOSDPos; - - fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0; - fpos.y *= -1; - fpos.z = 0.0; - fpos.w = 1.0; - - gl_Position = fpos; -} -)"; - -const char* kScreenFS_OSD = R"(#version 140 - -uniform sampler2D OSDTex; - -smooth in vec2 fTexcoord; - -out vec4 oColor; - -void main() -{ - vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0); - oColor = pixel.bgra; -} -)"; - #endif // MAIN_SHADERS_H From a2004785a4d49f02f8257a38489eb57a29ce4e91 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 18:22:02 +0200 Subject: [PATCH 091/105] re-add all old OSD messages --- src/frontend/Util_ROM.cpp | 6 ------ src/frontend/qt_sdl/main.cpp | 41 ++++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index ec3186a8..3f64b9dd 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -384,10 +384,6 @@ bool SaveState(const char* filename) } } - /*char msg[64]; - if (slot > 0) sprintf(msg, "State saved to slot %d", slot); - else sprintf(msg, "State saved to file"); - OSD::AddMessage(0, msg);*/ return true; } @@ -407,8 +403,6 @@ void UndoStateLoad() strncpy(SRAMPath[ROMSlot_NDS], PrevSRAMPath[ROMSlot_NDS], 1024); NDS::RelocateSave(SRAMPath[ROMSlot_NDS], false); } - - //OSD::AddMessage(0, "State load undone"); } } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 78f64f66..bea33b07 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -364,16 +364,16 @@ void EmuThread::run() if (Input::HotkeyPressed(HK_SolarSensorDecrease)) { if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--; - //char msg[64]; - //sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - //OSD::AddMessage(0, msg); + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); } if (Input::HotkeyPressed(HK_SolarSensorIncrease)) { if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++; - //char msg[64]; - //sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); - //OSD::AddMessage(0, msg); + char msg[64]; + sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel); + OSD::AddMessage(0, msg); } } @@ -411,7 +411,7 @@ void EmuThread::run() { bool lid = !NDS::IsLidClosed(); NDS::SetLidClosed(lid); - //OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened"); + OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened"); } // microphone input @@ -1493,13 +1493,16 @@ void MainWindow::onSaveState() if (Frontend::SaveState(filename)) { - // TODO: OSD message + char msg[64]; + if (slot > 0) sprintf(msg, "State saved to slot %d", slot); + else sprintf(msg, "State saved to file"); + OSD::AddMessage(0, msg); actLoadState[slot]->setEnabled(true); } else { - // TODO: OSD error message? + OSD::AddMessage(0xFFA0A0, "State save failed"); } emuThread->emuUnpause(); @@ -1534,10 +1537,10 @@ void MainWindow::onLoadState() if (!Platform::FileExists(filename)) { - /*char msg[64]; + char msg[64]; if (slot > 0) sprintf(msg, "State slot %d is empty", slot); else sprintf(msg, "State file does not exist"); - OSD::AddMessage(0xFFA0A0, msg);*/ + OSD::AddMessage(0xFFA0A0, msg); emuThread->emuUnpause(); return; @@ -1545,11 +1548,14 @@ void MainWindow::onLoadState() if (Frontend::LoadState(filename)) { - // TODO: OSD message + char msg[64]; + if (slot > 0) sprintf(msg, "State loaded from slot %d", slot); + else sprintf(msg, "State loaded from file"); + OSD::AddMessage(0, msg); } else { - // TODO: OSD error message? + OSD::AddMessage(0xFFA0A0, "State load failed"); } emuThread->emuUnpause(); @@ -1560,6 +1566,8 @@ void MainWindow::onUndoStateLoad() emuThread->emuPause(); Frontend::UndoStateLoad(); emuThread->emuUnpause(); + + OSD::AddMessage(0, "State load undone"); } void MainWindow::onQuit() @@ -1575,10 +1583,12 @@ void MainWindow::onPause(bool checked) if (checked) { emuThread->emuPause(); + OSD::AddMessage(0, "Paused"); } else { emuThread->emuUnpause(); + OSD::AddMessage(0, "Resumed"); } } @@ -1600,8 +1610,7 @@ void MainWindow::onReset() } else { - // OSD::AddMessage(0, "Reset"); - + OSD::AddMessage(0, "Reset"); emuThread->emuRun(); } } @@ -1835,7 +1844,7 @@ void emuStop() emit emuThread->windowEmuStop(); - //OSD::AddMessage(0xFFC040, "Shutdown"); + OSD::AddMessage(0xFFC040, "Shutdown"); } From b7946c1384ce7c44172036f0a04410a9c04ed78c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 22:21:36 +0200 Subject: [PATCH 092/105] * flesh out design for wifi settings dialog * move the pcap shit to a betterer place --- src/frontend/qt_sdl/LAN_PCap.cpp | 387 ++++++ src/frontend/qt_sdl/LAN_PCap.h | 53 + src/frontend/qt_sdl/LAN_Socket.cpp | 1145 +++++++++++++++++ src/frontend/qt_sdl/LAN_Socket.h | 38 + src/frontend/qt_sdl/WifiSettingsDialog.ui | 165 +++ src/{ => frontend/qt_sdl}/pcap/bluetooth.h | 0 src/{ => frontend/qt_sdl}/pcap/bpf.h | 0 .../qt_sdl}/pcap/can_socketcan.h | 0 .../qt_sdl}/pcap/compiler-tests.h | 0 src/{ => frontend/qt_sdl}/pcap/dlt.h | 0 src/{ => frontend/qt_sdl}/pcap/funcattrs.h | 0 src/{ => frontend/qt_sdl}/pcap/ipnet.h | 0 src/{ => frontend/qt_sdl}/pcap/namedb.h | 0 src/{ => frontend/qt_sdl}/pcap/nflog.h | 0 .../qt_sdl}/pcap/pcap-inttypes.h | 0 src/{ => frontend/qt_sdl}/pcap/pcap.h | 0 src/{ => frontend/qt_sdl}/pcap/sll.h | 0 src/{ => frontend/qt_sdl}/pcap/usb.h | 0 src/{ => frontend/qt_sdl}/pcap/vlan.h | 0 19 files changed, 1788 insertions(+) create mode 100644 src/frontend/qt_sdl/LAN_PCap.cpp create mode 100644 src/frontend/qt_sdl/LAN_PCap.h create mode 100644 src/frontend/qt_sdl/LAN_Socket.cpp create mode 100644 src/frontend/qt_sdl/LAN_Socket.h create mode 100644 src/frontend/qt_sdl/WifiSettingsDialog.ui rename src/{ => frontend/qt_sdl}/pcap/bluetooth.h (100%) rename src/{ => frontend/qt_sdl}/pcap/bpf.h (100%) rename src/{ => frontend/qt_sdl}/pcap/can_socketcan.h (100%) rename src/{ => frontend/qt_sdl}/pcap/compiler-tests.h (100%) rename src/{ => frontend/qt_sdl}/pcap/dlt.h (100%) rename src/{ => frontend/qt_sdl}/pcap/funcattrs.h (100%) rename src/{ => frontend/qt_sdl}/pcap/ipnet.h (100%) rename src/{ => frontend/qt_sdl}/pcap/namedb.h (100%) rename src/{ => frontend/qt_sdl}/pcap/nflog.h (100%) rename src/{ => frontend/qt_sdl}/pcap/pcap-inttypes.h (100%) rename src/{ => frontend/qt_sdl}/pcap/pcap.h (100%) rename src/{ => frontend/qt_sdl}/pcap/sll.h (100%) rename src/{ => frontend/qt_sdl}/pcap/usb.h (100%) rename src/{ => frontend/qt_sdl}/pcap/vlan.h (100%) diff --git a/src/frontend/qt_sdl/LAN_PCap.cpp b/src/frontend/qt_sdl/LAN_PCap.cpp new file mode 100644 index 00000000..ce278bcb --- /dev/null +++ b/src/frontend/qt_sdl/LAN_PCap.cpp @@ -0,0 +1,387 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +// direct LAN interface. Currently powered by libpcap, may change. + +#include +#include +#include +#include +#include +#include "../Wifi.h" +#include "LAN_PCap.h" +#include "PlatformConfig.h" + +#ifdef __WIN32__ + #include +#else + #include + #include + #include + #include +#endif + + +// welp +#ifndef PCAP_OPENFLAG_PROMISCUOUS +#define PCAP_OPENFLAG_PROMISCUOUS 1 +#endif + + +#define DECL_PCAP_FUNC(ret, name, args, args2) \ + typedef ret (*type_##name) args; \ + type_##name ptr_##name = NULL; \ + ret name args { return ptr_##name args2; } + +DECL_PCAP_FUNC(int, pcap_findalldevs, (pcap_if_t** alldevs, char* errbuf), (alldevs,errbuf)) +DECL_PCAP_FUNC(void, pcap_freealldevs, (pcap_if_t* alldevs), (alldevs)) +DECL_PCAP_FUNC(pcap_t*, pcap_open_live, (const char* src, int snaplen, int flags, int readtimeout, char* errbuf), (src,snaplen,flags,readtimeout,errbuf)) +DECL_PCAP_FUNC(void, pcap_close, (pcap_t* dev), (dev)) +DECL_PCAP_FUNC(int, pcap_setnonblock, (pcap_t* dev, int nonblock, char* errbuf), (dev,nonblock,errbuf)) +DECL_PCAP_FUNC(int, pcap_sendpacket, (pcap_t* dev, const u_char* data, int len), (dev,data,len)) +DECL_PCAP_FUNC(int, pcap_dispatch, (pcap_t* dev, int num, pcap_handler callback, u_char* data), (dev,num,callback,data)) +DECL_PCAP_FUNC(const u_char*, pcap_next, (pcap_t* dev, struct pcap_pkthdr* hdr), (dev,hdr)) + + +namespace LAN_PCap +{ + +const char* PCapLibNames[] = +{ +#ifdef __WIN32__ + // TODO: name for npcap in non-WinPCap mode + "wpcap.dll", +#else + // Linux lib names + "libpcap.so.1", + "libpcap.so", +#endif + NULL +}; + +AdapterData* Adapters = NULL; +int NumAdapters = 0; + +void* PCapLib = NULL; +pcap_t* PCapAdapter = NULL; +AdapterData* PCapAdapterData; + +u8 PacketBuffer[2048]; +int PacketLen; +volatile int RXNum; + + +#define LOAD_PCAP_FUNC(sym) \ + ptr_##sym = (type_##sym)SDL_LoadFunction(lib, #sym); \ + if (!ptr_##sym) return false; + +bool TryLoadPCap(void* lib) +{ + LOAD_PCAP_FUNC(pcap_findalldevs) + LOAD_PCAP_FUNC(pcap_freealldevs) + LOAD_PCAP_FUNC(pcap_open_live) + LOAD_PCAP_FUNC(pcap_close) + LOAD_PCAP_FUNC(pcap_setnonblock) + LOAD_PCAP_FUNC(pcap_sendpacket) + LOAD_PCAP_FUNC(pcap_dispatch) + LOAD_PCAP_FUNC(pcap_next) + + return true; +} + +bool Init(bool open_adapter) +{ + // TODO: how to deal with cases where an adapter is unplugged or changes config?? + if (!PCapLib) + { + PCapLib = NULL; + + for (int i = 0; PCapLibNames[i]; i++) + { + void* lib = SDL_LoadObject(PCapLibNames[i]); + if (!lib) continue; + + if (!TryLoadPCap(lib)) + { + SDL_UnloadObject(lib); + continue; + } + + printf("PCap: lib %s, init successful\n", PCapLibNames[i]); + PCapLib = lib; + break; + } + + if (PCapLib == NULL) + { + printf("PCap: init failed\n"); + return false; + } + } + + PCapAdapter = NULL; + PacketLen = 0; + RXNum = 0; + + NumAdapters = 0; + + char errbuf[PCAP_ERRBUF_SIZE]; + int ret; + + pcap_if_t* alldevs; + ret = pcap_findalldevs(&alldevs, errbuf); + if (ret < 0 || alldevs == NULL) + { + printf("PCap: no devices available\n"); + return false; + } + + pcap_if_t* dev = alldevs; + while (dev) { NumAdapters++; dev = dev->next; } + + Adapters = new AdapterData[NumAdapters]; + memset(Adapters, 0, sizeof(AdapterData)*NumAdapters); + + AdapterData* adata = &Adapters[0]; + dev = alldevs; + while (dev) + { + adata->Internal = dev; + +#ifdef __WIN32__ + // hax + int len = strlen(dev->name); + len -= 12; if (len > 127) len = 127; + strncpy(adata->DeviceName, &dev->name[12], len); + adata->DeviceName[len] = '\0'; +#else + strncpy(adata->DeviceName, dev->name, 127); + adata->DeviceName[127] = '\0'; + + strncpy(adata->FriendlyName, adata->DeviceName, 127); + adata->FriendlyName[127] = '\0'; +#endif // __WIN32__ + + dev = dev->next; + adata++; + } + +#ifdef __WIN32__ + + ULONG bufsize = 16384; + IP_ADAPTER_ADDRESSES* buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize); + ULONG uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize); + if (uret == ERROR_BUFFER_OVERFLOW) + { + HeapFree(GetProcessHeap(), 0, buf); + buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize); + uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize); + } + if (uret != ERROR_SUCCESS) + { + printf("GetAdaptersAddresses() shat itself: %08X\n", uret); + return false; + } + + for (int i = 0; i < NumAdapters; i++) + { + adata = &Adapters[i]; + IP_ADAPTER_ADDRESSES* addr = buf; + while (addr) + { + if (strcmp(addr->AdapterName, adata->DeviceName)) + { + addr = addr->Next; + continue; + } + + WideCharToMultiByte(CP_UTF8, 0, addr->FriendlyName, 127, adata->FriendlyName, 127, NULL, NULL); + adata->FriendlyName[127] = '\0'; + + WideCharToMultiByte(CP_UTF8, 0, addr->Description, 127, adata->Description, 127, NULL, NULL); + adata->Description[127] = '\0'; + + if (addr->PhysicalAddressLength != 6) + { + printf("weird MAC addr length %d for %s\n", addr->PhysicalAddressLength, addr->AdapterName); + } + else + memcpy(adata->MAC, addr->PhysicalAddress, 6); + + IP_ADAPTER_UNICAST_ADDRESS* ipaddr = addr->FirstUnicastAddress; + while (ipaddr) + { + SOCKADDR* sa = ipaddr->Address.lpSockaddr; + if (sa->sa_family == AF_INET) + { + struct in_addr sa4 = ((sockaddr_in*)sa)->sin_addr; + memcpy(adata->IP_v4, &sa4, 4); + } + + ipaddr = ipaddr->Next; + } + + break; + } + } + + HeapFree(GetProcessHeap(), 0, buf); + +#else + + struct ifaddrs* addrs; + if (getifaddrs(&addrs) != 0) + { + printf("getifaddrs() shat itself :(\n"); + return false; + } + + for (int i = 0; i < NumAdapters; i++) + { + adata = &Adapters[i]; + struct ifaddrs* curaddr = addrs; + while (curaddr) + { + if (strcmp(curaddr->ifa_name, adata->DeviceName)) + { + curaddr = curaddr->ifa_next; + continue; + } + + if (!curaddr->ifa_addr) + { + printf("Device (%s) does not have an address :/\n", curaddr->ifa_name); + curaddr = curaddr->ifa_next; + continue; + } + + u16 af = curaddr->ifa_addr->sa_family; + if (af == AF_INET) + { + struct sockaddr_in* sa = (sockaddr_in*)curaddr->ifa_addr; + memcpy(adata->IP_v4, &sa->sin_addr, 4); + } + else if (af == AF_PACKET) + { + struct sockaddr_ll* sa = (sockaddr_ll*)curaddr->ifa_addr; + if (sa->sll_halen != 6) + printf("weird MAC length %d for %s\n", sa->sll_halen, curaddr->ifa_name); + else + memcpy(adata->MAC, sa->sll_addr, 6); + } + + curaddr = curaddr->ifa_next; + } + } + + freeifaddrs(addrs); + +#endif // __WIN32__ + + if (!open_adapter) return true; + if (PCapAdapter) pcap_close(PCapAdapter); + + // open pcap device + PCapAdapterData = &Adapters[0]; + for (int i = 0; i < NumAdapters; i++) + { + if (!strncmp(Adapters[i].DeviceName, Config::LANDevice, 128)) + PCapAdapterData = &Adapters[i]; + } + + dev = (pcap_if_t*)PCapAdapterData->Internal; + PCapAdapter = pcap_open_live(dev->name, 2048, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf); + if (!PCapAdapter) + { + printf("PCap: failed to open adapter %s\n", errbuf); + return false; + } + + pcap_freealldevs(alldevs); + + if (pcap_setnonblock(PCapAdapter, 1, errbuf) < 0) + { + printf("PCap: failed to set nonblocking mode\n"); + pcap_close(PCapAdapter); PCapAdapter = NULL; + return false; + } + + return true; +} + +void DeInit() +{ + if (PCapLib) + { + if (PCapAdapter) + { + pcap_close(PCapAdapter); + PCapAdapter = NULL; + } + + SDL_UnloadObject(PCapLib); + PCapLib = NULL; + } +} + + +void RXCallback(u_char* blarg, const struct pcap_pkthdr* header, const u_char* data) +{ + while (RXNum > 0); + + if (header->len > 2048-64) return; + + PacketLen = header->len; + memcpy(PacketBuffer, data, PacketLen); + RXNum = 1; +} + +int SendPacket(u8* data, int len) +{ + if (PCapAdapter == NULL) + return 0; + + if (len > 2048) + { + printf("LAN_SendPacket: error: packet too long (%d)\n", len); + return 0; + } + + pcap_sendpacket(PCapAdapter, data, len); + // TODO: check success + return len; +} + +int RecvPacket(u8* data) +{ + if (PCapAdapter == NULL) + return 0; + + int ret = 0; + if (RXNum > 0) + { + memcpy(data, PacketBuffer, PacketLen); + ret = PacketLen; + RXNum = 0; + } + + pcap_dispatch(PCapAdapter, 1, RXCallback, NULL); + return ret; +} + +} diff --git a/src/frontend/qt_sdl/LAN_PCap.h b/src/frontend/qt_sdl/LAN_PCap.h new file mode 100644 index 00000000..250b8e90 --- /dev/null +++ b/src/frontend/qt_sdl/LAN_PCap.h @@ -0,0 +1,53 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef LAN_PCAP_H +#define LAN_PCAP_H + +#include "../types.h" + +namespace LAN_PCap +{ + +typedef struct +{ + char DeviceName[128]; + char FriendlyName[128]; + char Description[128]; + + u8 MAC[6]; + u8 IP_v4[4]; + + void* Internal; + +} AdapterData; + + +extern AdapterData* Adapters; +extern int NumAdapters; + + +bool Init(bool open_adapter); +void DeInit(); + +int SendPacket(u8* data, int len); +int RecvPacket(u8* data); + +} + +#endif // LAN_PCAP_H diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp new file mode 100644 index 00000000..c6fbd4b6 --- /dev/null +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -0,0 +1,1145 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +// indirect LAN interface, powered by BSD sockets. + +#include +#include +#include +#include "../Wifi.h" +#include "LAN_Socket.h" +#include "../Config.h" + +#ifdef __WIN32__ + #include + #include + #define socket_t SOCKET + #define sockaddr_t SOCKADDR +#else + #include + #include + #include + #include + #include + #include + #include + #define socket_t int + #define sockaddr_t struct sockaddr + #define closesocket close +#endif + +#ifndef INVALID_SOCKET +#define INVALID_SOCKET (socket_t)-1 +#endif + + +namespace LAN_Socket +{ + +const u32 kSubnet = 0x0A400000; +const u32 kServerIP = kSubnet | 0x01; +const u32 kDNSIP = kSubnet | 0x02; +const u32 kClientIP = kSubnet | 0x10; + +const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44}; +const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55}; + +u8 PacketBuffer[2048]; +int PacketLen; +volatile int RXNum; + +u16 IPv4ID; + + +// TODO: UDP sockets +// * use FIFO list +// * assign new socket when seeing new IP/port + + +typedef struct +{ + u8 DestIP[4]; + u16 SourcePort; + u16 DestPort; + + u32 SeqNum; // sequence number for incoming frames + u32 AckNum; + + // 0: unused + // 1: connected + u8 Status; + + socket_t Backend; + +} TCPSocket; + +typedef struct +{ + u8 DestIP[4]; + u16 SourcePort; + u16 DestPort; + + socket_t Backend; + struct sockaddr_in BackendAddr; + +} UDPSocket; + +TCPSocket TCPSocketList[16]; +UDPSocket UDPSocketList[4]; + +int UDPSocketID = 0; + + +bool Init() +{ + // TODO: how to deal with cases where an adapter is unplugged or changes config?? + //if (PCapLib) return true; + + //Lib = NULL; + PacketLen = 0; + RXNum = 0; + + IPv4ID = 1; + + memset(TCPSocketList, 0, sizeof(TCPSocketList)); + memset(UDPSocketList, 0, sizeof(UDPSocketList)); + + UDPSocketID = 0; + + return true; +} + +void DeInit() +{ + for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + { + TCPSocket* sock = &TCPSocketList[i]; + if (sock->Backend) closesocket(sock->Backend); + } + + for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) + { + UDPSocket* sock = &UDPSocketList[i]; + if (sock->Backend) closesocket(sock->Backend); + } +} + + +void FinishUDPFrame(u8* data, int len) +{ + u8* ipheader = &data[0xE]; + u8* udpheader = &data[0x22]; + + // lengths + *(u16*)&ipheader[2] = htons(len - 0xE); + *(u16*)&udpheader[4] = htons(len - (0xE + 0x14)); + + // IP checksum + u32 tmp = 0; + + for (int i = 0; i < 20; i += 2) + tmp += ntohs(*(u16*)&ipheader[i]); + while (tmp >> 16) + tmp = (tmp & 0xFFFF) + (tmp >> 16); + tmp ^= 0xFFFF; + *(u16*)&ipheader[10] = htons(tmp); + + // UDP checksum + // (note: normally not mandatory, but some older sgIP versions require it) + tmp = 0; + tmp += ntohs(*(u16*)&ipheader[12]); + tmp += ntohs(*(u16*)&ipheader[14]); + tmp += ntohs(*(u16*)&ipheader[16]); + tmp += ntohs(*(u16*)&ipheader[18]); + tmp += ntohs(0x1100); + tmp += (len-0x22); + for (u8* i = udpheader; i < &udpheader[len-0x23]; i += 2) + tmp += ntohs(*(u16*)i); + if (len & 1) + tmp += ntohs((u_short)udpheader[len-0x23]); + while (tmp >> 16) + tmp = (tmp & 0xFFFF) + (tmp >> 16); + tmp ^= 0xFFFF; + if (tmp == 0) tmp = 0xFFFF; + *(u16*)&udpheader[6] = htons(tmp); +} + +void FinishTCPFrame(u8* data, int len) +{ + u8* ipheader = &data[0xE]; + u8* tcpheader = &data[0x22]; + + // lengths + *(u16*)&ipheader[2] = htons(len - 0xE); + + // IP checksum + u32 tmp = 0; + + for (int i = 0; i < 20; i += 2) + tmp += ntohs(*(u16*)&ipheader[i]); + while (tmp >> 16) + tmp = (tmp & 0xFFFF) + (tmp >> 16); + tmp ^= 0xFFFF; + *(u16*)&ipheader[10] = htons(tmp); + + u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14; + + // TCP checksum + tmp = 0; + tmp += ntohs(*(u16*)&ipheader[12]); + tmp += ntohs(*(u16*)&ipheader[14]); + tmp += ntohs(*(u16*)&ipheader[16]); + tmp += ntohs(*(u16*)&ipheader[18]); + tmp += ntohs(0x0600); + tmp += tcplen; + for (u8* i = tcpheader; i < &tcpheader[tcplen-1]; i += 2) + tmp += ntohs(*(u16*)i); + if (tcplen & 1) + tmp += ntohs((u_short)tcpheader[tcplen-1]); + while (tmp >> 16) + tmp = (tmp & 0xFFFF) + (tmp >> 16); + tmp ^= 0xFFFF; + *(u16*)&tcpheader[16] = htons(tmp); +} + + +void HandleDHCPFrame(u8* data, int len) +{ + u8 type = 0xFF; + + u32 transid = *(u32*)&data[0x2E]; + + u8* options = &data[0x11A]; + for (;;) + { + if (options >= &data[len]) break; + u8 opt = *options++; + if (opt == 255) break; + + u8 len = *options++; + switch (opt) + { + case 53: // frame type + type = options[0]; + break; + } + + options += len; + } + + if (type == 0xFF) + { + printf("DHCP: bad frame\n"); + return; + } + + printf("DHCP: frame type %d, transid %08X\n", type, transid); + + if (type == 1 || // discover + type == 3) // request + { + u8 resp[512]; + u8* out = &resp[0]; + + // ethernet + memcpy(out, &data[6], 6); out += 6; + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0800); out += 2; + + // IP + u8* ipheader = out; + *out++ = 0x45; + *out++ = 0x00; + *(u16*)out = 0; out += 2; // total length + *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; + *out++ = 0x00; + *out++ = 0x00; + *out++ = 0x80; // TTL + *out++ = 0x11; // protocol (UDP) + *(u16*)out = 0; out += 2; // checksum + *(u32*)out = htonl(kServerIP); out += 4; // source IP + if (type == 1) + { + *(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP + } + else if (type == 3) + { + *(u32*)out = htonl(kClientIP); out += 4; // destination IP + } + + // UDP + u8* udpheader = out; + *(u16*)out = htons(67); out += 2; // source port + *(u16*)out = htons(68); out += 2; // destination port + *(u16*)out = 0; out += 2; // length + *(u16*)out = 0; out += 2; // checksum + + // DHCP + u8* body = out; + *out++ = 0x02; + *out++ = 0x01; + *out++ = 0x06; + *out++ = 0x00; + *(u32*)out = transid; out += 4; + *(u16*)out = 0; out += 2; // seconds elapsed + *(u16*)out = 0; out += 2; + *(u32*)out = htonl(0x00000000); out += 4; // client IP + *(u32*)out = htonl(kClientIP); out += 4; // your IP + *(u32*)out = htonl(kServerIP); out += 4; // server IP + *(u32*)out = htonl(0x00000000); out += 4; // gateway IP + memcpy(out, &data[6], 6); out += 6; + memset(out, 0, 10); out += 10; + memset(out, 0, 192); out += 192; + *(u32*)out = 0x63538263; out += 4; // DHCP magic + + // DHCP options + *out++ = 53; *out++ = 1; + *out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack + *out++ = 1; *out++ = 4; + *(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask + *out++ = 3; *out++ = 4; + *(u32*)out = htonl(kServerIP); out += 4; // router + *out++ = 51; *out++ = 4; + *(u32*)out = htonl(442030); out += 4; // lease time + *out++ = 54; *out++ = 4; + *(u32*)out = htonl(kServerIP); out += 4; // DHCP server + *out++ = 6; *out++ = 4; + *(u32*)out = htonl(kDNSIP); out += 4; // DNS (hax) + + *out++ = 0xFF; + memset(out, 0, 20); out += 20; + + u32 framelen = (u32)(out - &resp[0]); + if (framelen & 1) { *out++ = 0; framelen++; } + FinishUDPFrame(resp, framelen); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; + } +} + +void HandleDNSFrame(u8* data, int len) +{ + u8* ipheader = &data[0xE]; + u8* udpheader = &data[0x22]; + u8* dnsbody = &data[0x2A]; + + u32 srcip = ntohl(*(u32*)&ipheader[12]); + u16 srcport = ntohs(*(u16*)&udpheader[0]); + + u16 id = ntohs(*(u16*)&dnsbody[0]); + u16 flags = ntohs(*(u16*)&dnsbody[2]); + u16 numquestions = ntohs(*(u16*)&dnsbody[4]); + u16 numanswers = ntohs(*(u16*)&dnsbody[6]); + u16 numauth = ntohs(*(u16*)&dnsbody[8]); + u16 numadd = ntohs(*(u16*)&dnsbody[10]); + + printf("DNS: ID=%04X, flags=%04X, Q=%d, A=%d, auth=%d, add=%d\n", + id, flags, numquestions, numanswers, numauth, numadd); + + // for now we only take 'simple' DNS requests + if (flags & 0x8000) return; + if (numquestions != 1 || numanswers != 0) return; + + u8 resp[1024]; + u8* out = &resp[0]; + + // ethernet + memcpy(out, &data[6], 6); out += 6; + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0800); out += 2; + + // IP + u8* resp_ipheader = out; + *out++ = 0x45; + *out++ = 0x00; + *(u16*)out = 0; out += 2; // total length + *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; + *out++ = 0x00; + *out++ = 0x00; + *out++ = 0x80; // TTL + *out++ = 0x11; // protocol (UDP) + *(u16*)out = 0; out += 2; // checksum + *(u32*)out = htonl(kDNSIP); out += 4; // source IP + *(u32*)out = htonl(srcip); out += 4; // destination IP + + // UDP + u8* resp_udpheader = out; + *(u16*)out = htons(53); out += 2; // source port + *(u16*)out = htons(srcport); out += 2; // destination port + *(u16*)out = 0; out += 2; // length + *(u16*)out = 0; out += 2; // checksum + + // DNS + u8* resp_body = out; + *(u16*)out = htons(id); out += 2; // ID + *(u16*)out = htons(0x8000); out += 2; // flags + *(u16*)out = htons(numquestions); out += 2; // num questions + *(u16*)out = htons(numquestions); out += 2; // num answers + *(u16*)out = 0; out += 2; // num authority + *(u16*)out = 0; out += 2; // num additional + + u32 curoffset = 12; + for (u16 i = 0; i < numquestions; i++) + { + if (curoffset >= (len-0x2A)) return; + + u8 bitlength = 0; + while ((bitlength = dnsbody[curoffset++]) != 0) + curoffset += bitlength; + + curoffset += 4; + } + + u32 qlen = curoffset-12; + if (qlen > 512) return; + memcpy(out, &dnsbody[12], qlen); out += qlen; + + curoffset = 12; + for (u16 i = 0; i < numquestions; i++) + { + // assemble the requested domain name + u8 bitlength = 0; + char domainname[256] = ""; int o = 0; + while ((bitlength = dnsbody[curoffset++]) != 0) + { + if ((o+bitlength) >= 255) + { + // welp. atleast try not to explode. + domainname[o++] = '\0'; + break; + } + + strncpy(&domainname[o], (const char *)&dnsbody[curoffset], bitlength); + o += bitlength; + + curoffset += bitlength; + if (dnsbody[curoffset] != 0) + domainname[o++] = '.'; + else + domainname[o++] = '\0'; + } + + u16 type = ntohs(*(u16*)&dnsbody[curoffset]); + u16 cls = ntohs(*(u16*)&dnsbody[curoffset+2]); + + printf("- q%d: %04X %04X %s", i, type, cls, domainname); + + // get answer + struct addrinfo dns_hint; + struct addrinfo* dns_res; + u32 addr_res; + + memset(&dns_hint, 0, sizeof(dns_hint)); + dns_hint.ai_family = AF_INET; // TODO: other address types (INET6, etc) + if (getaddrinfo(domainname, "0", &dns_hint, &dns_res) == 0) + { + struct addrinfo* p = dns_res; + while (p) + { + struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr; + /*printf(" -> %d.%d.%d.%d", + addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, + addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4);*/ + + //addr_res = addr->sin_addr.S_un.S_addr; + addr_res = *(u32*)&addr->sin_addr; + p = p->ai_next; + } + } + else + { + printf(" shat itself :("); + addr_res = 0; + } + + printf("\n"); + curoffset += 4; + + // TODO: betterer support + // (under which conditions does the C00C marker work?) + *(u16*)out = htons(0xC00C); out += 2; + *(u16*)out = htons(type); out += 2; + *(u16*)out = htons(cls); out += 2; + *(u32*)out = htonl(3600); out += 4; // TTL (hardcoded for now) + *(u16*)out = htons(4); out += 2; // address length + *(u32*)out = addr_res; out += 4; // address + } + + u32 framelen = (u32)(out - &resp[0]); + if (framelen & 1) { *out++ = 0; framelen++; } + FinishUDPFrame(resp, framelen); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; +} + +void UDP_BuildIncomingFrame(UDPSocket* sock, u8* data, int len) +{ + u8 resp[2048]; + u8* out = &resp[0]; + + if (len > 1536) return; + + // ethernet + memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0800); out += 2; + + // IP + u8* resp_ipheader = out; + *out++ = 0x45; + *out++ = 0x00; + *(u16*)out = 0; out += 2; // total length + *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; + *out++ = 0x00; + *out++ = 0x00; + *out++ = 0x80; // TTL + *out++ = 0x11; // protocol (UDP) + *(u16*)out = 0; out += 2; // checksum + memcpy(out, sock->DestIP, 4); out += 4; // source IP + *(u32*)out = htonl(kClientIP); out += 4; // destination IP + + // UDP + u8* resp_tcpheader = out; + *(u16*)out = htons(sock->DestPort); out += 2; // source port + *(u16*)out = htons(sock->SourcePort); out += 2; // destination port + *(u16*)out = htons(len+8); out += 2; // length of header+data + *(u16*)out = 0; out += 2; // checksum + + memcpy(out, data, len); out += len; + + u32 framelen = (u32)(out - &resp[0]); + FinishUDPFrame(resp, framelen); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; +} + +void HandleUDPFrame(u8* data, int len) +{ + u8* ipheader = &data[0xE]; + u8* udpheader = &data[0x22]; + + // debug + /*for (int j = 0; j < len; j += 16) + { + int rem = len - j; + if (rem > 16) rem = 16; + for (int i = 0; i < rem; i++) + { + printf("%02X ", data[i+j]); + } + printf("\n"); + }*/ + + u16 srcport = ntohs(*(u16*)&udpheader[0]); + u16 dstport = ntohs(*(u16*)&udpheader[2]); + + int sockid = -1; + UDPSocket* sock; + for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) + { + sock = &UDPSocketList[i]; + if (sock->Backend != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && + sock->SourcePort == srcport && sock->DestPort == dstport) + { + sockid = i; + break; + } + } + + if (sockid == -1) + { + sockid = UDPSocketID; + sock = &UDPSocketList[sockid]; + + UDPSocketID++; + if (UDPSocketID >= (sizeof(UDPSocketList)/sizeof(UDPSocket))) + UDPSocketID = 0; + + if (sock->Backend != 0) + { + printf("LANMAGIC: closing previous UDP socket #%d\n", sockid); + closesocket(sock->Backend); + } + + sock->Backend = socket(AF_INET, SOCK_DGRAM, 0); + + memcpy(sock->DestIP, &ipheader[16], 4); + sock->SourcePort = srcport; + sock->DestPort = dstport; + + memset(&sock->BackendAddr, 0, sizeof(sock->BackendAddr)); + sock->BackendAddr.sin_family = AF_INET; + sock->BackendAddr.sin_port = htons(dstport); + memcpy(&sock->BackendAddr.sin_addr, &ipheader[16], 4); + /*if (bind(sock->Backend, (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)) == -1) + { + printf("bind() shat itself :(\n"); + }*/ + + printf("LANMAGIC: opening UDP socket #%d to %d.%d.%d.%d:%d, srcport %d\n", + sockid, + ipheader[16], ipheader[17], ipheader[18], ipheader[19], + dstport, srcport); + } + + u16 udplen = ntohs(*(u16*)&udpheader[4]) - 8; + + printf("UDP: socket %d sending %d bytes\n", sockid, udplen); + sendto(sock->Backend, (char*)&udpheader[8], udplen, 0, + (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)); +} + +void TCP_SYNACK(TCPSocket* sock, u8* data, int len) +{ + u8 resp[128]; + u8* out = &resp[0]; + + u8* ipheader = &data[0xE]; + u8* tcpheader = &data[0x22]; + + u32 seqnum = htonl(*(u32*)&tcpheader[4]); + seqnum++; + sock->AckNum = seqnum; + + //printf("SYNACK SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum); + + // ethernet + memcpy(out, &data[6], 6); out += 6; + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0800); out += 2; + + // IP + u8* resp_ipheader = out; + *out++ = 0x45; + *out++ = 0x00; + *(u16*)out = 0; out += 2; // total length + *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; + *out++ = 0x00; + *out++ = 0x00; + *out++ = 0x80; // TTL + *out++ = 0x06; // protocol (TCP) + *(u16*)out = 0; out += 2; // checksum + *(u32*)out = *(u32*)&ipheader[16]; out += 4; // source IP + *(u32*)out = *(u32*)&ipheader[12]; out += 4; // destination IP + + // TCP + u8* resp_tcpheader = out; + *(u16*)out = *(u16*)&tcpheader[2]; out += 2; // source port + *(u16*)out = *(u16*)&tcpheader[0]; out += 2; // destination port + *(u32*)out = htonl(sock->SeqNum); out += 4; sock->SeqNum++; // seq number + *(u32*)out = htonl(seqnum); out += 4; // ack seq number + *(u16*)out = htons(0x8012); out += 2; // flags (SYN+ACK) + *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) + *(u16*)out = 0; out += 2; // checksum + *(u16*)out = 0; out += 2; // urgent pointer + + // TCP options + *out++ = 0x02; *out++ = 0x04; // max segment size + *(u16*)out = htons(0x05B4); out += 2; + *out++ = 0x01; + *out++ = 0x01; + *out++ = 0x04; *out++ = 0x02; // SACK permitted + *out++ = 0x01; + *out++ = 0x03; *out++ = 0x03; // window size + *out++ = 0x08; + + u32 framelen = (u32)(out - &resp[0]); + //if (framelen & 1) { *out++ = 0; framelen++; } + FinishTCPFrame(resp, framelen); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; +} + +void TCP_ACK(TCPSocket* sock, bool fin) +{ + u8 resp[64]; + u8* out = &resp[0]; + + u16 flags = 0x5010; + if (fin) flags |= 0x0001; + + //printf("%sACK SEQ=%08X|%08X\n", fin?"FIN":" ", sock->SeqNum, sock->AckNum); + + // ethernet + memcpy(out, Wifi::GetMAC(), 6); out += 6; + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0800); out += 2; + + // IP + u8* resp_ipheader = out; + *out++ = 0x45; + *out++ = 0x00; + *(u16*)out = 0; out += 2; // total length + *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; + *out++ = 0x00; + *out++ = 0x00; + *out++ = 0x80; // TTL + *out++ = 0x06; // protocol (TCP) + *(u16*)out = 0; out += 2; // checksum + *(u32*)out = *(u32*)&sock->DestIP; out += 4; // source IP + *(u32*)out = htonl(kClientIP); out += 4; // destination IP + + // TCP + u8* resp_tcpheader = out; + *(u16*)out = htonl(sock->DestPort); out += 2; // source port + *(u16*)out = htonl(sock->SourcePort); out += 2; // destination port + *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number + *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number + *(u16*)out = htons(flags); out += 2; // flags + *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) + *(u16*)out = 0; out += 2; // checksum + *(u16*)out = 0; out += 2; // urgent pointer + + u32 framelen = (u32)(out - &resp[0]); + //if (framelen & 1) { *out++ = 0; framelen++; } + FinishTCPFrame(resp, framelen); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; +} + +void TCP_BuildIncomingFrame(TCPSocket* sock, u8* data, int len) +{ + u8 resp[2048]; + u8* out = &resp[0]; + + if (len > 1536) return; +//printf("INCOMING SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum); + // ethernet + memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0800); out += 2; + + // IP + u8* resp_ipheader = out; + *out++ = 0x45; + *out++ = 0x00; + *(u16*)out = 0; out += 2; // total length + *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; + *out++ = 0x00; + *out++ = 0x00; + *out++ = 0x80; // TTL + *out++ = 0x06; // protocol (TCP) + *(u16*)out = 0; out += 2; // checksum + memcpy(out, sock->DestIP, 4); out += 4; // source IP + *(u32*)out = htonl(kClientIP); out += 4; // destination IP + + // TCP + u8* resp_tcpheader = out; + *(u16*)out = htons(sock->DestPort); out += 2; // source port + *(u16*)out = htons(sock->SourcePort); out += 2; // destination port + *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number + *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number + *(u16*)out = htons(0x5018); out += 2; // flags (ACK, PSH) + *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) + *(u16*)out = 0; out += 2; // checksum + *(u16*)out = 0; out += 2; // urgent pointer + + memcpy(out, data, len); out += len; + + u32 framelen = (u32)(out - &resp[0]); + FinishTCPFrame(resp, framelen); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; + + sock->SeqNum += len; +} + +void HandleTCPFrame(u8* data, int len) +{ + u8* ipheader = &data[0xE]; + u8* tcpheader = &data[0x22]; + + u16 srcport = ntohs(*(u16*)&tcpheader[0]); + u16 dstport = ntohs(*(u16*)&tcpheader[2]); + u16 flags = ntohs(*(u16*)&tcpheader[12]); + + u32 tcpheaderlen = 4 * (flags >> 12); + u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14; + u32 tcpdatalen = tcplen - tcpheaderlen; + + /*printf("tcpflags=%04X header=%d data=%d seq=%08X|%08X\n", + flags, tcpheaderlen, tcpdatalen, + ntohl(*(u32*)&tcpheader[4]), + ntohl(*(u32*)&tcpheader[8]));*/ + + if (flags & 0x002) // SYN + { + int sockid = -1; + TCPSocket* sock; + for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + { + sock = &TCPSocketList[i]; + if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && + sock->SourcePort == srcport && sock->DestPort == dstport) + { + printf("LANMAGIC: duplicate TCP socket\n"); + sockid = i; + break; + } + } + + if (sockid == -1) + { + for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + { + sock = &TCPSocketList[i]; + if (sock->Status == 0) + { + sockid = i; + break; + } + } + } + + if (sockid == -1) + { + printf("LANMAGIC: !! TCP SOCKET LIST FULL\n"); + return; + } + + printf("LANMAGIC: opening TCP socket #%d to %d.%d.%d.%d:%d, srcport %d\n", + sockid, + ipheader[16], ipheader[17], ipheader[18], ipheader[19], + dstport, srcport); + + // keep track of it + sock->Status = 1; + memcpy(sock->DestIP, &ipheader[16], 4); + sock->DestPort = dstport; + sock->SourcePort = srcport; + sock->SeqNum = 0x13370000; + sock->AckNum = 0; + + // open backend socket + if (!sock->Backend) + { + sock->Backend = socket(AF_INET, SOCK_STREAM, 0); + } + + struct sockaddr_in conn_addr; + memset(&conn_addr, 0, sizeof(conn_addr)); + conn_addr.sin_family = AF_INET; + memcpy(&conn_addr.sin_addr, &ipheader[16], 4); + conn_addr.sin_port = htons(dstport); + if (connect(sock->Backend, (sockaddr*)&conn_addr, sizeof(conn_addr)) == -1) + { + printf("connect() shat itself :(\n"); + } + else + { + // acknowledge it + TCP_SYNACK(sock, data, len); + } + } + else + { + int sockid = -1; + TCPSocket* sock; + for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + { + sock = &TCPSocketList[i]; + if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && + sock->SourcePort == srcport && sock->DestPort == dstport) + { + sockid = i; + break; + } + } + + if (sockid == -1) + { + printf("LANMAGIC: bad TCP packet\n"); + return; + } + + // TODO: check those + u32 seqnum = ntohl(*(u32*)&tcpheader[4]); + u32 acknum = ntohl(*(u32*)&tcpheader[8]); + sock->SeqNum = acknum; + sock->AckNum = seqnum + tcpdatalen; + + // send data over the socket + if (tcpdatalen > 0) + { + u8* tcpdata = &tcpheader[tcpheaderlen]; + + printf("TCP: socket %d sending %d bytes (flags=%04X)\n", sockid, tcpdatalen, flags); + send(sock->Backend, (char*)tcpdata, tcpdatalen, 0); + + // kind of a hack, there + TCP_ACK(sock, false); + } + + if (flags & 0x001) // FIN + { + // TODO: timeout etc + printf("TCP: socket %d closing\n", sockid); + + sock->Status = 0; + closesocket(sock->Backend); + sock->Backend = 0; + } + } +} + +void HandleARPFrame(u8* data, int len) +{ + u16 protocol = ntohs(*(u16*)&data[0x10]); + if (protocol != 0x0800) return; + + u16 op = ntohs(*(u16*)&data[0x14]); + u32 targetip = ntohl(*(u32*)&data[0x26]); + + // TODO: handle ARP to the client + // this only handles ARP to the DHCP/router + + if (op == 1) + { + // opcode 1=req 2=reply + // sender MAC + // sender IP + // target MAC + // target IP + + const u8* targetmac; + if (targetip == kServerIP) targetmac = kServerMAC; + else if (targetip == kDNSIP) targetmac = kDNSMAC; + else return; + + u8 resp[64]; + u8* out = &resp[0]; + + // ethernet + memcpy(out, &data[6], 6); out += 6; + memcpy(out, kServerMAC, 6); out += 6; + *(u16*)out = htons(0x0806); out += 2; + + // ARP + *(u16*)out = htons(0x0001); out += 2; // hardware type + *(u16*)out = htons(0x0800); out += 2; // protocol + *out++ = 6; // MAC address size + *out++ = 4; // IP address size + *(u16*)out = htons(0x0002); out += 2; // opcode + memcpy(out, targetmac, 6); out += 6; + *(u32*)out = htonl(targetip); out += 4; + memcpy(out, &data[0x16], 6+4); out += 6+4; + + u32 framelen = (u32)(out - &resp[0]); + + // TODO: if there is already a packet queued, this will overwrite it + // that being said, this will only happen during DHCP setup, so probably + // not a big deal + + PacketLen = framelen; + memcpy(PacketBuffer, resp, PacketLen); + RXNum = 1; + } + else + { + printf("wat??\n"); + } +} + +void HandlePacket(u8* data, int len) +{ + u16 ethertype = ntohs(*(u16*)&data[0xC]); + + if (ethertype == 0x0800) // IPv4 + { + u8 protocol = data[0x17]; + if (protocol == 0x11) // UDP + { + u16 srcport = ntohs(*(u16*)&data[0x22]); + u16 dstport = ntohs(*(u16*)&data[0x24]); + if (srcport == 68 && dstport == 67) // DHCP + { + printf("LANMAGIC: DHCP packet\n"); + return HandleDHCPFrame(data, len); + } + else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS + { + printf("LANMAGIC: DNS packet\n"); + return HandleDNSFrame(data, len); + } + + printf("LANMAGIC: UDP packet %d->%d\n", srcport, dstport); + return HandleUDPFrame(data, len); + } + else if (protocol == 0x06) // TCP + { + printf("LANMAGIC: TCP packet\n"); + return HandleTCPFrame(data, len); + } + else + printf("LANMAGIC: unsupported IP protocol %02X\n", protocol); + } + else if (ethertype == 0x0806) // ARP + { + printf("LANMAGIC: ARP packet\n"); + return HandleARPFrame(data, len); + } + else + printf("LANMAGIC: unsupported ethernet type %04X\n", ethertype); +} + +int SendPacket(u8* data, int len) +{ + if (len > 2048) + { + printf("LAN_SendPacket: error: packet too long (%d)\n", len); + return 0; + } + + HandlePacket(data, len); + return len; +} + +int RecvPacket(u8* data) +{ + int ret = 0; + if (RXNum > 0) + { + memcpy(data, PacketBuffer, PacketLen); + ret = PacketLen; + RXNum = 0; + } + + for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + { + TCPSocket* sock = &TCPSocketList[i]; + if (sock->Status != 1) continue; + + fd_set fd; + struct timeval tv; + + FD_ZERO(&fd); + FD_SET(sock->Backend, &fd); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (!select(sock->Backend+1, &fd, 0, 0, &tv)) + { + continue; + } + + u8 recvbuf[1024]; + int recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); + if (recvlen < 1) + { + if (recvlen == 0) + { + // socket has closed from the other side + printf("TCP: socket %d closed from other side\n", i); + sock->Status = 2; + TCP_ACK(sock, true); + } + continue; + } + + printf("TCP: socket %d receiving %d bytes\n", i, recvlen); + TCP_BuildIncomingFrame(sock, recvbuf, recvlen); + + // debug + /*for (int j = 0; j < recvlen; j += 16) + { + int rem = recvlen - j; + if (rem > 16) rem = 16; + for (int k = 0; k < rem; k++) + { + printf("%02X ", recvbuf[k+j]); + } + printf("\n"); + }*/ + + //recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); + //if (recvlen == 0) printf("it closed immediately after\n"); + } + + for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) + { + UDPSocket* sock = &UDPSocketList[i]; + if (sock->Backend == 0) continue; + + fd_set fd; + struct timeval tv; + + FD_ZERO(&fd); + FD_SET(sock->Backend, &fd); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (!select(sock->Backend+1, &fd, 0, 0, &tv)) + { + continue; + } + + u8 recvbuf[1024]; + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + int recvlen = recvfrom(sock->Backend, (char*)recvbuf, 1024, 0, &fromAddr, &fromLen); + if (recvlen < 1) continue; + + if (fromAddr.sa_family != AF_INET) continue; + struct sockaddr_in* fromAddrIn = (struct sockaddr_in*)&fromAddr; + if (memcmp(&fromAddrIn->sin_addr, sock->DestIP, 4)) continue; + if (ntohs(fromAddrIn->sin_port) != sock->DestPort) continue; + + printf("UDP: socket %d receiving %d bytes\n", i, recvlen); + UDP_BuildIncomingFrame(sock, recvbuf, recvlen); + } + + return ret; +} + +} diff --git a/src/frontend/qt_sdl/LAN_Socket.h b/src/frontend/qt_sdl/LAN_Socket.h new file mode 100644 index 00000000..8453a5f4 --- /dev/null +++ b/src/frontend/qt_sdl/LAN_Socket.h @@ -0,0 +1,38 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef LAN_SOCKET_H +#define LAN_SOCKET_H + +#include "../types.h" + +namespace LAN_Socket +{ + +// + + +bool Init(); +void DeInit(); + +int SendPacket(u8* data, int len); +int RecvPacket(u8* data); + +} + +#endif // LAN_SOCKET_H diff --git a/src/frontend/qt_sdl/WifiSettingsDialog.ui b/src/frontend/qt_sdl/WifiSettingsDialog.ui new file mode 100644 index 00000000..bfee1fd5 --- /dev/null +++ b/src/frontend/qt_sdl/WifiSettingsDialog.ui @@ -0,0 +1,165 @@ + + + WifiSettingsDialog + + + + 0 + 0 + 479 + 217 + + + + + 0 + 0 + + + + Wifi settings - melonDS + + + + QLayout::SetFixedSize + + + + + Local + + + + + + <html><head/><body><p>Enabling this allows (theoretically) playing local multiplayer games over a local network. It may or may not help make for a better connection in general.</p></body></html> + + + Bind socket to any address + + + + + + + + + + Online + + + + + + MAC address: + + + + + + + <html><head/><body><p>Direct mode directly routes network traffic to the host network. It is the most reliable, but requires an ethernet connection.</p><p><br/></p><p>Non-direct mode uses a layer of emulation to get around this, but is more prone to problems.</p></body></html> + + + Direct mode [TEXT PLACEHOLDER] + + + + + + + + 0 + 0 + + + + + 350 + 0 + + + + <html><head/><body><p>Selects the network adapter through which to route network traffic under direct mode.</p></body></html> + + + + + + + Network adapter: + + + + + + + IP address: + + + + + + + [PLACEHOLDER] + + + + + + + [PLACEHOLDER] + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + WifiSettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WifiSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/pcap/bluetooth.h b/src/frontend/qt_sdl/pcap/bluetooth.h similarity index 100% rename from src/pcap/bluetooth.h rename to src/frontend/qt_sdl/pcap/bluetooth.h diff --git a/src/pcap/bpf.h b/src/frontend/qt_sdl/pcap/bpf.h similarity index 100% rename from src/pcap/bpf.h rename to src/frontend/qt_sdl/pcap/bpf.h diff --git a/src/pcap/can_socketcan.h b/src/frontend/qt_sdl/pcap/can_socketcan.h similarity index 100% rename from src/pcap/can_socketcan.h rename to src/frontend/qt_sdl/pcap/can_socketcan.h diff --git a/src/pcap/compiler-tests.h b/src/frontend/qt_sdl/pcap/compiler-tests.h similarity index 100% rename from src/pcap/compiler-tests.h rename to src/frontend/qt_sdl/pcap/compiler-tests.h diff --git a/src/pcap/dlt.h b/src/frontend/qt_sdl/pcap/dlt.h similarity index 100% rename from src/pcap/dlt.h rename to src/frontend/qt_sdl/pcap/dlt.h diff --git a/src/pcap/funcattrs.h b/src/frontend/qt_sdl/pcap/funcattrs.h similarity index 100% rename from src/pcap/funcattrs.h rename to src/frontend/qt_sdl/pcap/funcattrs.h diff --git a/src/pcap/ipnet.h b/src/frontend/qt_sdl/pcap/ipnet.h similarity index 100% rename from src/pcap/ipnet.h rename to src/frontend/qt_sdl/pcap/ipnet.h diff --git a/src/pcap/namedb.h b/src/frontend/qt_sdl/pcap/namedb.h similarity index 100% rename from src/pcap/namedb.h rename to src/frontend/qt_sdl/pcap/namedb.h diff --git a/src/pcap/nflog.h b/src/frontend/qt_sdl/pcap/nflog.h similarity index 100% rename from src/pcap/nflog.h rename to src/frontend/qt_sdl/pcap/nflog.h diff --git a/src/pcap/pcap-inttypes.h b/src/frontend/qt_sdl/pcap/pcap-inttypes.h similarity index 100% rename from src/pcap/pcap-inttypes.h rename to src/frontend/qt_sdl/pcap/pcap-inttypes.h diff --git a/src/pcap/pcap.h b/src/frontend/qt_sdl/pcap/pcap.h similarity index 100% rename from src/pcap/pcap.h rename to src/frontend/qt_sdl/pcap/pcap.h diff --git a/src/pcap/sll.h b/src/frontend/qt_sdl/pcap/sll.h similarity index 100% rename from src/pcap/sll.h rename to src/frontend/qt_sdl/pcap/sll.h diff --git a/src/pcap/usb.h b/src/frontend/qt_sdl/pcap/usb.h similarity index 100% rename from src/pcap/usb.h rename to src/frontend/qt_sdl/pcap/usb.h diff --git a/src/pcap/vlan.h b/src/frontend/qt_sdl/pcap/vlan.h similarity index 100% rename from src/pcap/vlan.h rename to src/frontend/qt_sdl/pcap/vlan.h From 590ab2ac2bdc79e536c0f332cf9f1a4d700fffe9 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 22:37:37 +0200 Subject: [PATCH 093/105] fix things --- src/frontend/qt_sdl/CMakeLists.txt | 4 ++++ src/frontend/qt_sdl/main.cpp | 21 +++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 0b7fa547..dbc1e3a8 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -7,7 +7,10 @@ SET(SOURCES_QT_SDL InputConfigDialog.cpp VideoSettingsDialog.cpp AudioSettingsDialog.cpp + WifiSettingsDialog.cpp Input.cpp + LAN_PCap.cpp + LAN_Socket.cpp OSD.cpp OSD_shaders.h font.h @@ -40,6 +43,7 @@ pkg_check_modules(SDL2 REQUIRED sdl2) add_executable(melonDS ${SOURCES_QT_SDL}) target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) +target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") target_link_libraries(melonDS core ${SDL2_LIBRARIES}) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index bea33b07..e60a58d4 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -38,6 +38,7 @@ #include "InputConfigDialog.h" #include "VideoSettingsDialog.h" #include "AudioSettingsDialog.h" +#include "WifiSettingsDialog.h" #include "types.h" #include "version.h" @@ -298,9 +299,10 @@ void EmuThread::initOpenGL() oglContext->moveToThread(this); } -void deinitOpenGL() +void EmuThread::deinitOpenGL() { - // TODO!! + delete oglContext; + delete oglSurface; } void* oglGetProcAddress(const char* proc) @@ -545,16 +547,11 @@ void EmuThread::run() NDS::DeInit(); //Platform::LAN_DeInit(); - /*if (Screen_UseGL) - { - OSD::DeInit(true); - GLScreen_DeInit(); - } - else - OSD::DeInit(false);*/ - if (hasOGL) + { oglContext->doneCurrent(); + deinitOpenGL(); + } } void EmuThread::changeWindowTitle(char* title) @@ -844,7 +841,6 @@ void ScreenPanelGL::initializeGL() screenShader->addShaderFromSourceCode(QOpenGLShader::Fragment, kScreenFS); GLuint pid = screenShader->programId(); - printf("program: %d\n", pid); glBindAttribLocation(pid, 0, "vPosition"); glBindAttribLocation(pid, 1, "vTexcoord"); glBindFragDataLocation(pid, 0, "oColor"); @@ -1675,7 +1671,7 @@ void MainWindow::onAudioSettingsFinished(int res) void MainWindow::onOpenWifiSettings() { - // + WifiSettingsDialog::openDlg(this); } void MainWindow::onChangeSavestateSRAMReloc(bool checked) @@ -1822,6 +1818,7 @@ void MainWindow::onUpdateVideoSettings(bool glchange) { emuThread->emuPause(); + if (hasOGL) emuThread->deinitOpenGL(); delete panel; createScreenPanel(); connect(emuThread, SIGNAL(windowUpdate()), panel, SLOT(update())); From a38b20484d72d9d03ac7c807323343c8576c2c35 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 28 May 2020 23:12:21 +0200 Subject: [PATCH 094/105] finish the wifi dialog also guess who the idiot is who forgot to add their files --- src/frontend/qt_sdl/Platform.cpp | 22 ++-- src/frontend/qt_sdl/WifiSettingsDialog.cpp | 140 +++++++++++++++++++++ src/frontend/qt_sdl/WifiSettingsDialog.h | 68 ++++++++++ src/frontend/qt_sdl/main.cpp | 19 ++- src/frontend/qt_sdl/main.h | 1 + 5 files changed, 237 insertions(+), 13 deletions(-) create mode 100644 src/frontend/qt_sdl/WifiSettingsDialog.cpp create mode 100644 src/frontend/qt_sdl/WifiSettingsDialog.h diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 6b256e02..edc8d45b 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -22,8 +22,8 @@ #include #include "Platform.h" #include "PlatformConfig.h" -//#include "LAN_Socket.h" -//#include "LAN_PCap.h" +#include "LAN_Socket.h" +#include "LAN_PCap.h" #include #ifdef __WIN32__ @@ -559,7 +559,7 @@ int MP_RecvPacket(u8* data, bool block) bool LAN_Init() { - /*if (Config::DirectLAN) + if (Config::DirectLAN) { if (!LAN_PCap::Init(true)) return false; @@ -568,7 +568,7 @@ bool LAN_Init() { if (!LAN_Socket::Init()) return false; - }*/ + } return true; } @@ -580,26 +580,24 @@ void LAN_DeInit() // LAN_PCap::DeInit(); //else // LAN_Socket::DeInit(); - /*LAN_PCap::DeInit(); - LAN_Socket::DeInit();*/ + LAN_PCap::DeInit(); + LAN_Socket::DeInit(); } int LAN_SendPacket(u8* data, int len) { - /*if (Config::DirectLAN) + if (Config::DirectLAN) return LAN_PCap::SendPacket(data, len); else - return LAN_Socket::SendPacket(data, len);*/ - return 0; + return LAN_Socket::SendPacket(data, len); } int LAN_RecvPacket(u8* data) { - /*if (Config::DirectLAN) + if (Config::DirectLAN) return LAN_PCap::RecvPacket(data); else - return LAN_Socket::RecvPacket(data);*/ - return 0; + return LAN_Socket::RecvPacket(data); } diff --git a/src/frontend/qt_sdl/WifiSettingsDialog.cpp b/src/frontend/qt_sdl/WifiSettingsDialog.cpp new file mode 100644 index 00000000..457a78d0 --- /dev/null +++ b/src/frontend/qt_sdl/WifiSettingsDialog.cpp @@ -0,0 +1,140 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include + +#include "types.h" +#include "Platform.h" +#include "Config.h" +#include "PlatformConfig.h" + +#include "LAN_Socket.h" +#include "LAN_PCap.h" +#include "Wifi.h" + +#include "WifiSettingsDialog.h" +#include "ui_WifiSettingsDialog.h" + + +#ifdef __WIN32__ +#define PCAP_NAME "winpcap/npcap" +#else +#define PCAP_NAME "libpcap" +#endif + + +WifiSettingsDialog* WifiSettingsDialog::currentDlg = nullptr; + + +WifiSettingsDialog::WifiSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::WifiSettingsDialog) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + LAN_Socket::Init(); + haspcap = LAN_PCap::Init(false); + + ui->cbDirectMode->setText("Direct mode (requires " PCAP_NAME " and ethernet connection)"); + + ui->cbBindAnyAddr->setChecked(Config::SocketBindAnyAddr != 0); + + int sel = 0; + for (int i = 0; i < LAN_PCap::NumAdapters; i++) + { + LAN_PCap::AdapterData* adapter = &LAN_PCap::Adapters[i]; + + ui->cbxDirectAdapter->addItem(QString(adapter->FriendlyName)); + + if (!strncmp(adapter->DeviceName, Config::LANDevice, 128)) + sel = i; + } + ui->cbxDirectAdapter->setCurrentIndex(sel); + + ui->cbDirectMode->setChecked(Config::DirectLAN != 0); + if (!haspcap) ui->cbDirectMode->setEnabled(false); + + updateAdapterControls(); +} + +WifiSettingsDialog::~WifiSettingsDialog() +{ + delete ui; +} + +void WifiSettingsDialog::on_WifiSettingsDialog_accepted() +{ + Config::SocketBindAnyAddr = ui->cbBindAnyAddr->isChecked() ? 1:0; + Config::DirectLAN = ui->cbDirectMode->isChecked() ? 1:0; + + int sel = ui->cbxDirectAdapter->currentIndex(); + if (sel < 0 || sel >= LAN_PCap::NumAdapters) sel = 0; + if (LAN_PCap::NumAdapters < 1) + { + Config::LANDevice[0] = '\0'; + } + else + { + strncpy(Config::LANDevice, LAN_PCap::Adapters[sel].DeviceName, 127); + Config::LANDevice[127] = '\0'; + } + + Config::Save(); + + closeDlg(); +} + +void WifiSettingsDialog::on_WifiSettingsDialog_rejected() +{ + closeDlg(); +} + +void WifiSettingsDialog::on_cbDirectMode_stateChanged(int state) +{ + updateAdapterControls(); +} + +void WifiSettingsDialog::on_cbxDirectAdapter_currentIndexChanged(int sel) +{ + if (!haspcap) return; + + if (sel < 0 || sel >= LAN_PCap::NumAdapters) return; + if (LAN_PCap::NumAdapters < 1) return; + + LAN_PCap::AdapterData* adapter = &LAN_PCap::Adapters[sel]; + char tmp[64]; + + sprintf(tmp, "MAC: %02X:%02X:%02X:%02X:%02X:%02X", + adapter->MAC[0], adapter->MAC[1], adapter->MAC[2], + adapter->MAC[3], adapter->MAC[4], adapter->MAC[5]); + ui->lblAdapterMAC->setText(QString(tmp)); + + sprintf(tmp, "IP: %d.%d.%d.%d", + adapter->IP_v4[0], adapter->IP_v4[1], + adapter->IP_v4[2], adapter->IP_v4[3]); + ui->lblAdapterIP->setText(QString(tmp)); +} + +void WifiSettingsDialog::updateAdapterControls() +{ + bool enable = haspcap && ui->cbDirectMode->isChecked(); + + ui->cbxDirectAdapter->setEnabled(enable); + ui->lblAdapterMAC->setEnabled(enable); + ui->lblAdapterIP->setEnabled(enable); +} diff --git a/src/frontend/qt_sdl/WifiSettingsDialog.h b/src/frontend/qt_sdl/WifiSettingsDialog.h new file mode 100644 index 00000000..f8aad1b4 --- /dev/null +++ b/src/frontend/qt_sdl/WifiSettingsDialog.h @@ -0,0 +1,68 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef WIFISETTINGSDIALOG_H +#define WIFISETTINGSDIALOG_H + +#include + +namespace Ui { class WifiSettingsDialog; } +class WifiSettingsDialog; + +class WifiSettingsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit WifiSettingsDialog(QWidget* parent); + ~WifiSettingsDialog(); + + static WifiSettingsDialog* currentDlg; + static WifiSettingsDialog* openDlg(QWidget* parent) + { + if (currentDlg) + { + currentDlg->activateWindow(); + return currentDlg; + } + + currentDlg = new WifiSettingsDialog(parent); + currentDlg->show(); + return currentDlg; + } + static void closeDlg() + { + currentDlg = nullptr; + } + +private slots: + void on_WifiSettingsDialog_accepted(); + void on_WifiSettingsDialog_rejected(); + + void on_cbDirectMode_stateChanged(int state); + void on_cbxDirectAdapter_currentIndexChanged(int sel); + +private: + Ui::WifiSettingsDialog* ui; + + bool haspcap; + + void updateAdapterControls(); +}; + +#endif // WIFISETTINGSDIALOG_H diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index e60a58d4..5870d8a8 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1671,7 +1671,24 @@ void MainWindow::onAudioSettingsFinished(int res) void MainWindow::onOpenWifiSettings() { - WifiSettingsDialog::openDlg(this); + WifiSettingsDialog* dlg = WifiSettingsDialog::openDlg(this); + connect(dlg, &WifiSettingsDialog::finished, this, &MainWindow::onWifiSettingsFinished); +} + +void MainWindow::onWifiSettingsFinished(int res) +{ + emuThread->emuPause(); + + if (Wifi::MPInited) + { + Platform::MP_DeInit(); + Platform::MP_Init(); + } + + Platform::LAN_DeInit(); + Platform::LAN_Init(); + + emuThread->emuUnpause(); } void MainWindow::onChangeSavestateSRAMReloc(bool checked) diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index ef51158e..279aed86 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -205,6 +205,7 @@ private slots: void onOpenAudioSettings(); void onAudioSettingsFinished(int res); void onOpenWifiSettings(); + void onWifiSettingsFinished(int res); void onChangeSavestateSRAMReloc(bool checked); void onChangeScreenSize(); void onChangeScreenRotation(QAction* act); From 935f121025d6736207adb7d17851fb54ea0f767d Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 29 May 2020 21:03:46 +0200 Subject: [PATCH 095/105] * add options for static linking * make the vsync checkbox and shit work to some extent (they don't actually function tho) --- CMakeLists.txt | 7 +++++- src/frontend/qt_sdl/CMakeLists.txt | 28 +++++++++++++++++---- src/frontend/qt_sdl/VideoSettingsDialog.cpp | 15 +++++++++++ src/frontend/qt_sdl/VideoSettingsDialog.h | 3 +++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e640a487..03097251 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) project(melonDS) -if(NOT CMAKE_BUILD_TYPE) +if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() @@ -20,6 +20,7 @@ endif() if (CMAKE_BUILD_TYPE STREQUAL Release) add_compile_options(-O3) + add_link_options(-s) endif() add_compile_options(-fno-pic) @@ -27,6 +28,10 @@ add_link_options(-no-pie) option(BUILD_QT_SDL "Build Qt/SDL frontend" ON) +if (WIN32) + option(BUILD_STATIC "Statically link dependencies" OFF) +endif() + add_subdirectory(src) if (BUILD_QT_SDL) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index dbc1e3a8..8992b504 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -30,9 +30,15 @@ if (WIN32) set(CMAKE_RC_COMPILE_OBJECT " -i -o ") endif() -find_package(Qt5 COMPONENTS Core REQUIRED) -find_package(Qt5 COMPONENTS Gui REQUIRED) -find_package(Qt5 COMPONENTS Widgets REQUIRED) +if (BUILD_STATIC AND QT5_STATIC_DIR) + set(QT5_STATIC_BASE ${QT5_STATIC_DIR}/lib/cmake/Qt5) + set(Qt5_DIR ${QT5_STATIC_BASE}) + set(Qt5Core_DIR ${QT5_STATIC_BASE}Core) + set(Qt5Gui_DIR ${QT5_STATIC_BASE}Gui) + set(Qt5Widgets_DIR ${QT5_STATIC_BASE}Widgets) +endif() + +find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) @@ -46,7 +52,13 @@ target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") -target_link_libraries(melonDS core ${SDL2_LIBRARIES}) +target_link_libraries(melonDS core) + +if (BUILD_STATIC) + target_link_libraries(melonDS -static ${SDL2_LIBRARIES}) +else() + target_link_libraries(melonDS ${SDL2_LIBRARIES}) +endif() if (UNIX) option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) @@ -77,7 +89,13 @@ if (UNIX) target_sources(melonDS PUBLIC melon_grc.c) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 Qt5::Core Qt5::Gui Qt5::Widgets) + + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) + if (BUILD_STATIC) + target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) + else() + target_link_libraries(melonDS Qt5::Core Qt5::Gui Qt5::Widgets) + endif() endif () install(FILES ../../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.cpp b/src/frontend/qt_sdl/VideoSettingsDialog.cpp index efb50518..ba433c33 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.cpp +++ b/src/frontend/qt_sdl/VideoSettingsDialog.cpp @@ -60,6 +60,9 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui( ui->cbxGLResolution->addItem(QString("%1x native (%2x%3)").arg(i).arg(256*i).arg(192*i)); ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1); + if (!Config::ScreenVSync) + ui->sbVSyncInterval->setEnabled(false); + if (Config::_3DRenderer == 0) { ui->cbGLDisplay->setEnabled(true); @@ -136,6 +139,18 @@ void VideoSettingsDialog::on_cbGLDisplay_stateChanged(int state) emit updateVideoSettings(old_gl != new_gl); } +void VideoSettingsDialog::on_cbVSync_stateChanged(int state) +{ + bool vsync = (state != 0); + ui->sbVSyncInterval->setEnabled(vsync); + Config::ScreenVSync = vsync; +} + +void VideoSettingsDialog::on_sbVSyncInterval_valueChanged(int val) +{ + Config::ScreenVSyncInterval = val; +} + void VideoSettingsDialog::on_cbSoftwareThreaded_stateChanged(int state) { Config::Threaded3D = (state != 0); diff --git a/src/frontend/qt_sdl/VideoSettingsDialog.h b/src/frontend/qt_sdl/VideoSettingsDialog.h index 2f6d17cc..2311d4d2 100644 --- a/src/frontend/qt_sdl/VideoSettingsDialog.h +++ b/src/frontend/qt_sdl/VideoSettingsDialog.h @@ -60,6 +60,9 @@ private slots: void onChange3DRenderer(int renderer); void on_cbGLDisplay_stateChanged(int state); + void on_cbVSync_stateChanged(int state); + void on_sbVSyncInterval_valueChanged(int val); + void on_cbxGLResolution_currentIndexChanged(int idx); void on_cbSoftwareThreaded_stateChanged(int state); From d3dd7bd9880bfd6a5b65f263272742105620ccb3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 29 May 2020 21:19:18 +0200 Subject: [PATCH 096/105] get rid of console in release builds --- src/frontend/qt_sdl/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 8992b504..37a8ff1a 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -47,7 +47,12 @@ set(CMAKE_AUTORCC ON) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) -add_executable(melonDS ${SOURCES_QT_SDL}) +if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release)) + add_executable(melonDS WIN32 ${SOURCES_QT_SDL}) +else() + add_executable(melonDS ${SOURCES_QT_SDL}) +endif() + target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") From 9557e18b7cd559679552535e4362115b6d249ab3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 29 May 2020 21:27:40 +0200 Subject: [PATCH 097/105] fart around --- src/frontend/qt_sdl/main.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 5870d8a8..2aaac96e 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -273,6 +273,8 @@ void EmuThread::initOpenGL() QOpenGLContext* windowctx = mainWindow->getOGLContext(); QSurfaceFormat format = windowctx->format(); + format.setSwapInterval(0); + oglSurface = new QOffscreenSurface(); oglSurface->setFormat(format); oglSurface->create(); @@ -791,14 +793,9 @@ void ScreenPanelNative::onScreenLayoutChanged() ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) { - QSurfaceFormat format; - format.setDepthBufferSize(24); - format.setStencilBufferSize(8); - format.setVersion(3, 2); - format.setProfile(QSurfaceFormat::CoreProfile); - setFormat(format); - touching = false; + + curVSync = -1; } ScreenPanelGL::~ScreenPanelGL() From 8ddd82ca2c7c8844a1d3c2cc7418d03976c9c52e Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 29 May 2020 21:35:06 +0200 Subject: [PATCH 098/105] I'm a derp --- src/frontend/qt_sdl/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 2aaac96e..68a32c8d 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -795,7 +795,6 @@ ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent) { touching = false; - curVSync = -1; } ScreenPanelGL::~ScreenPanelGL() From 054b94b2b759abefead466242dd350bc210e4e6b Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 29 May 2020 22:00:31 +0200 Subject: [PATCH 099/105] fix the Github Actions shit, hopefully --- .github/workflows/build-ubuntu.yml | 2 +- .github/workflows/build-windows.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index b57c5b75..6071e33e 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -27,7 +27,7 @@ jobs: && tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ && sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \ && sudo apt-get update \ - && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev + && sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qt5-default - name: Create build environment run: mkdir ${{runner.workspace}}/build - name: Configure diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index ec14e30a..b8e8b04f 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -25,7 +25,7 @@ jobs: 7z x -y msys64.7z "-oC:\tools\" C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Syuq --noconfirm" - name: Install dependencies - run: C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Sq --noconfirm git make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain}" + run: C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Sq --noconfirm git make mingw-w64-x86_64-{cmake,mesa,SDL2,qt5-static,toolchain}" - name: Create build environment run: | New-Item -ItemType directory -Path ${{runner.workspace}}\melonDS\build @@ -33,7 +33,7 @@ jobs: - name: Configure run: | C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \ - && cd melonDS/build && cmake .. -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}" + && cd melonDS/build && cmake .. -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_STATIC=ON -DQT5_STATIC_DIR=C:/tools/msys64/mingw64/qt5-static" - name: Make run: | C:\tools\msys64\usr\bin\bash.exe -lc "export PATH=`"/mingw64/bin:`$PATH`" \ From 88823f66cb7f053e1d0f22d2eb0510ab32d8e474 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 29 May 2020 22:18:21 +0200 Subject: [PATCH 100/105] * fix the OpenGL shito under Linux * make the 'BIOS not found' errors a bit more user-friendly --- src/OpenGLSupport.h | 14 +++++++++++++- src/frontend/qt_sdl/main.cpp | 6 +++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/OpenGLSupport.h b/src/OpenGLSupport.h index edf7edad..925c0ad0 100644 --- a/src/OpenGLSupport.h +++ b/src/OpenGLSupport.h @@ -49,9 +49,21 @@ // if you need more OpenGL functions, add them to the macronator here -#define DO_PROCLIST(func) \ +#ifdef __WIN32__ + +#define DO_PROCLIST_1_3(func) \ func(GLACTIVETEXTURE, glActiveTexture); \ func(GLBLENDCOLOR, glBlendColor); \ + +#else + +#define DO_PROCLIST_1_3(func) + +#endif + + +#define DO_PROCLIST(func) \ + DO_PROCLIST_1_3(func) \ \ func(GLGENFRAMEBUFFERS, glGenFramebuffers); \ func(GLDELETEFRAMEBUFFERS, glDeleteFramebuffers); \ diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 68a32c8d..8df6ec87 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1360,13 +1360,13 @@ QString MainWindow::loadErrorStr(int error) { switch (error) { - case Frontend::Load_BIOS9Missing: return "DS ARM9 BIOS was not found or could not be accessed."; + case Frontend::Load_BIOS9Missing: return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings."; case Frontend::Load_BIOS9Bad: return "DS ARM9 BIOS is not a valid BIOS dump."; - case Frontend::Load_BIOS7Missing: return "DS ARM7 BIOS was not found or could not be accessed."; + case Frontend::Load_BIOS7Missing: return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings."; case Frontend::Load_BIOS7Bad: return "DS ARM7 BIOS is not a valid BIOS dump."; - case Frontend::Load_FirmwareMissing: return "DS firmware was not found or could not be accessed."; + case Frontend::Load_FirmwareMissing: return "DS firmware was not found or could not be accessed. Check your emu settings."; case Frontend::Load_FirmwareBad: return "DS firmware is not a valid firmware dump."; case Frontend::Load_FirmwareNotBootable: return "DS firmware is not bootable."; From c45068da0eb4dc5ce25524cc0b0a12cd78ed036a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 30 May 2020 00:28:21 +0200 Subject: [PATCH 101/105] embed romlist.bin --- CMakeLists.txt | 4 - romlist.bin | Bin 108384 -> 0 bytes src/CMakeLists.txt | 1 + src/NDSCart.cpp | 51 +- src/ROMList.h | 6809 ++++++++++++++++++++++++++++++++++ src/frontend/qt_sdl/main.cpp | 33 - 6 files changed, 6829 insertions(+), 69 deletions(-) delete mode 100644 romlist.bin create mode 100644 src/ROMList.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 03097251..885f0dd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,3 @@ add_subdirectory(src) if (BUILD_QT_SDL) add_subdirectory(src/frontend/qt_sdl) endif() - -configure_file( - ${CMAKE_SOURCE_DIR}/romlist.bin - ${CMAKE_BINARY_DIR}/romlist.bin COPYONLY) diff --git a/romlist.bin b/romlist.bin deleted file mode 100644 index 537439ed979b1a0bf9f8bf717aebca071924d9f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108384 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

UMzxGC5?Hemc{gZrVzpwUv!;^ew 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 P&ZjIN_84#KG2Z_Vi;S%* diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 56bb3cb5..3dc42434 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ add_library(core STATIC NDSCart.cpp OpenGLSupport.cpp Platform.h + ROMList.h RTC.cpp Savestate.cpp SPI.cpp diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 8ced842f..a8c65498 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -23,6 +23,7 @@ #include "ARM.h" #include "CRC32.h" #include "Platform.h" +#include "ROMList.h" namespace NDSCart_SRAM @@ -808,34 +809,21 @@ void ApplyDLDIPatch() } -bool ReadROMParams(u32 gamecode, u32* params) +bool ReadROMParams(u32 gamecode, ROMListEntry* params) { - // format for romlist.bin: - // [gamecode] [ROM size] [save type] [reserved] - // list must be sorted by gamecode - - FILE* f = Platform::OpenDataFile("romlist.bin"); - if (!f) return false; - - fseek(f, 0, SEEK_END); - u32 len = (u32)ftell(f); - u32 maxlen = len; - len >>= 4; // 16 bytes per entry + u32 len = sizeof(ROMList) / sizeof(ROMListEntry); u32 offset = 0; u32 chk_size = len >> 1; for (;;) { u32 key = 0; - fseek(f, offset + (chk_size << 4), SEEK_SET); - fread(&key, 4, 1, f); - - printf("chk_size=%d, key=%08X, wanted=%08X, offset=%08X\n", chk_size, key, gamecode, offset); + ROMListEntry* curentry = &ROMList[offset + chk_size]; + key = curentry->GameCode; if (key == gamecode) { - fread(params, 4, 3, f); - fclose(f); + memcpy(params, curentry, sizeof(ROMListEntry)); return true; } else @@ -843,22 +831,20 @@ bool ReadROMParams(u32 gamecode, u32* params) if (key < gamecode) { if (chk_size == 0) - offset += 0x10; + offset++; else - offset += (chk_size << 4); + offset += chk_size; } else if (chk_size == 0) { - fclose(f); return false; } chk_size >>= 1; } - if (offset >= maxlen) + if (offset >= len) { - fclose(f); return false; } } @@ -936,22 +922,23 @@ bool LoadROM(const char* path, const char* sram, bool direct) CartCRC = CRC32(CartROM, CartROMSize); printf("ROM CRC32: %08X\n", CartCRC); - u32 romparams[3]; - if (!ReadROMParams(gamecode, romparams)) + ROMListEntry romparams; + if (!ReadROMParams(gamecode, &romparams)) { // set defaults printf("ROM entry not found\n"); - romparams[0] = CartROMSize; + romparams.GameCode = gamecode; + romparams.ROMSize = CartROMSize; if (*(u32*)&CartROM[0x20] < 0x4000) - romparams[1] = 0; // no saveRAM for homebrew + romparams.SaveMemType = 0; // no saveRAM for homebrew else - romparams[1] = 2; // assume EEPROM 64k (TODO FIXME) + romparams.SaveMemType = 2; // assume EEPROM 64k (TODO FIXME) } else - printf("ROM entry: %08X %08X %08X\n", romparams[0], romparams[1], romparams[2]); + printf("ROM entry: %08X %08X\n", romparams.ROMSize, romparams.SaveMemType); - if (romparams[0] != len) printf("!! bad ROM size %d (expected %d) rounded to %d\n", len, romparams[0], CartROMSize); + if (romparams.ROMSize != len) printf("!! bad ROM size %d (expected %d) rounded to %d\n", len, romparams.ROMSize, CartROMSize); // generate a ROM ID // note: most games don't check the actual value @@ -963,7 +950,7 @@ bool LoadROM(const char* path, const char* sram, bool direct) else CartID |= (0x100 - (CartROMSize >> 28)) << 8; - if (romparams[1] == 8) + if (romparams.SaveMemType == 8) CartID |= 0x08000000; // NAND flag printf("Cart ID: %08X\n", CartID); @@ -1018,7 +1005,7 @@ bool LoadROM(const char* path, const char* sram, bool direct) // save printf("Save file: %s\n", sram); - NDSCart_SRAM::LoadSave(sram, romparams[1]); + NDSCart_SRAM::LoadSave(sram, romparams.SaveMemType); return true; } diff --git a/src/ROMList.h b/src/ROMList.h new file mode 100644 index 00000000..ead3ee4c --- /dev/null +++ b/src/ROMList.h @@ -0,0 +1,6809 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef ROMLIST_H +#define ROMLIST_H + +typedef struct +{ + u32 GameCode; + u32 ROMSize; + u32 SaveMemType; + +} ROMListEntry; + + +ROMListEntry ROMList[] = +{ + {0x41464141, 0x00800000, 0x00000004}, + {0x414D4155, 0x00800000, 0x00000008}, + {0x43363341, 0x02000000, 0x00000008}, + {0x43443241, 0x02000000, 0x00000002}, + {0x43495941, 0x01000000, 0x00000001}, + {0x434D5341, 0x01000000, 0x00000002}, + {0x434E5341, 0x00800000, 0x00000002}, + {0x43575A41, 0x02000000, 0x00000002}, + {0x44323643, 0x04000000, 0x00000001}, + {0x44324254, 0x04000000, 0x00000002}, + {0x44324C43, 0x00800000, 0x00000001}, + {0x44325542, 0x01000000, 0x00000002}, + {0x44325942, 0x00800000, 0x00000001}, + {0x44334444, 0x02000000, 0x00000001}, + {0x44334542, 0x04000000, 0x00000001}, + {0x44334754, 0x00800000, 0x00000002}, + {0x44334756, 0x02000000, 0x00000002}, + {0x44335141, 0x04000000, 0x00000002}, + {0x44335159, 0x04000000, 0x00000002}, + {0x44335254, 0x02000000, 0x00000001}, + {0x44335742, 0x08000000, 0x00000002}, + {0x44335942, 0x00800000, 0x00000001}, + {0x44343642, 0x00800000, 0x00000001}, + {0x44344259, 0x02000000, 0x00000001}, + {0x44344443, 0x00800000, 0x00000001}, + {0x44345254, 0x02000000, 0x00000001}, + {0x44345542, 0x00800000, 0x00000002}, + {0x44345942, 0x00800000, 0x00000001}, + {0x44353243, 0x02000000, 0x00000002}, + {0x44353642, 0x00800000, 0x00000001}, + {0x44353842, 0x01000000, 0x00000001}, + {0x44354259, 0x02000000, 0x00000002}, + {0x44354442, 0x01000000, 0x00000002}, + {0x44354659, 0x01000000, 0x00000001}, + {0x44354841, 0x02000000, 0x00000002}, + {0x44354C42, 0x01000000, 0x00000002}, + {0x44354C43, 0x00000000, 0x00000001}, + {0x44355342, 0x01000000, 0x00000001}, + {0x44355542, 0x02000000, 0x00000002}, + {0x44355942, 0x00800000, 0x00000001}, + {0x44363243, 0x01000000, 0x00000002}, + {0x44364142, 0x02000000, 0x00000002}, + {0x44364341, 0x01000000, 0x00000002}, + {0x44364843, 0x04000000, 0x00000001}, + {0x44364B43, 0x02000000, 0x00000002}, + {0x44364C42, 0x01000000, 0x00000002}, + {0x44365542, 0x01000000, 0x00000002}, + {0x44374543, 0x02000000, 0x00000002}, + {0x44374959, 0x04000000, 0x00000002}, + {0x44375359, 0x02000000, 0x00000001}, + {0x44384243, 0x02000000, 0x00000001}, + {0x44384A59, 0x01000000, 0x00000002}, + {0x44384F42, 0x01000000, 0x00000001}, + {0x44394259, 0x02000000, 0x00000003}, + {0x44394341, 0x04000000, 0x00000001}, + {0x44394543, 0x01000000, 0x00000003}, + {0x44414441, 0x04000000, 0x00000006}, + {0x44414A42, 0x01000000, 0x00000003}, + {0x44414C59, 0x00800000, 0x00000002}, + {0x44414D56, 0x02000000, 0x00000001}, + {0x44414E43, 0x04000000, 0x00000001}, + {0x44415041, 0x04000000, 0x00000006}, + {0x44415249, 0x10000000, 0x00000006}, + {0x44423542, 0x04000000, 0x00000002}, + {0x44424242, 0x00000000, 0x00000001}, + {0x44424354, 0x08000000, 0x00000001}, + {0x44424542, 0x10000000, 0x00000003}, + {0x44424A42, 0x04000000, 0x00000001}, + {0x44424B42, 0x01000000, 0x00000001}, + {0x44424C54, 0x02000000, 0x00000001}, + {0x44425249, 0x10000000, 0x00000006}, + {0x44425642, 0x02000000, 0x00000002}, + {0x44434343, 0x02000000, 0x00000002}, + {0x44434643, 0x02000000, 0x00000002}, + {0x44434842, 0x01000000, 0x00000001}, + {0x44434A42, 0x04000000, 0x00000002}, + {0x44434C54, 0x01000000, 0x00000001}, + {0x44435159, 0x01000000, 0x00000001}, + {0x44435342, 0x08000000, 0x00000002}, + {0x44435359, 0x01000000, 0x00000001}, + {0x44435559, 0x04000000, 0x00000002}, + {0x44435943, 0x02000000, 0x00000002}, + {0x44444254, 0x04000000, 0x00000002}, + {0x44444842, 0x04000000, 0x00000001}, + {0x44444856, 0x02000000, 0x00000002}, + {0x44445054, 0x08000000, 0x00000001}, + {0x44445249, 0x20000000, 0x00000006}, + {0x44445443, 0x00000000, 0x00000002}, + {0x44445459, 0x02000000, 0x00000002}, + {0x44445641, 0x01000000, 0x00000002}, + {0x44454242, 0x01000000, 0x00000001}, + {0x44454542, 0x10000000, 0x00000003}, + {0x44454559, 0x10000000, 0x00000003}, + {0x44454756, 0x02000000, 0x00000002}, + {0x44454842, 0x02000000, 0x00000002}, + {0x44454D54, 0x00800000, 0x00000002}, + {0x44454E42, 0x02000000, 0x00000001}, + {0x44454E59, 0x02000000, 0x00000002}, + {0x44455143, 0x04000000, 0x00000002}, + {0x44455249, 0x20000000, 0x00000006}, + {0x44455342, 0x01000000, 0x00000001}, + {0x44455642, 0x00800000, 0x00000002}, + {0x44464242, 0x02000000, 0x00000001}, + {0x44464B42, 0x04000000, 0x00000002}, + {0x44464B59, 0x02000000, 0x00000001}, + {0x44464C42, 0x10000000, 0x00000003}, + {0x44465343, 0x00800000, 0x00000001}, + {0x44465359, 0x04000000, 0x00000001}, + {0x44465442, 0x01000000, 0x00000002}, + {0x44473242, 0x04000000, 0x00000001}, + {0x44474B42, 0x00800000, 0x00000002}, + {0x44474C43, 0x04000000, 0x00000001}, + {0x44474D41, 0x01000000, 0x00000001}, + {0x44474D43, 0x04000000, 0x00000001}, + {0x44475049, 0x08000000, 0x00000006}, + {0x44475759, 0x01000000, 0x00000001}, + {0x44483842, 0x04000000, 0x00000002}, + {0x44485142, 0x00800000, 0x00000002}, + {0x44485442, 0x01000000, 0x00000002}, + {0x44493643, 0x00800000, 0x00000001}, + {0x44494243, 0x02000000, 0x00000001}, + {0x44494442, 0x04000000, 0x00000001}, + {0x44494C43, 0x04000000, 0x00000001}, + {0x44495443, 0x00000000, 0x00000002}, + {0x44495742, 0x01000000, 0x00000002}, + {0x444A3343, 0x10000000, 0x00000003}, + {0x444A3443, 0x00800000, 0x00000001}, + {0x444A4542, 0x04000000, 0x00000001}, + {0x444A4742, 0x02000000, 0x00000002}, + {0x444A4F42, 0x04000000, 0x00000002}, + {0x444A5543, 0x00000000, 0x00000002}, + {0x444A5641, 0x04000000, 0x00000002}, + {0x444B3842, 0x02000000, 0x00000002}, + {0x444B4159, 0x08000000, 0x00000002}, + {0x444B4356, 0x08000000, 0x00000002}, + {0x444B4C42, 0x04000000, 0x00000001}, + {0x444B5049, 0x08000000, 0x00000006}, + {0x444C3643, 0x01000000, 0x00000001}, + {0x444C4254, 0x00800000, 0x00000001}, + {0x444C4842, 0x04000000, 0x00000002}, + {0x444C5059, 0x00800000, 0x00000001}, + {0x444C5941, 0x01000000, 0x00000002}, + {0x444D3442, 0x02000000, 0x00000001}, + {0x444D4359, 0x02000000, 0x00000001}, + {0x444D4C54, 0x08000000, 0x00000001}, + {0x444D5642, 0x02000000, 0x00000001}, + {0x444E4242, 0x00800000, 0x00000002}, + {0x444E4259, 0x04000000, 0x00000007}, + {0x444E4641, 0x02000000, 0x00000002}, + {0x444E4C54, 0x00800000, 0x00000002}, + {0x444E4D42, 0x01000000, 0x00000001}, + {0x444F4142, 0x04000000, 0x00000001}, + {0x444F4359, 0x04000000, 0x00000001}, + {0x444F4543, 0x02000000, 0x00000002}, + {0x444F4642, 0x00800000, 0x00000001}, + {0x444F4656, 0x02000000, 0x00000002}, + {0x444F5056, 0x02000000, 0x00000002}, + {0x444F5143, 0x02000000, 0x00000001}, + {0x44504C43, 0x04000000, 0x00000003}, + {0x44505041, 0x01000000, 0x00000002}, + {0x44505342, 0x01000000, 0x00000002}, + {0x44505542, 0x01000000, 0x00000001}, + {0x44505A55, 0x08000000, 0x00000003}, + {0x44513343, 0x04000000, 0x00000002}, + {0x44513443, 0x04000000, 0x00000002}, + {0x44513743, 0x02000000, 0x00000002}, + {0x44514543, 0x04000000, 0x00000002}, + {0x44514A59, 0x01000000, 0x00000001}, + {0x44514C54, 0x00800000, 0x00000002}, + {0x44515142, 0x01000000, 0x00000002}, + {0x44515543, 0x04000000, 0x00000002}, + {0x44515642, 0x02000000, 0x00000002}, + {0x44524642, 0x08000000, 0x00000002}, + {0x44524842, 0x02000000, 0x00000001}, + {0x44525359, 0x00000000, 0x00000005}, + {0x44525642, 0x04000000, 0x00000001}, + {0x44533341, 0x02000000, 0x00000001}, + {0x44534F41, 0x08000000, 0x00000005}, + {0x44535143, 0x02000000, 0x00000001}, + {0x44535342, 0x01000000, 0x00000002}, + {0x44535541, 0x04000000, 0x00000001}, + {0x44535642, 0x02000000, 0x00000002}, + {0x44544442, 0x00800000, 0x00000001}, + {0x44544C59, 0x08000000, 0x00000002}, + {0x44545659, 0x02000000, 0x00000001}, + {0x44545759, 0x01000000, 0x00000001}, + {0x44553243, 0x04000000, 0x00000002}, + {0x44553642, 0x00800000, 0x00000001}, + {0x44554254, 0x02000000, 0x00000001}, + {0x44554259, 0x08000000, 0x00000003}, + {0x44554959, 0x04000000, 0x00000001}, + {0x44554D59, 0x04000000, 0x00000002}, + {0x44555043, 0x08000000, 0x00000006}, + {0x44563442, 0x02000000, 0x00000001}, + {0x44564159, 0x04000000, 0x00000002}, + {0x44564643, 0x02000000, 0x00000002}, + {0x44564859, 0x04000000, 0x00000001}, + {0x44564A59, 0x01000000, 0x00000002}, + {0x44564B43, 0x01000000, 0x00000002}, + {0x44564C42, 0x01000000, 0x00000001}, + {0x44564E43, 0x10000000, 0x00000005}, + {0x44565042, 0x00800000, 0x00000002}, + {0x44565841, 0x04000000, 0x00000003}, + {0x44573742, 0x01000000, 0x00000002}, + {0x44574242, 0x01000000, 0x00000002}, + {0x44574642, 0x00800000, 0x00000001}, + {0x44574943, 0x08000000, 0x00000002}, + {0x44574C41, 0x02000000, 0x00000001}, + {0x44574C42, 0x02000000, 0x00000001}, + {0x44575343, 0x04000000, 0x00000001}, + {0x44584D59, 0x00800000, 0x00000001}, + {0x44593443, 0x00000000, 0x00000001}, + {0x44593642, 0x02000000, 0x00000002}, + {0x44594159, 0x02000000, 0x00000001}, + {0x44594442, 0x04000000, 0x00000002}, + {0x44594641, 0x04000000, 0x00000001}, + {0x44594842, 0x01000000, 0x00000001}, + {0x44594A42, 0x04000000, 0x00000001}, + {0x44594A43, 0x04000000, 0x00000001}, + {0x44594A59, 0x00800000, 0x00000001}, + {0x44594C41, 0x04000000, 0x00000001}, + {0x44594D42, 0x01000000, 0x00000002}, + {0x44595143, 0x01000000, 0x00000001}, + {0x445A3643, 0x01000000, 0x00000001}, + {0x445A3659, 0x08000000, 0x00000000}, + {0x445A4341, 0x01000000, 0x00000001}, + {0x445A4641, 0x04000000, 0x00000001}, + {0x445A5054, 0x04000000, 0x00000002}, + {0x445A5142, 0x00000000, 0x00000002}, + {0x445A5359, 0x08000000, 0x00000001}, + {0x445A5442, 0x02000000, 0x00000001}, + {0x445A5443, 0x02000000, 0x00000003}, + {0x445A5942, 0x02000000, 0x00000002}, + {0x45323241, 0x01000000, 0x00000002}, + {0x45323341, 0x04000000, 0x00000008}, + {0x45323343, 0x04000000, 0x00000003}, + {0x45323542, 0x01000000, 0x00000001}, + {0x45323559, 0x08000000, 0x00000008}, + {0x45323643, 0x04000000, 0x00000001}, + {0x45323741, 0x01000000, 0x00000000}, + {0x45323859, 0x00800000, 0x00000000}, + {0x45324142, 0x04000000, 0x00000001}, + {0x45324143, 0x08000000, 0x00000003}, + {0x45324241, 0x02000000, 0x00000002}, + {0x45324242, 0x04000000, 0x00000002}, + {0x45324259, 0x02000000, 0x00000002}, + {0x45324341, 0x04000000, 0x00000001}, + {0x45324343, 0x01000000, 0x00000001}, + {0x45324354, 0x00800000, 0x00000001}, + {0x45324356, 0x02000000, 0x00000001}, + {0x45324359, 0x04000000, 0x00000006}, + {0x45324441, 0x02000000, 0x00000005}, + {0x45324442, 0x01000000, 0x00000002}, + {0x45324456, 0x04000000, 0x00000001}, + {0x45324459, 0x01000000, 0x00000003}, + {0x45324542, 0x00800000, 0x00000003}, + {0x45324643, 0x01000000, 0x00000001}, + {0x45324654, 0x04000000, 0x00000000}, + {0x45324741, 0x04000000, 0x00000001}, + {0x45324759, 0x01000000, 0x00000001}, + {0x45324842, 0x02000000, 0x00000003}, + {0x45324854, 0x01000000, 0x00000001}, + {0x45324859, 0x02000000, 0x00000003}, + {0x45324941, 0x04000000, 0x00000002}, + {0x45324A42, 0x04000000, 0x00000001}, + {0x45324A59, 0x02000000, 0x00000002}, + {0x45324B41, 0x02000000, 0x00000001}, + {0x45324C41, 0x04000000, 0x00000002}, + {0x45324C59, 0x08000000, 0x00000003}, + {0x45324D56, 0x04000000, 0x00000002}, + {0x45324D59, 0x01000000, 0x00000001}, + {0x45325041, 0x02000000, 0x00000001}, + {0x45325042, 0x02000000, 0x00000001}, + {0x45325043, 0x04000000, 0x00000003}, + {0x45325059, 0x04000000, 0x00000005}, + {0x45325141, 0x02000000, 0x00000002}, + {0x45325242, 0x02000000, 0x00000001}, + {0x45325254, 0x02000000, 0x00000002}, + {0x45325341, 0x01000000, 0x00000001}, + {0x45325342, 0x02000000, 0x00000005}, + {0x45325343, 0x00800000, 0x00000001}, + {0x45325359, 0x04000000, 0x00000005}, + {0x45325442, 0x04000000, 0x00000003}, + {0x45325459, 0x00800000, 0x00000001}, + {0x45325642, 0x02000000, 0x00000001}, + {0x45325741, 0x02000000, 0x00000003}, + {0x45325742, 0x01000000, 0x00000002}, + {0x45325759, 0x04000000, 0x00000005}, + {0x45325841, 0x00800000, 0x00000001}, + {0x45325A43, 0x01000000, 0x00000003}, + {0x45333241, 0x01000000, 0x00000008}, + {0x45333259, 0x04000000, 0x00000008}, + {0x45333441, 0x00800000, 0x00000008}, + {0x45333641, 0x02000000, 0x00000008}, + {0x45333759, 0x08000000, 0x00000008}, + {0x45333842, 0x08000000, 0x00000001}, + {0x45333859, 0x00800000, 0x00000000}, + {0x45334159, 0x00800000, 0x00000001}, + {0x45334241, 0x04000000, 0x00000003}, + {0x45334242, 0x08000000, 0x00000001}, + {0x45334259, 0x04000000, 0x00000005}, + {0x45334341, 0x04000000, 0x00000005}, + {0x45334441, 0x02000000, 0x00000005}, + {0x45334442, 0x04000000, 0x00000001}, + {0x45334443, 0x04000000, 0x00000001}, + {0x45334541, 0x04000000, 0x00000001}, + {0x45334641, 0x00800000, 0x00000001}, + {0x45334643, 0x00800000, 0x00000001}, + {0x45334659, 0x02000000, 0x00000002}, + {0x45334741, 0x02000000, 0x00000005}, + {0x45334743, 0x02000000, 0x00000002}, + {0x45334759, 0x02000000, 0x00000003}, + {0x45334841, 0x04000000, 0x00000003}, + {0x45334943, 0x04000000, 0x00000001}, + {0x45334959, 0x04000000, 0x00000002}, + {0x45334A42, 0x04000000, 0x00000005}, + {0x45334A43, 0x00800000, 0x00000001}, + {0x45334A56, 0x02000000, 0x00000001}, + {0x45334B41, 0x02000000, 0x00000002}, + {0x45334C41, 0x02000000, 0x00000001}, + {0x45334C59, 0x04000000, 0x00000002}, + {0x45334D43, 0x08000000, 0x00000003}, + {0x45334D54, 0x02000000, 0x00000001}, + {0x45334F41, 0x02000000, 0x00000001}, + {0x45335043, 0x08000000, 0x00000005}, + {0x45335141, 0x04000000, 0x00000002}, + {0x45335159, 0x04000000, 0x00000002}, + {0x45335341, 0x02000000, 0x00000001}, + {0x45335342, 0x01000000, 0x00000001}, + {0x45335343, 0x04000000, 0x00000003}, + {0x45335356, 0x08000000, 0x00000005}, + {0x45335359, 0x00800000, 0x00000001}, + {0x45335456, 0x04000000, 0x00000002}, + {0x45335459, 0x04000000, 0x00000003}, + {0x45335541, 0x02000000, 0x00000002}, + {0x45335543, 0x02000000, 0x00000001}, + {0x45335741, 0x04000000, 0x00000001}, + {0x45335743, 0x08000000, 0x00000002}, + {0x45335759, 0x01000000, 0x00000001}, + {0x45343243, 0x08000000, 0x00000003}, + {0x45343459, 0x00800000, 0x00000000}, + {0x45343543, 0x02000000, 0x00000003}, + {0x45343559, 0x01000000, 0x00000000}, + {0x45343842, 0x02000000, 0x00000001}, + {0x45344241, 0x04000000, 0x00000005}, + {0x45344259, 0x02000000, 0x00000001}, + {0x45344341, 0x04000000, 0x00000001}, + {0x45344441, 0x02000000, 0x00000005}, + {0x45344643, 0x00800000, 0x00000001}, + {0x45344659, 0x08000000, 0x00000003}, + {0x45344759, 0x10000000, 0x00000003}, + {0x45344842, 0x00800000, 0x00000001}, + {0x45344843, 0x04000000, 0x00000002}, + {0x45344943, 0x04000000, 0x00000002}, + {0x45344A42, 0x00800000, 0x00000001}, + {0x45344A43, 0x01000000, 0x00000001}, + {0x45344A56, 0x02000000, 0x00000001}, + {0x45344C41, 0x00800000, 0x00000001}, + {0x45344D41, 0x00800000, 0x00000000}, + {0x45344D43, 0x01000000, 0x00000003}, + {0x45344D56, 0x02000000, 0x00000002}, + {0x45344E41, 0x04000000, 0x00000001}, + {0x45345059, 0x04000000, 0x00000002}, + {0x45345141, 0x02000000, 0x00000001}, + {0x45345341, 0x02000000, 0x00000003}, + {0x45345342, 0x01000000, 0x00000001}, + {0x45345456, 0x04000000, 0x00000003}, + {0x45345459, 0x02000000, 0x00000001}, + {0x45345642, 0x01000000, 0x00000001}, + {0x45345643, 0x04000000, 0x00000001}, + {0x45345659, 0x08000000, 0x00000003}, + {0x45345741, 0x02000000, 0x00000002}, + {0x45345742, 0x02000000, 0x00000002}, + {0x45345759, 0x04000000, 0x00000003}, + {0x45345A43, 0x04000000, 0x00000001}, + {0x45353541, 0x01000000, 0x00000008}, + {0x45353542, 0x00800000, 0x00000001}, + {0x45353841, 0x02000000, 0x00000008}, + {0x45353941, 0x04000000, 0x00000008}, + {0x45354143, 0x08000000, 0x00000003}, + {0x45354259, 0x02000000, 0x00000002}, + {0x45354359, 0x00800000, 0x00000008}, + {0x45354441, 0x02000000, 0x00000005}, + {0x45354443, 0x02000000, 0x00000001}, + {0x45354643, 0x00800000, 0x00000002}, + {0x45354741, 0x01000000, 0x00000001}, + {0x45354743, 0x04000000, 0x00000001}, + {0x45354841, 0x02000000, 0x00000002}, + {0x45354943, 0x01000000, 0x00000001}, + {0x45354959, 0x04000000, 0x00000002}, + {0x45354B41, 0x02000000, 0x00000001}, + {0x45354B43, 0x04000000, 0x00000005}, + {0x45354C41, 0x04000000, 0x00000001}, + {0x45354D43, 0x04000000, 0x00000001}, + {0x45354E59, 0x04000000, 0x00000002}, + {0x45354F42, 0x10000000, 0x00000005}, + {0x45355043, 0x02000000, 0x00000001}, + {0x45355059, 0x01000000, 0x00000001}, + {0x45355141, 0x00800000, 0x00000001}, + {0x45355241, 0x02000000, 0x00000001}, + {0x45355243, 0x08000000, 0x00000001}, + {0x45355259, 0x02000000, 0x00000002}, + {0x45355341, 0x01000000, 0x00000001}, + {0x45355342, 0x01000000, 0x00000001}, + {0x45355343, 0x04000000, 0x00000001}, + {0x45355356, 0x02000000, 0x00000002}, + {0x45355359, 0x04000000, 0x00000001}, + {0x45355541, 0x00800000, 0x00000001}, + {0x45355643, 0x02000000, 0x00000001}, + {0x45355659, 0x08000000, 0x00000003}, + {0x45355843, 0x01000000, 0x00000001}, + {0x45355941, 0x08000000, 0x00000003}, + {0x45363241, 0x02000000, 0x00000008}, + {0x45363341, 0x02000000, 0x00000008}, + {0x45363359, 0x01000000, 0x00000008}, + {0x45363442, 0x01000000, 0x00000001}, + {0x45363543, 0x02000000, 0x00000002}, + {0x45363559, 0x04000000, 0x00000008}, + {0x45363642, 0x01000000, 0x00000001}, + {0x45363741, 0x04000000, 0x00000008}, + {0x45363742, 0x02000000, 0x00000001}, + {0x45363842, 0x00800000, 0x00000001}, + {0x45364241, 0x02000000, 0x00000001}, + {0x45364243, 0x02000000, 0x00000002}, + {0x45364254, 0x02000000, 0x00000001}, + {0x45364341, 0x01000000, 0x00000002}, + {0x45364356, 0x02000000, 0x00000002}, + {0x45364542, 0x02000000, 0x00000002}, + {0x45364641, 0x02000000, 0x00000002}, + {0x45364643, 0x04000000, 0x00000002}, + {0x45364742, 0x02000000, 0x00000002}, + {0x45364743, 0x08000000, 0x00000002}, + {0x45364759, 0x04000000, 0x00000002}, + {0x45364841, 0x01000000, 0x00000001}, + {0x45364843, 0x04000000, 0x00000001}, + {0x45364A56, 0x02000000, 0x00000001}, + {0x45364B41, 0x01000000, 0x00000001}, + {0x45364B59, 0x00800000, 0x00000008}, + {0x45364C41, 0x01000000, 0x00000001}, + {0x45364C43, 0x02000000, 0x00000001}, + {0x45364D41, 0x02000000, 0x00000005}, + {0x45364D43, 0x08000000, 0x00000002}, + {0x45364D54, 0x01000000, 0x00000001}, + {0x45364E41, 0x02000000, 0x00000001}, + {0x45364F41, 0x08000000, 0x00000001}, + {0x45365042, 0x01000000, 0x00000001}, + {0x45365241, 0x00800000, 0x00000002}, + {0x45365242, 0x02000000, 0x00000002}, + {0x45365259, 0x02000000, 0x00000002}, + {0x45365342, 0x01000000, 0xFFFFFFFF}, + {0x45365343, 0x04000000, 0x00000002}, + {0x45365359, 0x04000000, 0x00000005}, + {0x45365541, 0x00800000, 0x00000002}, + {0x45365559, 0x02000000, 0x00000002}, + {0x45365642, 0x01000000, 0x00000001}, + {0x45365742, 0x01000000, 0x00000001}, + {0x45365743, 0x04000000, 0x00000002}, + {0x45365941, 0x00800000, 0x00000005}, + {0x45365A42, 0x04000000, 0x00000002}, + {0x45373243, 0x08000000, 0x00000003}, + {0x45373359, 0x01000000, 0x00000001}, + {0x45373442, 0x01000000, 0x00000001}, + {0x45373541, 0x01000000, 0x00000008}, + {0x45373542, 0x00800000, 0xFFFFFFFF}, + {0x45373643, 0x00800000, 0x00000001}, + {0x45374143, 0x02000000, 0x00000002}, + {0x45374159, 0x02000000, 0x00000002}, + {0x45374241, 0x00800000, 0x00000001}, + {0x45374242, 0x02000000, 0x00000002}, + {0x45374243, 0x02000000, 0x00000002}, + {0x45374259, 0x04000000, 0x00000002}, + {0x45374341, 0x00800000, 0x00000002}, + {0x45374342, 0x01000000, 0x00000001}, + {0x45374441, 0x04000000, 0x00000005}, + {0x45374442, 0x00800000, 0x00000001}, + {0x45374542, 0x04000000, 0x00000002}, + {0x45374641, 0x02000000, 0x00000002}, + {0x45374659, 0x01000000, 0x00000002}, + {0x45374741, 0x02000000, 0x00000002}, + {0x45374742, 0x04000000, 0x00000001}, + {0x45374842, 0x00800000, 0x00000001}, + {0x45374943, 0x04000000, 0x00000002}, + {0x45374A42, 0x00800000, 0x00000001}, + {0x45374A43, 0x04000000, 0x00000001}, + {0x45374C41, 0x02000000, 0x00000001}, + {0x45374C43, 0x01000000, 0x00000002}, + {0x45374D41, 0x02000000, 0x00000002}, + {0x45374D43, 0x02000000, 0x00000008}, + {0x45374D59, 0x04000000, 0x00000002}, + {0x45374E41, 0x02000000, 0x00000002}, + {0x45375043, 0x04000000, 0x00000002}, + {0x45375141, 0x00800000, 0x00000002}, + {0x45375143, 0x04000000, 0x00000001}, + {0x45375242, 0x02000000, 0x00000002}, + {0x45375341, 0x08000000, 0x00000003}, + {0x45375359, 0x02000000, 0x00000001}, + {0x45375459, 0x04000000, 0x00000002}, + {0x45375541, 0x02000000, 0x00000002}, + {0x45375643, 0x00800000, 0x00000001}, + {0x45375742, 0x02000000, 0x00000002}, + {0x45375759, 0x04000000, 0x00000001}, + {0x45375842, 0x01000000, 0x00000001}, + {0x45375941, 0x08000000, 0x00000005}, + {0x45375943, 0x04000000, 0x00000002}, + {0x45375A42, 0x00800000, 0x00000001}, + {0x45383259, 0x02000000, 0x00000008}, + {0x45383342, 0x00800000, 0x00000001}, + {0x45383343, 0x04000000, 0x00000005}, + {0x45383541, 0x02000000, 0x00000008}, + {0x45383542, 0x00800000, 0x00000001}, + {0x45383559, 0x00800000, 0x00000000}, + {0x45384142, 0x00800000, 0x00000001}, + {0x45384159, 0x01000000, 0x00000002}, + {0x45384241, 0x02000000, 0x00000001}, + {0x45384242, 0x04000000, 0x00000002}, + {0x45384243, 0x02000000, 0x00000001}, + {0x45384342, 0x00800000, 0x00000001}, + {0x45384359, 0x01000000, 0x00000002}, + {0x45384443, 0x02000000, 0x00000002}, + {0x45384643, 0x04000000, 0x00000002}, + {0x45384659, 0x02000000, 0x00000003}, + {0x45384741, 0x04000000, 0x00000003}, + {0x45384759, 0x08000000, 0x00000005}, + {0x45384841, 0x02000000, 0x00000001}, + {0x45384842, 0x01000000, 0x00000001}, + {0x45384941, 0x02000000, 0x00000002}, + {0x45384959, 0x04000000, 0x00000001}, + {0x45384C41, 0x04000000, 0x00000001}, + {0x45384C43, 0x04000000, 0x00000002}, + {0x45384C59, 0x01000000, 0x00000001}, + {0x45384D41, 0x01000000, 0x00000001}, + {0x45384D42, 0x04000000, 0x00000001}, + {0x45384D43, 0x02000000, 0x00000002}, + {0x45384E41, 0x00800000, 0x00000001}, + {0x45384E42, 0x01000000, 0x00000001}, + {0x45384F41, 0x04000000, 0x00000003}, + {0x45384F59, 0x08000000, 0x00000003}, + {0x45385043, 0x02000000, 0x00000002}, + {0x45385059, 0x01000000, 0x00000001}, + {0x45385141, 0x00800000, 0x00000002}, + {0x45385142, 0x04000000, 0x00000002}, + {0x45385143, 0x01000000, 0x00000001}, + {0x45385243, 0x04000000, 0x00000002}, + {0x45385259, 0x02000000, 0x00000002}, + {0x45385342, 0x04000000, 0x00000002}, + {0x45385359, 0x04000000, 0x00000001}, + {0x45385442, 0x08000000, 0x00000001}, + {0x45385459, 0x02000000, 0x00000002}, + {0x45385542, 0x04000000, 0x00000001}, + {0x45385641, 0x01000000, 0x00000001}, + {0x45385643, 0x04000000, 0x00000002}, + {0x45385741, 0x04000000, 0x00000001}, + {0x45385743, 0x02000000, 0x00000002}, + {0x45385759, 0x08000000, 0x00000005}, + {0x45385841, 0x00800000, 0x00000001}, + {0x45385859, 0x08000000, 0x00000001}, + {0x45385941, 0x01000000, 0x00000001}, + {0x45385942, 0x00800000, 0x00000001}, + {0x45385943, 0x10000000, 0x00000003}, + {0x45385A42, 0x00800000, 0x00000001}, + {0x45393241, 0x00800000, 0x00000008}, + {0x45393341, 0x01000000, 0x00000008}, + {0x45393343, 0x02000000, 0x00000002}, + {0x45393443, 0x04000000, 0x00000005}, + {0x45393459, 0x04000000, 0x00000008}, + {0x45393541, 0x04000000, 0x00000008}, + {0x45393643, 0x04000000, 0x00000002}, + {0x45394241, 0x01000000, 0x00000001}, + {0x45394242, 0x02000000, 0x00000001}, + {0x45394243, 0x08000000, 0x00000005}, + {0x45394259, 0x02000000, 0x00000003}, + {0x45394341, 0x04000000, 0x00000001}, + {0x45394441, 0x02000000, 0x00000003}, + {0x45394542, 0x04000000, 0x00000002}, + {0x45394543, 0x01000000, 0x00000003}, + {0x45394641, 0x00800000, 0x00000001}, + {0x45394643, 0x02000000, 0x00000003}, + {0x45394659, 0x02000000, 0x00000001}, + {0x45394841, 0x04000000, 0x00000005}, + {0x45394856, 0x04000000, 0x00000002}, + {0x45394943, 0x01000000, 0x00000002}, + {0x45394A59, 0x00800000, 0x00000005}, + {0x45394B42, 0x10000000, 0x00000003}, + {0x45394C41, 0x02000000, 0x00000002}, + {0x45394C42, 0x08000000, 0x00000001}, + {0x45394D41, 0x01000000, 0x00000002}, + {0x45394D43, 0x01000000, 0x00000001}, + {0x45394D59, 0x01000000, 0x00000001}, + {0x45394E41, 0x01000000, 0x00000001}, + {0x45395042, 0x04000000, 0x00000002}, + {0x45395056, 0x04000000, 0x00000001}, + {0x45395059, 0x04000000, 0x00000003}, + {0x45395141, 0x04000000, 0x00000001}, + {0x45395259, 0x04000000, 0x00000002}, + {0x45395341, 0x02000000, 0x00000001}, + {0x45395343, 0x02000000, 0x00000001}, + {0x45395459, 0x04000000, 0x00000003}, + {0x45395643, 0x01000000, 0x00000001}, + {0x45395742, 0x08000000, 0x00000002}, + {0x45395743, 0x08000000, 0x00000001}, + {0x45395941, 0x08000000, 0x00000003}, + {0x45395943, 0x04000000, 0x00000002}, + {0x45395A43, 0x04000000, 0x00000002}, + {0x45413541, 0x04000000, 0x00000001}, + {0x45413543, 0x02000000, 0x00000002}, + {0x45413641, 0x02000000, 0x00000005}, + {0x45413642, 0x04000000, 0x00000001}, + {0x45413741, 0x01000000, 0x00000001}, + {0x45413956, 0x02000000, 0x00000000}, + {0x45414143, 0x04000000, 0x00000002}, + {0x45414156, 0x02000000, 0x00000007}, + {0x45414159, 0x04000000, 0x00000002}, + {0x45414241, 0x02000000, 0x00000001}, + {0x45414242, 0x02000000, 0x00000002}, + {0x45414243, 0x02000000, 0x00000001}, + {0x45414254, 0x01000000, 0x00000001}, + {0x45414256, 0x02000000, 0x00000001}, + {0x45414341, 0x00800000, 0x00000001}, + {0x45414356, 0x04000000, 0x00000001}, + {0x45414441, 0x04000000, 0x00000006}, + {0x45414442, 0x04000000, 0x00000001}, + {0x45414443, 0x04000000, 0x00000002}, + {0x45414541, 0x08000000, 0x00000001}, + {0x45414559, 0x02000000, 0x00000003}, + {0x45414641, 0x04000000, 0x00000003}, + {0x45414642, 0x02000000, 0x00000003}, + {0x45414643, 0x08000000, 0x00000002}, + {0x45414941, 0x04000000, 0x00000001}, + {0x45414959, 0x02000000, 0x00000001}, + {0x45414A42, 0x01000000, 0x00000002}, + {0x45414A43, 0x04000000, 0x00000003}, + {0x45414A59, 0x04000000, 0x00000002}, + {0x45414B41, 0x08000000, 0x00000005}, + {0x45414C42, 0x04000000, 0x00000002}, + {0x45414C56, 0x04000000, 0x00000002}, + {0x45414E42, 0x02000000, 0x00000001}, + {0x45414E43, 0x04000000, 0x00000001}, + {0x45415041, 0x04000000, 0x00000006}, + {0x45415042, 0x02000000, 0x00000002}, + {0x45415043, 0x02000000, 0x00000001}, + {0x45415054, 0x02000000, 0x00000001}, + {0x45415141, 0x02000000, 0x00000001}, + {0x45415143, 0x01000000, 0x00000002}, + {0x45415241, 0x02000000, 0x00000001}, + {0x45415243, 0x00800000, 0x00000001}, + {0x45415259, 0x01000000, 0x00000001}, + {0x45415343, 0x01000000, 0x00000001}, + {0x45415359, 0x01000000, 0x00000002}, + {0x45415441, 0x01000000, 0x00000001}, + {0x45415443, 0x04000000, 0x00000001}, + {0x45415543, 0x04000000, 0x00000001}, + {0x45415641, 0x04000000, 0x00000002}, + {0x45415643, 0x01000000, 0x00000001}, + {0x45415741, 0x04000000, 0x00000002}, + {0x45415743, 0x00800000, 0x00000001}, + {0x45415941, 0x00800000, 0x00000002}, + {0x45415942, 0x02000000, 0x00000001}, + {0x45415A42, 0x08000000, 0x00000001}, + {0x45415A43, 0x02000000, 0x00000002}, + {0x45423243, 0x02000000, 0x00000001}, + {0x45423342, 0x04000000, 0x00000001}, + {0x45423343, 0x00800000, 0x00000001}, + {0x45423442, 0x04000000, 0x00000002}, + {0x45423443, 0x02000000, 0x00000003}, + {0x45423542, 0x04000000, 0x00000002}, + {0x45423543, 0x01000000, 0x00000002}, + {0x45423641, 0x02000000, 0x00000005}, + {0x45423642, 0x04000000, 0x00000001}, + {0x45423741, 0x01000000, 0x00000001}, + {0x45423743, 0x02000000, 0x00000002}, + {0x45424143, 0x01000000, 0x00000001}, + {0x45424159, 0x00800000, 0x00000001}, + {0x45424243, 0x01000000, 0x00000002}, + {0x45424341, 0x04000000, 0x00000003}, + {0x45424354, 0x08000000, 0x00000001}, + {0x45424442, 0x04000000, 0x00000002}, + {0x45424443, 0x04000000, 0x00000001}, + {0x45424541, 0x00800000, 0x00000008}, + {0x45424641, 0x00800000, 0x00000001}, + {0x45424642, 0x01000000, 0x00000002}, + {0x45424654, 0x01000000, 0x00000001}, + {0x45424656, 0x02000000, 0x00000001}, + {0x45424743, 0x02000000, 0x00000001}, + {0x45424841, 0x02000000, 0x00000002}, + {0x45424842, 0x00800000, 0x00000001}, + {0x45424942, 0x01000000, 0x00000003}, + {0x45424959, 0x02000000, 0x00000001}, + {0x45424A41, 0x04000000, 0x00000005}, + {0x45424A42, 0x04000000, 0x00000001}, + {0x45424A43, 0x01000000, 0x00000001}, + {0x45424A59, 0x04000000, 0x00000001}, + {0x45424B41, 0x02000000, 0x00000003}, + {0x45424B43, 0x02000000, 0x00000002}, + {0x45424B59, 0x04000000, 0x00000003}, + {0x45424C42, 0x04000000, 0x00000002}, + {0x45424C43, 0x08000000, 0x00000003}, + {0x45424C59, 0x04000000, 0x00000002}, + {0x45424E43, 0x04000000, 0x00000003}, + {0x45425141, 0x00800000, 0x00000001}, + {0x45425143, 0x01000000, 0x00000002}, + {0x45425159, 0x00800000, 0x00000001}, + {0x45425241, 0x02000000, 0x00000001}, + {0x45425243, 0x02000000, 0x00000005}, + {0x45425259, 0x08000000, 0x00000003}, + {0x45425341, 0x04000000, 0x00000002}, + {0x45425442, 0x04000000, 0x00000002}, + {0x45425443, 0x08000000, 0x00000005}, + {0x45425543, 0x04000000, 0x00000003}, + {0x45425559, 0x04000000, 0x00000002}, + {0x45425641, 0x01000000, 0x00000001}, + {0x45425741, 0x00800000, 0x00000001}, + {0x45425742, 0x04000000, 0x00000002}, + {0x45425759, 0x02000000, 0x00000002}, + {0x45425942, 0x01000000, 0x00000001}, + {0x45425943, 0x04000000, 0x00000001}, + {0x45425959, 0x04000000, 0x00000005}, + {0x45433342, 0x04000000, 0x00000002}, + {0x45433441, 0x02000000, 0x00000003}, + {0x45433459, 0x04000000, 0x00000008}, + {0x45433542, 0x00800000, 0x00000001}, + {0x45433641, 0x02000000, 0x00000005}, + {0x45433642, 0x08000000, 0x00000002}, + {0x45433643, 0x10000000, 0x00000005}, + {0x45433741, 0x02000000, 0x00000001}, + {0x45433841, 0x02000000, 0x00000002}, + {0x45433859, 0x00800000, 0x00000008}, + {0x45434156, 0x04000000, 0x00000002}, + {0x45434241, 0x04000000, 0x00000005}, + {0x45434259, 0x02000000, 0x00000002}, + {0x45434341, 0x02000000, 0x00000001}, + {0x45434343, 0x01000000, 0x00000001}, + {0x45434354, 0x00800000, 0x00000001}, + {0x45434441, 0x01000000, 0x00000001}, + {0x45434442, 0x02000000, 0x00000001}, + {0x45434443, 0x04000000, 0x00000003}, + {0x45434459, 0x08000000, 0x00000003}, + {0x45434541, 0x00800000, 0x00000001}, + {0x45434559, 0x02000000, 0x00000001}, + {0x45434642, 0x02000000, 0x00000001}, + {0x45434659, 0x08000000, 0x00000002}, + {0x45434741, 0x04000000, 0x00000003}, + {0x45434759, 0x02000000, 0x00000002}, + {0x45434843, 0x01000000, 0x00000001}, + {0x45434941, 0x01000000, 0x00000001}, + {0x45434943, 0x04000000, 0x00000003}, + {0x45434956, 0x04000000, 0x00000002}, + {0x45434959, 0x04000000, 0x00000002}, + {0x45434A42, 0x03E8823C, 0x00000002}, + {0x45434A43, 0x04000000, 0x00000002}, + {0x45434A56, 0x04000000, 0x00000001}, + {0x45434A59, 0x04000000, 0x00000002}, + {0x45434B42, 0x10000000, 0x00000006}, + {0x45434B43, 0x01000000, 0x00000001}, + {0x45434C42, 0x04000000, 0x00000002}, + {0x45434C56, 0x04000000, 0x00000002}, + {0x45434D41, 0x02000000, 0x00000005}, + {0x45434D56, 0x02000000, 0x00000001}, + {0x45434F43, 0x01000000, 0x00000001}, + {0x45435041, 0x01000000, 0x00000001}, + {0x45435043, 0x00800000, 0x00000002}, + {0x45435159, 0x01000000, 0x00000001}, + {0x45435241, 0x02000000, 0x00000002}, + {0x45435243, 0x02000000, 0x00000001}, + {0x45435341, 0x04000000, 0x00000002}, + {0x45435343, 0x04000000, 0x00000001}, + {0x45435359, 0x01000000, 0x00000001}, + {0x45435441, 0x04000000, 0x00000005}, + {0x45435442, 0x01000000, 0x00000001}, + {0x45435641, 0x04000000, 0x00000005}, + {0x45435741, 0x04000000, 0x00000002}, + {0x45435759, 0x02000000, 0x00000002}, + {0x45435842, 0x01000000, 0x00000001}, + {0x45435943, 0x02000000, 0x00000002}, + {0x45435959, 0x02000000, 0x00000001}, + {0x45443241, 0x02000000, 0x00000002}, + {0x45443343, 0x01000000, 0x00000001}, + {0x45443442, 0x00800000, 0x00000001}, + {0x45443643, 0x02000000, 0x00000001}, + {0x45443659, 0x00800000, 0x00000008}, + {0x45443741, 0x02000000, 0x00000001}, + {0x45443759, 0x08000000, 0x00000008}, + {0x45444154, 0x08000000, 0x00000005}, + {0x45444241, 0x01000000, 0x00000001}, + {0x45444243, 0x04000000, 0x00000002}, + {0x45444343, 0x00800000, 0x00000003}, + {0x45444354, 0x02000000, 0x00000001}, + {0x45444356, 0x04000000, 0x00000002}, + {0x45444441, 0x01000000, 0x00000001}, + {0x45444459, 0x01000000, 0x00000001}, + {0x45444559, 0x00800000, 0x00000001}, + {0x45444641, 0x04000000, 0x00000002}, + {0x45444642, 0x00800000, 0x00000001}, + {0x45444643, 0x08000000, 0x00000002}, + {0x45444743, 0x00800000, 0x00000001}, + {0x45444759, 0x00800000, 0x00000003}, + {0x45444841, 0x04000000, 0x00000002}, + {0x45444842, 0x04000000, 0x00000001}, + {0x45444859, 0x04000000, 0x00000001}, + {0x45444943, 0x02000000, 0x00000003}, + {0x45444956, 0x02000000, 0x00000002}, + {0x45444959, 0x02000000, 0x00000005}, + {0x45444A42, 0x01000000, 0x00000002}, + {0x45444A59, 0x02000000, 0x00000002}, + {0x45444B41, 0x01000000, 0x00000002}, + {0x45444C41, 0x04000000, 0x00000003}, + {0x45444C42, 0x04000000, 0x00000002}, + {0x45444C59, 0x04000000, 0x00000005}, + {0x45444D41, 0x01000000, 0x00000005}, + {0x45444D42, 0x04000000, 0x00000001}, + {0x45444D43, 0x02000000, 0x00000005}, + {0x45444D44, 0x20000000, 0x00000000}, + {0x45444E41, 0x01000000, 0x00000005}, + {0x45444E42, 0x02000000, 0x00000001}, + {0x45444E43, 0x04000000, 0x00000002}, + {0x45444E59, 0x02000000, 0x00000001}, + {0x45445041, 0x01000000, 0x00000002}, + {0x45445042, 0x04000000, 0xFFFFFFFF}, + {0x45445043, 0x02000000, 0x00000001}, + {0x45445054, 0x08000000, 0x00000001}, + {0x45445241, 0x02000000, 0x00000001}, + {0x45445243, 0x01000000, 0x00000001}, + {0x45445341, 0x01000000, 0x00000001}, + {0x45445342, 0x04000000, 0x00000002}, + {0x45445343, 0x01000000, 0x00000001}, + {0x45445441, 0x01000000, 0x00000002}, + {0x45445442, 0x01000000, 0x00000001}, + {0x45445443, 0x04000000, 0x00000002}, + {0x45445542, 0x01000000, 0x00000001}, + {0x45445641, 0x01000000, 0x00000002}, + {0x45445642, 0x00800000, 0x00000001}, + {0x45445741, 0x02000000, 0x00000005}, + {0x45445742, 0x04000000, 0x00000001}, + {0x45445759, 0x01000000, 0x00000002}, + {0x45445842, 0x01000000, 0x00000001}, + {0x45445A41, 0x00800000, 0x00000008}, + {0x45445A42, 0x08000000, 0x00000001}, + {0x45453242, 0x00800000, 0x00000001}, + {0x45453341, 0x00800000, 0x00000002}, + {0x45453442, 0x01000000, 0x00000001}, + {0x45453559, 0x04000000, 0x00000000}, + {0x45453642, 0x02000000, 0x00000001}, + {0x45453741, 0x01000000, 0x00000001}, + {0x45453742, 0x02000000, 0x00000001}, + {0x45454241, 0x00800000, 0x00000001}, + {0x45454254, 0x02000000, 0x00000001}, + {0x45454343, 0x01000000, 0x00000005}, + {0x45454359, 0x02000000, 0x00000002}, + {0x45454442, 0x04000000, 0x00000002}, + {0x45454456, 0x10000000, 0x00000006}, + {0x45454641, 0x04000000, 0x00000003}, + {0x45454659, 0x04000000, 0x00000005}, + {0x45454741, 0x01000000, 0x00000001}, + {0x45454742, 0x04000000, 0x00000001}, + {0x45454743, 0x02000000, 0x00000002}, + {0x45454841, 0x08000000, 0x00000005}, + {0x45454943, 0x04000000, 0x00000002}, + {0x45454A59, 0x01000000, 0x00000001}, + {0x45454B42, 0x04000000, 0x00000002}, + {0x45454C59, 0x02000000, 0x00000001}, + {0x45454D44, 0x20000000, 0x00000000}, + {0x45454D56, 0x02000000, 0x00000001}, + {0x45454F59, 0x01000000, 0x00000005}, + {0x45455056, 0x04000000, 0x00000001}, + {0x45455141, 0x00800000, 0x00000002}, + {0x45455143, 0x04000000, 0x00000002}, + {0x45455241, 0x04000000, 0x00000001}, + {0x45455243, 0x04000000, 0x00000001}, + {0x45455341, 0x04000000, 0x00000002}, + {0x45455456, 0x04000000, 0x00000002}, + {0x45455459, 0x02000000, 0x00000003}, + {0x45455641, 0x01000000, 0x00000001}, + {0x45455642, 0x00800000, 0x00000002}, + {0x45455741, 0x04000000, 0x00000005}, + {0x45455742, 0x04000000, 0x00000001}, + {0x45455743, 0x01000000, 0x00000002}, + {0x45455842, 0x04000000, 0x00000001}, + {0x45455943, 0x08000000, 0x00000002}, + {0x45455A41, 0x04000000, 0x00000006}, + {0x45455A42, 0x00800000, 0x00000001}, + {0x45463242, 0x00800000, 0x00000001}, + {0x45463541, 0x04000000, 0x00000002}, + {0x45463641, 0x08000000, 0x00000003}, + {0x45463642, 0x08000000, 0x00000001}, + {0x45463659, 0x02000000, 0x00000000}, + {0x45463742, 0x01000000, 0xFFFFFFFF}, + {0x45463743, 0x01000000, 0x00000003}, + {0x45463859, 0x08000000, 0x00000008}, + {0x45464159, 0x02000000, 0x00000002}, + {0x45464243, 0x08000000, 0x00000003}, + {0x45464341, 0x04000000, 0x00000002}, + {0x45464343, 0x00800000, 0x00000001}, + {0x45464441, 0x01000000, 0x00000001}, + {0x45464443, 0x04000000, 0x00000002}, + {0x45464541, 0x00800000, 0x00000001}, + {0x45464542, 0x00800000, 0x00000001}, + {0x45464543, 0x01000000, 0x00000001}, + {0x45464641, 0x08000000, 0x00000003}, + {0x45464741, 0x04000000, 0x00000002}, + {0x45464743, 0x00800000, 0x00000001}, + {0x45464759, 0x01000000, 0x00000001}, + {0x45464841, 0x02000000, 0x00000001}, + {0x45464843, 0x02000000, 0x00000002}, + {0x45464859, 0x00800000, 0x00000002}, + {0x45464956, 0x02000000, 0x00000002}, + {0x45464959, 0x04000000, 0x00000002}, + {0x45464B43, 0x02000000, 0x00000001}, + {0x45464B59, 0x02000000, 0x00000001}, + {0x45464C42, 0x10000000, 0x00000003}, + {0x45464C43, 0x02000000, 0x00000001}, + {0x45464D41, 0x01000000, 0x00000001}, + {0x45464D44, 0x02000000, 0xFFFFFFFF}, + {0x45464D59, 0x04000000, 0x00000003}, + {0x45464E41, 0x02000000, 0x00000005}, + {0x45465042, 0x04000000, 0x00000002}, + {0x45465043, 0x00800000, 0x00000002}, + {0x45465054, 0x02000000, 0x00000001}, + {0x45465056, 0x04000000, 0x00000002}, + {0x45465241, 0x08000000, 0x00000003}, + {0x45465242, 0x08000000, 0x00000003}, + {0x45465243, 0x02000000, 0x00000002}, + {0x45465259, 0x02000000, 0x00000002}, + {0x45465341, 0x02000000, 0x00000005}, + {0x45465359, 0x04000000, 0x00000001}, + {0x45465443, 0x04000000, 0x00000001}, + {0x45465541, 0x04000000, 0x00000002}, + {0x45465542, 0x01000000, 0x00000002}, + {0x45465742, 0x04000000, 0x00000001}, + {0x45465743, 0x02000000, 0x00000002}, + {0x45465841, 0x08000000, 0x00000003}, + {0x45465842, 0x04000000, 0x00000001}, + {0x45473241, 0x02000000, 0x00000003}, + {0x45473256, 0x02000000, 0x00000006}, + {0x45473459, 0x01000000, 0x00000008}, + {0x45473541, 0x01000000, 0x00000001}, + {0x45473642, 0x00800000, 0x00000001}, + {0x45473741, 0x02000000, 0x00000001}, + {0x45473743, 0x01000000, 0x00000001}, + {0x45473759, 0x08000000, 0x00000000}, + {0x45473859, 0x02000000, 0x00000000}, + {0x45474142, 0x01000000, 0x00000001}, + {0x45474159, 0x01000000, 0x00000001}, + {0x45474243, 0x02000000, 0x00000005}, + {0x45474254, 0x00800000, 0x00000001}, + {0x45474341, 0x00800000, 0x00000002}, + {0x45474342, 0x04000000, 0x00000002}, + {0x45474354, 0x04000000, 0x00000001}, + {0x45474356, 0x04000000, 0x00000002}, + {0x45474359, 0x00800000, 0x00000001}, + {0x45474441, 0x02000000, 0x00000005}, + {0x45474443, 0x04000000, 0x00000006}, + {0x45474541, 0x04000000, 0x00000001}, + {0x45474542, 0x00800000, 0x00000001}, + {0x45474641, 0x04000000, 0x00000001}, + {0x45474642, 0x04000000, 0x00000003}, + {0x45474742, 0x02000000, 0x00000005}, + {0x45474754, 0x00800000, 0x00000001}, + {0x45474842, 0x02000000, 0x00000001}, + {0x45474942, 0x02000000, 0x00000001}, + {0x45474A59, 0x02000000, 0x00000002}, + {0x45474B41, 0x02000000, 0x00000002}, + {0x45474B56, 0x02000000, 0x00000005}, + {0x45474B59, 0x10000000, 0x00000003}, + {0x45474C43, 0x04000000, 0x00000001}, + {0x45474C59, 0x04000000, 0x00000001}, + {0x45474D41, 0x01000000, 0x00000001}, + {0x45474D42, 0x02000000, 0x00000001}, + {0x45474D43, 0x04000000, 0x00000001}, + {0x45474D56, 0x02000000, 0x00000002}, + {0x45474E43, 0x02000000, 0x00000002}, + {0x45474E59, 0x08000000, 0x00000003}, + {0x45474F59, 0x08000000, 0x00000003}, + {0x45475041, 0x01000000, 0x00000001}, + {0x45475049, 0x08000000, 0x00000006}, + {0x45475059, 0x04000000, 0x00000002}, + {0x45475142, 0x04000000, 0x00000001}, + {0x45475241, 0x02000000, 0x00000005}, + {0x45475256, 0x02000000, 0x00000002}, + {0x45475356, 0x02000000, 0x00000001}, + {0x45475541, 0x02000000, 0x00000002}, + {0x45475542, 0x00800000, 0x00000001}, + {0x45475642, 0x01000000, 0x00000002}, + {0x45475842, 0x04000000, 0x00000002}, + {0x45475843, 0x00800000, 0x00000001}, + {0x45475941, 0x04000000, 0x00000002}, + {0x45475A42, 0x02000000, 0x00000001}, + {0x45483241, 0x01000000, 0x00000001}, + {0x45483341, 0x02000000, 0x00000001}, + {0x45483343, 0x00800000, 0x00000001}, + {0x45483442, 0x02000000, 0x00000001}, + {0x45483541, 0x01000000, 0x00000001}, + {0x45483542, 0x01000000, 0x00000001}, + {0x45483559, 0x02000000, 0x00000000}, + {0x45483741, 0x02000000, 0x00000001}, + {0x45483742, 0x04000000, 0x00000002}, + {0x45483842, 0x04000000, 0x00000002}, + {0x45483959, 0x00800000, 0x00000008}, + {0x45484142, 0x04000000, 0x00000001}, + {0x45484159, 0x04000000, 0x00000002}, + {0x45484241, 0x08000000, 0x00000002}, + {0x45484254, 0x01000000, 0x00000001}, + {0x45484342, 0x00800000, 0x00000001}, + {0x45484459, 0x02000000, 0x00000005}, + {0x45484541, 0x04000000, 0x00000002}, + {0x45484542, 0x01000000, 0x00000002}, + {0x45484659, 0x04000000, 0x00000002}, + {0x45484742, 0x10000000, 0x00000001}, + {0x45484743, 0x02000000, 0x00000002}, + {0x45484759, 0x08000000, 0x00000001}, + {0x45484841, 0x04000000, 0x00000001}, + {0x45484942, 0x04000000, 0x00000002}, + {0x45484943, 0x04000000, 0x00000002}, + {0x45484959, 0x02000000, 0x00000002}, + {0x45484B43, 0x02000000, 0x00000002}, + {0x45484B56, 0x02000000, 0x00000002}, + {0x45484B59, 0x08000000, 0x00000005}, + {0x45484C41, 0x02000000, 0x00000001}, + {0x45484C42, 0x08000000, 0x00000001}, + {0x45484C43, 0x01000000, 0x00000002}, + {0x45484C59, 0x04000000, 0x00000002}, + {0x45484D41, 0x04000000, 0x00000005}, + {0x45484D54, 0x00800000, 0x00000001}, + {0x45485041, 0x02000000, 0x00000005}, + {0x45485043, 0x04000000, 0x00000001}, + {0x45485059, 0x00800000, 0x00000002}, + {0x45485341, 0x02000000, 0x00000002}, + {0x45485342, 0x02000000, 0x00000001}, + {0x45485359, 0x02000000, 0x00000001}, + {0x45485441, 0x02000000, 0x00000001}, + {0x45485442, 0x01000000, 0x00000002}, + {0x45485559, 0x01000000, 0x00000002}, + {0x45485641, 0x04000000, 0x00000002}, + {0x45485642, 0x01000000, 0x00000001}, + {0x45485741, 0x01000000, 0x00000001}, + {0x45485843, 0x02000000, 0x00000001}, + {0x45485942, 0x02000000, 0x00000002}, + {0x45485943, 0x04000000, 0x00000002}, + {0x45485A42, 0x00800000, 0x00000001}, + {0x45485A59, 0x04000000, 0x00000001}, + {0x45493241, 0x01000000, 0x00000001}, + {0x45493242, 0x04000000, 0x00000001}, + {0x45493341, 0x08000000, 0x00000002}, + {0x45493441, 0x02000000, 0x00000001}, + {0x45493459, 0x04000000, 0x00000008}, + {0x45493541, 0x01000000, 0x00000001}, + {0x45493642, 0x04000000, 0x00000002}, + {0x45493741, 0x02000000, 0x00000001}, + {0x45493842, 0x04000000, 0x00000001}, + {0x45493859, 0x01000000, 0x00000000}, + {0x45494159, 0x04000000, 0x00000001}, + {0x45494341, 0x02000000, 0x00000002}, + {0x45494342, 0x02000000, 0x00000002}, + {0x45494359, 0x01000000, 0x00000001}, + {0x45494442, 0x04000000, 0x00000001}, + {0x45494459, 0x04000000, 0x00000002}, + {0x45494643, 0x08000000, 0x00000003}, + {0x45494659, 0x04000000, 0x00000001}, + {0x45494742, 0x04000000, 0x00000001}, + {0x45494942, 0x00800000, 0x00000001}, + {0x45494959, 0x00800000, 0x00000001}, + {0x45494B42, 0x08000000, 0x00000007}, + {0x45494C43, 0x04000000, 0x00000001}, + {0x45494C59, 0x04000000, 0x00000002}, + {0x45494D43, 0x00800000, 0x00000001}, + {0x45494E41, 0x08000000, 0x00000005}, + {0x45494E59, 0x08000000, 0x00000002}, + {0x45495056, 0x02000000, 0x00000002}, + {0x45495059, 0x02000000, 0x00000003}, + {0x45495141, 0x02000000, 0x00000005}, + {0x45495241, 0x01000000, 0x00000001}, + {0x45495243, 0x02000000, 0x00000002}, + {0x45495256, 0x02000000, 0x00000001}, + {0x45495259, 0x04000000, 0x00000002}, + {0x45495341, 0x02000000, 0x00000002}, + {0x45495342, 0x04000000, 0x00000001}, + {0x45495343, 0x01000000, 0x00000002}, + {0x45495441, 0x01000000, 0x00000008}, + {0x45495442, 0x01000000, 0x00000001}, + {0x45495456, 0x02000000, 0x00000001}, + {0x45495541, 0x01000000, 0x00000001}, + {0x45495542, 0x01000000, 0x00000001}, + {0x45495543, 0x02000000, 0x00000002}, + {0x45495559, 0x04000000, 0x00000002}, + {0x45495643, 0x04000000, 0x00000002}, + {0x45495659, 0x08000000, 0x00000003}, + {0x45495741, 0x08000000, 0x00000005}, + {0x45495742, 0x01000000, 0x00000002}, + {0x45495743, 0x01000000, 0x00000001}, + {0x45495941, 0x01000000, 0x00000001}, + {0x45495943, 0x02000000, 0x00000002}, + {0x45495A42, 0x00800000, 0x00000001}, + {0x454A3259, 0x02000000, 0x00000008}, + {0x454A3342, 0x08000000, 0x00000002}, + {0x454A3343, 0x10000000, 0x00000003}, + {0x454A3442, 0x00800000, 0x00000001}, + {0x454A3542, 0x00800000, 0x00000001}, + {0x454A3559, 0x08000000, 0x00000000}, + {0x454A3642, 0x00800000, 0x00000001}, + {0x454A3741, 0x02000000, 0x00000001}, + {0x454A4142, 0x01000000, 0x00000001}, + {0x454A4143, 0x01000000, 0x00000001}, + {0x454A4159, 0x01000000, 0x00000002}, + {0x454A4241, 0x04000000, 0x00000005}, + {0x454A4341, 0x04000000, 0x00000001}, + {0x454A4454, 0x00800000, 0x00000001}, + {0x454A4459, 0x01000000, 0x00000001}, + {0x454A4543, 0x01000000, 0x00000001}, + {0x454A4642, 0x01000000, 0x00000002}, + {0x454A4643, 0x02000000, 0x00000002}, + {0x454A4759, 0x02000000, 0x00000001}, + {0x454A4841, 0x01000000, 0x00000002}, + {0x454A4943, 0x00800000, 0x00000001}, + {0x454A4956, 0x04000000, 0x00000003}, + {0x454A4A42, 0x01000000, 0x00000001}, + {0x454A4A43, 0x00800000, 0x00000001}, + {0x454A4C41, 0x01000000, 0x00000001}, + {0x454A4C42, 0x04000000, 0x00000001}, + {0x454A4C43, 0x08000000, 0x00000002}, + {0x454A4C54, 0x08000000, 0x00000002}, + {0x454A4C59, 0x04000000, 0x00000001}, + {0x454A4D42, 0x00800000, 0x00000001}, + {0x454A4D59, 0x04000000, 0x00000001}, + {0x454A4E41, 0x02000000, 0x00000001}, + {0x454A4E43, 0x02000000, 0x00000001}, + {0x454A4E59, 0x02000000, 0x00000001}, + {0x454A4F41, 0x02000000, 0x00000002}, + {0x454A5043, 0x04000000, 0x00000002}, + {0x454A5141, 0x08000000, 0x00000001}, + {0x454A5143, 0x00800000, 0x00000001}, + {0x454A5242, 0x08000000, 0x00000003}, + {0x454A5243, 0x02000000, 0x00000001}, + {0x454A5341, 0x04000000, 0x00000005}, + {0x454A5342, 0x00800000, 0x00000001}, + {0x454A5441, 0x01000000, 0x00000002}, + {0x454A5442, 0x01000000, 0x00000002}, + {0x454A5459, 0x04000000, 0x00000002}, + {0x454A5541, 0x04000000, 0x00000001}, + {0x454A5542, 0x08000000, 0x00000001}, + {0x454A5641, 0x04000000, 0x00000002}, + {0x454A5642, 0x01000000, 0x00000001}, + {0x454A5659, 0x01000000, 0x00000001}, + {0x454A5743, 0x00800000, 0x00000001}, + {0x454A5759, 0x00800000, 0x00000002}, + {0x454A5841, 0x04000000, 0x00000003}, + {0x454A5959, 0x01000000, 0x00000002}, + {0x454A5A42, 0x02000000, 0x00000001}, + {0x454B3243, 0x00800000, 0x00000003}, + {0x454B3342, 0x01000000, 0x00000001}, + {0x454B3641, 0x08000000, 0x00000003}, + {0x454B3741, 0x02000000, 0x00000001}, + {0x454B3842, 0x02000000, 0x00000002}, + {0x454B4143, 0x01000000, 0x00000002}, + {0x454B4241, 0x00800000, 0x00000001}, + {0x454B4242, 0x02000000, 0x00000002}, + {0x454B4243, 0x04000000, 0x00000002}, + {0x454B4343, 0x04000000, 0x00000001}, + {0x454B4356, 0x08000000, 0x00000002}, + {0x454B4541, 0x04000000, 0x00000002}, + {0x454B4559, 0x08000000, 0x00000005}, + {0x454B4841, 0x04000000, 0x00000003}, + {0x454B4843, 0x01000000, 0x00000001}, + {0x454B4959, 0x02000000, 0x00000005}, + {0x454B4A43, 0x08000000, 0x00000003}, + {0x454B4A59, 0x08000000, 0x00000002}, + {0x454B4B41, 0x01000000, 0x00000003}, + {0x454B4C41, 0x08000000, 0x00000003}, + {0x454B4C54, 0x08000000, 0x00000002}, + {0x454B4C59, 0x02000000, 0x00000002}, + {0x454B4D42, 0x04000000, 0x00000001}, + {0x454B4E41, 0x00800000, 0x00000001}, + {0x454B4E59, 0x04000000, 0x00000002}, + {0x454B5049, 0x08000000, 0x00000006}, + {0x454B5142, 0x01000000, 0x00000001}, + {0x454B5159, 0x02000000, 0x00000001}, + {0x454B5243, 0x04000000, 0x00000001}, + {0x454B5341, 0x04000000, 0x00000002}, + {0x454B5342, 0x08000000, 0x00000003}, + {0x454B5356, 0x04000000, 0x00000001}, + {0x454B5441, 0x04000000, 0x00000002}, + {0x454B5559, 0x04000000, 0x00000001}, + {0x454B5641, 0x01000000, 0x00000001}, + {0x454B5741, 0x04000000, 0x00000003}, + {0x454B5759, 0x04000000, 0x00000002}, + {0x454B5943, 0x02000000, 0x00000002}, + {0x454B5959, 0x04000000, 0x00000002}, + {0x454B5A41, 0x00800000, 0x00000002}, + {0x454C3241, 0x01000000, 0x00000003}, + {0x454C3259, 0x04000000, 0x00000005}, + {0x454C3541, 0x08000000, 0x00000002}, + {0x454C3642, 0x08000000, 0x00000002}, + {0x454C3741, 0x02000000, 0x00000001}, + {0x454C3742, 0x00800000, 0x00000001}, + {0x454C3859, 0x08000000, 0x00000000}, + {0x454C4143, 0x04000000, 0x00000001}, + {0x454C4156, 0x04000000, 0x00000002}, + {0x454C4241, 0x08000000, 0x00000002}, + {0x454C4242, 0x02000000, 0x00000001}, + {0x454C4243, 0x00800000, 0x00000002}, + {0x454C4256, 0x02000000, 0x00000002}, + {0x454C4259, 0x00800000, 0x00000001}, + {0x454C4341, 0x04000000, 0x00000003}, + {0x454C4342, 0x01000000, 0x00000002}, + {0x454C4354, 0x02000000, 0x00000001}, + {0x454C4441, 0x04000000, 0x00000003}, + {0x454C4442, 0x01000000, 0x00000001}, + {0x454C4443, 0x02000000, 0x00000005}, + {0x454C4459, 0x01000000, 0x00000008}, + {0x454C4556, 0x02000000, 0x00000003}, + {0x454C4641, 0x00800000, 0x00000001}, + {0x454C4642, 0x04000000, 0x00000002}, + {0x454C4741, 0x02000000, 0x00000001}, + {0x454C4742, 0x01000000, 0x00000001}, + {0x454C4759, 0x04000000, 0x00000002}, + {0x454C4859, 0x08000000, 0x00000003}, + {0x454C4A41, 0x04000000, 0x00000001}, + {0x454C4A42, 0x02000000, 0x00000002}, + {0x454C4A59, 0x01000000, 0x00000002}, + {0x454C4B54, 0x02000000, 0x00000002}, + {0x454C4C42, 0x01000000, 0x00000003}, + {0x454C4C54, 0x04000000, 0x00000001}, + {0x454C4D41, 0x02000000, 0x00000002}, + {0x454C4D42, 0x00800000, 0x00000001}, + {0x454C4D43, 0x04000000, 0x00000002}, + {0x454C4D54, 0x04000000, 0x00000002}, + {0x454C4E41, 0x04000000, 0x00000001}, + {0x454C4E42, 0x01000000, 0x00000001}, + {0x454C4E59, 0x04000000, 0x00000001}, + {0x454C4F43, 0x08000000, 0x00000003}, + {0x454C5041, 0x00800000, 0x00000002}, + {0x454C5043, 0x01000000, 0x00000001}, + {0x454C5059, 0x00800000, 0x00000001}, + {0x454C5141, 0x00800000, 0x00000001}, + {0x454C5142, 0x00800000, 0x00000003}, + {0x454C5159, 0x08000000, 0x00000002}, + {0x454C5242, 0x01000000, 0x00000001}, + {0x454C5243, 0x02000000, 0x00000001}, + {0x454C5259, 0x02000000, 0x00000001}, + {0x454C5341, 0x01000000, 0x00000001}, + {0x454C5342, 0x02000000, 0x00000003}, + {0x454C5343, 0x00800000, 0x00000002}, + {0x454C5359, 0x10000000, 0x00000005}, + {0x454C5441, 0x01000000, 0x00000001}, + {0x454C5459, 0x00800000, 0x00000002}, + {0x454C5541, 0x00800000, 0x00000002}, + {0x454C5741, 0x08000000, 0x00000003}, + {0x454C5759, 0x02000000, 0x00000001}, + {0x454C5841, 0x04000000, 0x00000001}, + {0x454C5942, 0x02000000, 0x00000001}, + {0x454C5A41, 0x08000000, 0x00000007}, + {0x454D3241, 0x00800000, 0x00000001}, + {0x454D3243, 0x02000000, 0x00000002}, + {0x454D3259, 0x02000000, 0x00000008}, + {0x454D3341, 0x08000000, 0x00000002}, + {0x454D3342, 0x04000000, 0x00000002}, + {0x454D3442, 0x02000000, 0x00000001}, + {0x454D3443, 0x04000000, 0x00000001}, + {0x454D3542, 0x01000000, 0x00000001}, + {0x454D3543, 0x01000000, 0x00000001}, + {0x454D3643, 0x04000000, 0x00000002}, + {0x454D3741, 0x02000000, 0x00000001}, + {0x454D3742, 0x01000000, 0x00000001}, + {0x454D3743, 0x01000000, 0x00000003}, + {0x454D4143, 0x01000000, 0x00000002}, + {0x454D4154, 0x02000000, 0x00000001}, + {0x454D4159, 0x00800000, 0x00000001}, + {0x454D4241, 0x00800000, 0x00000001}, + {0x454D4242, 0x00800000, 0x00000001}, + {0x454D4243, 0x02000000, 0x00000002}, + {0x454D4341, 0x01000000, 0x00000001}, + {0x454D4342, 0x04000000, 0x00000001}, + {0x454D4343, 0x04000000, 0x00000002}, + {0x454D4354, 0x04000000, 0x00000002}, + {0x454D4356, 0x04000000, 0x00000002}, + {0x454D4359, 0x02000000, 0x00000001}, + {0x454D4441, 0x02000000, 0x00000005}, + {0x454D4459, 0x02000000, 0x00000002}, + {0x454D4643, 0x04000000, 0x00000003}, + {0x454D4659, 0x04000000, 0x00000003}, + {0x454D4742, 0x04000000, 0x00000003}, + {0x454D4843, 0x04000000, 0x00000002}, + {0x454D4943, 0x01000000, 0x00000002}, + {0x454D4959, 0x04000000, 0x00000001}, + {0x454D4A42, 0x04000000, 0x00000002}, + {0x454D4A59, 0x00800000, 0x00000002}, + {0x454D4C54, 0x08000000, 0x00000001}, + {0x454D4D42, 0x00800000, 0x00000001}, + {0x454D4D59, 0x02000000, 0x00000001}, + {0x454D4E41, 0x02000000, 0x00000005}, + {0x454D4E42, 0x04000000, 0x00000001}, + {0x454D4E43, 0x04000000, 0x00000001}, + {0x454D4E59, 0x01000000, 0x00000002}, + {0x454D5042, 0x02000000, 0x00000001}, + {0x454D5043, 0x04000000, 0x00000002}, + {0x454D5141, 0x00800000, 0x00000001}, + {0x454D5241, 0x04000000, 0x00000002}, + {0x454D5242, 0x01000000, 0x00000002}, + {0x454D5259, 0x02000000, 0x00000003}, + {0x454D5341, 0x01000000, 0x00000002}, + {0x454D5342, 0x01000000, 0x00000002}, + {0x454D5459, 0x04000000, 0x00000002}, + {0x454D5642, 0x02000000, 0x00000001}, + {0x454D5643, 0x02000000, 0x00000002}, + {0x454D5741, 0x00800000, 0x00000001}, + {0x454D5842, 0x04000000, 0x00000002}, + {0x454D5843, 0x04000000, 0x00000003}, + {0x454D5A43, 0x02000000, 0x00000001}, + {0x454E3242, 0x02000000, 0x00000001}, + {0x454E3243, 0x01000000, 0x00000002}, + {0x454E3342, 0x02000000, 0x00000001}, + {0x454E3542, 0x01000000, 0x00000001}, + {0x454E3543, 0x01000000, 0x00000001}, + {0x454E3641, 0x08000000, 0x00000003}, + {0x454E3741, 0x02000000, 0x00000001}, + {0x454E3742, 0x08000000, 0x00000003}, + {0x454E3841, 0x02000000, 0x00000005}, + {0x454E4143, 0x02000000, 0x00000005}, + {0x454E4259, 0x04000000, 0x00000007}, + {0x454E4341, 0x01000000, 0x00000002}, + {0x454E4354, 0x01000000, 0x00000001}, + {0x454E4441, 0x04000000, 0x00000003}, + {0x454E4443, 0x08000000, 0x00000001}, + {0x454E4541, 0x04000000, 0x00000002}, + {0x454E4543, 0x02000000, 0x00000003}, + {0x454E4641, 0x02000000, 0x00000002}, + {0x454E4654, 0x04000000, 0x00000002}, + {0x454E4656, 0x02000000, 0x00000002}, + {0x454E4741, 0x02000000, 0x00000001}, + {0x454E4743, 0x04000000, 0x00000002}, + {0x454E4759, 0x04000000, 0x00000002}, + {0x454E4841, 0x04000000, 0x00000001}, + {0x454E4843, 0x02000000, 0x00000002}, + {0x454E4859, 0x04000000, 0x00000003}, + {0x454E4942, 0x00800000, 0x00000001}, + {0x454E4A41, 0x02000000, 0x00000002}, + {0x454E4A43, 0x01000000, 0x00000001}, + {0x454E4B43, 0x08000000, 0x00000002}, + {0x454E4C41, 0x02000000, 0x00000002}, + {0x454E4C59, 0x08000000, 0x00000002}, + {0x454E4D54, 0x01000000, 0x00000002}, + {0x454E4E42, 0x04000000, 0x00000002}, + {0x454E4E59, 0x08000000, 0x00000003}, + {0x454E5041, 0x02000000, 0x00000001}, + {0x454E5042, 0x01000000, 0x00000002}, + {0x454E5059, 0x00800000, 0x00000001}, + {0x454E5142, 0x04000000, 0x00000001}, + {0x454E5159, 0x04000000, 0x00000002}, + {0x454E5241, 0x01000000, 0x00000001}, + {0x454E5341, 0x00800000, 0x00000002}, + {0x454E5342, 0x02000000, 0x00000001}, + {0x454E5356, 0x04000000, 0x00000002}, + {0x454E5442, 0x04000000, 0x00000002}, + {0x454E5642, 0x04000000, 0x00000001}, + {0x454E5643, 0x04000000, 0x00000001}, + {0x454E5842, 0x01000000, 0x00000001}, + {0x454E5A41, 0x01000000, 0x00000002}, + {0x454E5A43, 0x04000000, 0x00000002}, + {0x454F3241, 0x04000000, 0x00000003}, + {0x454F3341, 0x00800000, 0x00000001}, + {0x454F3441, 0x02000000, 0x00000005}, + {0x454F3541, 0x01000000, 0x00000001}, + {0x454F3542, 0x00800000, 0x00000001}, + {0x454F3559, 0x08000000, 0x00000000}, + {0x454F3642, 0x02000000, 0x00000001}, + {0x454F3659, 0x00800000, 0x00000000}, + {0x454F3741, 0x02000000, 0x00000001}, + {0x454F3743, 0x04000000, 0x00000002}, + {0x454F3842, 0x01000000, 0x00000001}, + {0x454F3959, 0x00800000, 0x00000000}, + {0x454F4142, 0x04000000, 0x00000001}, + {0x454F4143, 0x01000000, 0x00000001}, + {0x454F4156, 0x04000000, 0x00000001}, + {0x454F4241, 0x02000000, 0x00000001}, + {0x454F4259, 0x08000000, 0x00000003}, + {0x454F4341, 0x04000000, 0x00000005}, + {0x454F4359, 0x04000000, 0x00000001}, + {0x454F4641, 0x04000000, 0x00000003}, + {0x454F4842, 0x04000000, 0x00000001}, + {0x454F4843, 0x02000000, 0x00000001}, + {0x454F4942, 0x02000000, 0x00000001}, + {0x454F4943, 0x01000000, 0x00000008}, + {0x454F4A42, 0x04000000, 0x00000001}, + {0x454F4A43, 0x04000000, 0x00000002}, + {0x454F4B42, 0x04000000, 0x00000003}, + {0x454F4D41, 0x04000000, 0x00000002}, + {0x454F4D56, 0x02000000, 0x00000003}, + {0x454F4D59, 0x04000000, 0x00000001}, + {0x454F4E41, 0x02000000, 0x00000002}, + {0x454F4F42, 0x08000000, 0x00000002}, + {0x454F4F43, 0x04000000, 0x00000002}, + {0x454F5043, 0x01000000, 0x00000002}, + {0x454F5059, 0x04000000, 0x00000003}, + {0x454F5259, 0x04000000, 0x00000002}, + {0x454F5342, 0x02000000, 0x00000001}, + {0x454F5356, 0x04000000, 0x00000003}, + {0x454F5541, 0x00800000, 0x00000001}, + {0x454F5741, 0x02000000, 0x00000002}, + {0x454F5742, 0x02000000, 0x00000001}, + {0x454F5743, 0x00800000, 0x00000001}, + {0x454F5843, 0x04000000, 0x00000001}, + {0x454F5A42, 0x04000000, 0x00000003}, + {0x454F5A43, 0x02000000, 0x00000001}, + {0x45503342, 0x04000000, 0x00000001}, + {0x45503343, 0x04000000, 0x00000002}, + {0x45503441, 0x02000000, 0x00000002}, + {0x45503541, 0x04000000, 0x00000001}, + {0x45503643, 0x04000000, 0x00000007}, + {0x45503659, 0x04000000, 0x00000000}, + {0x45503741, 0x02000000, 0x00000001}, + {0x45503743, 0x04000000, 0x00000002}, + {0x45503859, 0x00800000, 0x00000008}, + {0x45504143, 0x02000000, 0x00000003}, + {0x45504243, 0x01000000, 0x00000002}, + {0x45504259, 0x02000000, 0x00000001}, + {0x45504341, 0x00800000, 0x00000002}, + {0x45504342, 0x04000000, 0x00000002}, + {0x45504442, 0x00800000, 0x00000001}, + {0x45504443, 0x01000000, 0x00000002}, + {0x45504542, 0x01000000, 0x00000002}, + {0x45504543, 0x08000000, 0x00000002}, + {0x45504643, 0x04000000, 0x00000002}, + {0x45504659, 0x01000000, 0x00000001}, + {0x45504741, 0x04000000, 0x00000002}, + {0x45504743, 0x02000000, 0x00000001}, + {0x45504754, 0x02000000, 0x00000001}, + {0x45504841, 0x04000000, 0x00000001}, + {0x45504941, 0x00800000, 0x00000008}, + {0x45504A41, 0x00800000, 0x00000001}, + {0x45504A43, 0x04000000, 0x00000002}, + {0x45504B41, 0x01000000, 0x00000001}, + {0x45504C41, 0x00800000, 0x00000001}, + {0x45504C42, 0x04000000, 0x00000002}, + {0x45504C43, 0x04000000, 0x00000003}, + {0x45504C54, 0x02000000, 0x00000001}, + {0x45504C59, 0x00800000, 0x00000002}, + {0x45504D41, 0x02000000, 0x00000002}, + {0x45504D43, 0x04000000, 0x00000001}, + {0x45504E41, 0x01000000, 0x00000001}, + {0x45504E59, 0x04000000, 0x00000002}, + {0x45504F41, 0x00800000, 0x00000001}, + {0x45504F43, 0x01000000, 0x00000003}, + {0x45504F59, 0x01000000, 0x00000001}, + {0x45505041, 0x001A68C8, 0x00000002}, + {0x45505043, 0x04000000, 0x00000005}, + {0x45505056, 0x02000000, 0x00000001}, + {0x45505141, 0x02000000, 0x00000002}, + {0x45505143, 0x01000000, 0x00000001}, + {0x45505159, 0x04000000, 0x00000002}, + {0x45505241, 0x04000000, 0x00000001}, + {0x45505242, 0x08000000, 0x00000002}, + {0x45505243, 0x02000000, 0x00000001}, + {0x45505256, 0x02000000, 0x00000001}, + {0x45505341, 0x02000000, 0x00000003}, + {0x45505342, 0x01000000, 0x00000002}, + {0x45505343, 0x10000000, 0x00000003}, + {0x45505356, 0x02000000, 0x00000002}, + {0x45505359, 0x02000000, 0x00000005}, + {0x45505442, 0x04000000, 0x00000002}, + {0x45505642, 0x08000000, 0x00000006}, + {0x45505659, 0x08000000, 0x00000003}, + {0x45505741, 0x01000000, 0x00000001}, + {0x45505742, 0x00800000, 0x00000001}, + {0x45505743, 0x02000000, 0x00000002}, + {0x45505841, 0x02000000, 0x00000005}, + {0x45505843, 0x02000000, 0x00000001}, + {0x45513543, 0x01000000, 0x00000002}, + {0x45513643, 0x08000000, 0x00000001}, + {0x45513741, 0x02000000, 0x00000001}, + {0x45513841, 0x02000000, 0x00000005}, + {0x45514141, 0x00800000, 0x00000000}, + {0x45514242, 0x00800000, 0x00000001}, + {0x45514243, 0x02000000, 0x00000002}, + {0x45514342, 0x01000000, 0x00000001}, + {0x45514359, 0x04000000, 0x00000002}, + {0x45514441, 0x04000000, 0x00000002}, + {0x45514459, 0x10000000, 0x00000003}, + {0x45514559, 0x00800000, 0x00000001}, + {0x45514641, 0x04000000, 0x00000002}, + {0x45514643, 0x01000000, 0x00000001}, + {0x45514741, 0x02000000, 0x00000003}, + {0x45514742, 0x02000000, 0x00000002}, + {0x45514743, 0x04000000, 0x00000003}, + {0x45514759, 0x04000000, 0x00000002}, + {0x45514841, 0x02000000, 0x00000001}, + {0x45514943, 0x02000000, 0x00000002}, + {0x45514A41, 0x01000000, 0x00000002}, + {0x45514A43, 0x00800000, 0x00000002}, + {0x45514A59, 0x01000000, 0x00000001}, + {0x45514B41, 0x02000000, 0x00000001}, + {0x45514B42, 0x04000000, 0x00000001}, + {0x45514B43, 0x02000000, 0x00000001}, + {0x45514C43, 0x04000000, 0x00000001}, + {0x45514D41, 0x04000000, 0x00000005}, + {0x45514E41, 0x00800000, 0x00000002}, + {0x45514E42, 0x02000000, 0x00000001}, + {0x45514F43, 0x04000000, 0x00000002}, + {0x45515042, 0x02000000, 0x00000001}, + {0x45515043, 0x02000000, 0x00000001}, + {0x45515141, 0x02000000, 0x00000002}, + {0x45515242, 0x01000000, 0x00000001}, + {0x45515243, 0x02000000, 0x00000001}, + {0x45515259, 0x02000000, 0x00000001}, + {0x45515341, 0x00800000, 0x00000002}, + {0x45515343, 0x01000000, 0x00000001}, + {0x45515359, 0x02000000, 0x00000002}, + {0x45515442, 0x01000000, 0x00000001}, + {0x45515641, 0x02000000, 0x00000002}, + {0x45515742, 0x01000000, 0x00000001}, + {0x45515743, 0x02000000, 0x00000001}, + {0x45515759, 0x00800000, 0x00000001}, + {0x45515842, 0x02000000, 0x00000001}, + {0x45515941, 0x00800000, 0x00000002}, + {0x45515943, 0x04000000, 0x00000001}, + {0x45515A43, 0x01000000, 0x00000001}, + {0x45523342, 0x08000000, 0x00000005}, + {0x45523442, 0x02000000, 0x00000001}, + {0x45523443, 0x02000000, 0x00000001}, + {0x45523459, 0x04000000, 0x00000008}, + {0x45523542, 0x10000000, 0x00000001}, + {0x45523559, 0x04000000, 0x00000008}, + {0x45523641, 0x04000000, 0x00000003}, + {0x45523642, 0x08000000, 0x00000002}, + {0x45523659, 0x04000000, 0x00000008}, + {0x45523741, 0x02000000, 0x00000001}, + {0x45524141, 0x00800000, 0x00000008}, + {0x45524143, 0x01000000, 0x00000002}, + {0x45524159, 0x01000000, 0x00000001}, + {0x45524241, 0x04000000, 0x00000002}, + {0x45524254, 0x04000000, 0x00000001}, + {0x45524256, 0x02000000, 0x00000001}, + {0x45524259, 0x04000000, 0x00000001}, + {0x45524341, 0x02000000, 0x00000001}, + {0x45524343, 0x00800000, 0x00000002}, + {0x45524354, 0x00800000, 0x00000001}, + {0x45524441, 0x01000000, 0x00000002}, + {0x45524442, 0x04000000, 0x00000005}, + {0x45524443, 0x00800000, 0x00000001}, + {0x45524459, 0x00800000, 0x00000001}, + {0x45524541, 0x01000000, 0x00000002}, + {0x45524542, 0x02000000, 0x00000001}, + {0x45524543, 0x02000000, 0x00000003}, + {0x45524559, 0x04000000, 0x00000003}, + {0x45524641, 0x04000000, 0x00000001}, + {0x45524643, 0x08000000, 0x00000002}, + {0x45524659, 0x01000000, 0x00000001}, + {0x45524756, 0x04000000, 0x00000001}, + {0x45524841, 0x02000000, 0x00000002}, + {0x45524842, 0x02000000, 0x00000001}, + {0x45524859, 0x01000000, 0x00000002}, + {0x45524942, 0x01000000, 0x00000001}, + {0x45524943, 0x04000000, 0x00000002}, + {0x45524959, 0x04000000, 0x00000001}, + {0x45524A41, 0x08000000, 0x00000005}, + {0x45524A42, 0x01000000, 0x00000001}, + {0x45524A43, 0x08000000, 0x00000003}, + {0x45524B42, 0x02000000, 0x00000001}, + {0x45524C42, 0x10000000, 0x00000001}, + {0x45524C43, 0x04000000, 0x00000003}, + {0x45524C54, 0x08000000, 0x00000001}, + {0x45524C59, 0x01000000, 0x00000002}, + {0x45524D43, 0x02000000, 0x00000002}, + {0x45524E42, 0x04000000, 0x00000003}, + {0x45524E43, 0x04000000, 0x00000002}, + {0x45524F55, 0x08000000, 0x00000008}, + {0x45525041, 0x02000000, 0x00000002}, + {0x45525042, 0x00800000, 0x00000001}, + {0x45525043, 0x04000000, 0x00000002}, + {0x45525059, 0x02000000, 0x00000002}, + {0x45525143, 0x04000000, 0x00000002}, + {0x45525241, 0x02000000, 0x00000002}, + {0x45525243, 0x02000000, 0x00000005}, + {0x45525254, 0x01000000, 0x00000001}, + {0x45525259, 0x02000000, 0x00000002}, + {0x45525342, 0x01000000, 0x00000001}, + {0x45525359, 0x01000000, 0x00000005}, + {0x45525441, 0x01000000, 0x00000002}, + {0x45525443, 0x02000000, 0x00000003}, + {0x45525459, 0x04000000, 0x00000001}, + {0x45525542, 0x01000000, 0x00000001}, + {0x45525741, 0x02000000, 0x00000005}, + {0x45525759, 0x04000000, 0x00000001}, + {0x45525843, 0x04000000, 0x00000001}, + {0x45525942, 0x08000000, 0x00000001}, + {0x45525959, 0x04000000, 0x00000001}, + {0x45525A42, 0x00800000, 0x00000001}, + {0x45525A43, 0x02000000, 0x00000001}, + {0x45533241, 0x04000000, 0x00000002}, + {0x45533242, 0x08000000, 0x00000002}, + {0x45533243, 0x08000000, 0x00000004}, + {0x45533341, 0x02000000, 0x00000001}, + {0x45533459, 0x08000000, 0x00000008}, + {0x45533543, 0x08000000, 0x00000001}, + {0x45533559, 0x04000000, 0x00000008}, + {0x45533641, 0x04000000, 0x00000001}, + {0x45533642, 0x04000000, 0x00000001}, + {0x45533741, 0x02000000, 0x00000001}, + {0x45533759, 0x04000000, 0x00000008}, + {0x45533842, 0x04000000, 0x00000002}, + {0x45533859, 0x00800000, 0x00000000}, + {0x45534143, 0x02000000, 0x00000001}, + {0x45534154, 0x01000000, 0x00000001}, + {0x45534242, 0x02000000, 0x00000001}, + {0x45534243, 0x01000000, 0x00000002}, + {0x45534256, 0x02000000, 0x00000001}, + {0x45534342, 0x04000000, 0x00000002}, + {0x45534354, 0x04000000, 0x00000005}, + {0x45534359, 0x00800000, 0x00000001}, + {0x45534443, 0x08000000, 0x00000001}, + {0x45534542, 0x04000000, 0x00000001}, + {0x45534556, 0x04000000, 0x00000001}, + {0x45534641, 0x02000000, 0x00000002}, + {0x45534656, 0x08000000, 0x00000003}, + {0x45534743, 0x08000000, 0x00000001}, + {0x45534754, 0x02000000, 0x00000001}, + {0x45534759, 0x04000000, 0x00000003}, + {0x45534841, 0x02000000, 0x00000002}, + {0x45534844, 0x02000000, 0xFFFFFFFF}, + {0x45534859, 0x02000000, 0x00000003}, + {0x45534941, 0x01000000, 0x00000001}, + {0x45534959, 0x04000000, 0x00000002}, + {0x45534A42, 0x04000000, 0x00000003}, + {0x45534A56, 0x04000000, 0x00000003}, + {0x45534B54, 0x02000000, 0x00000002}, + {0x45534C42, 0x04000000, 0x00000001}, + {0x45534C54, 0x01000000, 0x00000001}, + {0x45534D43, 0x02000000, 0x00000003}, + {0x45534D54, 0x01000000, 0x00000001}, + {0x45534E41, 0x01000000, 0x00000001}, + {0x45534E42, 0x01000000, 0x00000001}, + {0x45534E43, 0x04000000, 0x00000002}, + {0x45534F41, 0x08000000, 0x00000005}, + {0x45534F43, 0x02000000, 0x00000001}, + {0x45535043, 0x04000000, 0x00000002}, + {0x45535143, 0x02000000, 0x00000001}, + {0x45535243, 0x00800000, 0x00000001}, + {0x45535341, 0x04000000, 0x00000002}, + {0x45535342, 0x01000000, 0x00000002}, + {0x45535359, 0x04000000, 0x00000003}, + {0x45535541, 0x04000000, 0x00000001}, + {0x45535543, 0x02000000, 0x00000001}, + {0x45535559, 0x00800000, 0x00000001}, + {0x45535641, 0x02000000, 0x00000002}, + {0x45535643, 0x02000000, 0x00000001}, + {0x45535659, 0x02000000, 0x00000003}, + {0x45535741, 0x01000000, 0x00000002}, + {0x45535759, 0x08000000, 0x00000003}, + {0x45535842, 0x04000000, 0x00000003}, + {0x45535843, 0x01000000, 0x00000001}, + {0x45535943, 0x04000000, 0x00000002}, + {0x45535A42, 0x00800000, 0x00000001}, + {0x45543241, 0x02000000, 0x00000001}, + {0x45543341, 0x02000000, 0x00000002}, + {0x45543343, 0x04000000, 0x00000003}, + {0x45543442, 0x01000000, 0x00000002}, + {0x45543541, 0x02000000, 0x00000005}, + {0x45543542, 0x00800000, 0x00000001}, + {0x45543543, 0x02000000, 0x00000005}, + {0x45543559, 0x00800000, 0x00000008}, + {0x45543641, 0x04000000, 0x00000001}, + {0x45543642, 0x04000000, 0x00000002}, + {0x45543643, 0x01000000, 0x00000002}, + {0x45543741, 0x02000000, 0x00000001}, + {0x45543841, 0x02000000, 0x00000002}, + {0x45544142, 0x04000000, 0x00000002}, + {0x45544143, 0x02000000, 0x00000002}, + {0x45544154, 0x02000000, 0x00000001}, + {0x45544156, 0x02000000, 0x00000001}, + {0x45544159, 0x01000000, 0x00000002}, + {0x45544241, 0x02000000, 0x00000001}, + {0x45544254, 0x01000000, 0x00000001}, + {0x45544256, 0x02000000, 0x00000002}, + {0x45544259, 0x08000000, 0x00000003}, + {0x45544341, 0x02000000, 0x00000001}, + {0x45544359, 0x02000000, 0x00000001}, + {0x45544454, 0x10000000, 0x00000008}, + {0x45544459, 0x04000000, 0x00000003}, + {0x45544559, 0x01000000, 0x00000001}, + {0x45544641, 0x00800000, 0x00000001}, + {0x45544659, 0x04000000, 0x00000005}, + {0x45544742, 0x08000000, 0x00000002}, + {0x45544759, 0x02000000, 0x00000001}, + {0x45544941, 0x00800000, 0x00000001}, + {0x45544943, 0x01000000, 0x00000001}, + {0x45544959, 0x01000000, 0x00000001}, + {0x45544A41, 0x02000000, 0x00000001}, + {0x45544A56, 0x04000000, 0x00000001}, + {0x45544B43, 0x04000000, 0x00000002}, + {0x45544C41, 0x00800000, 0x00000001}, + {0x45544C42, 0x00800000, 0x00000001}, + {0x45544C59, 0x08000000, 0x00000002}, + {0x45544D41, 0x04000000, 0x00000002}, + {0x45544D42, 0x08000000, 0x00000003}, + {0x45544D43, 0x02000000, 0x00000001}, + {0x45544D54, 0x04000000, 0x00000002}, + {0x45544E41, 0x04000000, 0x00000002}, + {0x45545041, 0x01000000, 0x00000002}, + {0x45545054, 0x08000000, 0x00000001}, + {0x45545059, 0x02000000, 0x00000005}, + {0x45545141, 0x01000000, 0x00000002}, + {0x45545143, 0x04000000, 0x00000003}, + {0x45545259, 0x02000000, 0x00000002}, + {0x45545341, 0x02000000, 0x00000001}, + {0x45545343, 0x04000000, 0x00000001}, + {0x45545359, 0x04000000, 0x00000001}, + {0x45545541, 0x01000000, 0x00000001}, + {0x45545543, 0x01000000, 0x00000001}, + {0x45545559, 0x04000000, 0x00000002}, + {0x45545659, 0x02000000, 0x00000001}, + {0x45545741, 0x00800000, 0x00000001}, + {0x45545743, 0x02000000, 0x00000001}, + {0x45545841, 0x00800000, 0x00000001}, + {0x45545942, 0x08000000, 0x00000002}, + {0x45545959, 0x01000000, 0x00000002}, + {0x45545A41, 0x01000000, 0x00000005}, + {0x45545A59, 0x01000000, 0x00000005}, + {0x45553242, 0x02000000, 0x00000001}, + {0x45553342, 0x02000000, 0x00000002}, + {0x45553459, 0x02000000, 0x00000008}, + {0x45553541, 0x02000000, 0x00000005}, + {0x45553542, 0x04000000, 0x00000002}, + {0x45553543, 0x02000000, 0x00000002}, + {0x45553559, 0x01000000, 0x00000000}, + {0x45553659, 0x01000000, 0x00000000}, + {0x45553743, 0x02000000, 0x00000001}, + {0x45554159, 0x04000000, 0x00000003}, + {0x45554241, 0x04000000, 0x00000005}, + {0x45554242, 0x04000000, 0x00000003}, + {0x45554259, 0x08000000, 0x00000003}, + {0x45554341, 0x04000000, 0x00000005}, + {0x45554342, 0x01000000, 0x00000001}, + {0x45554359, 0x00400000, 0x00000003}, + {0x45554442, 0x02000000, 0x00000001}, + {0x45554443, 0x01000000, 0x00000003}, + {0x45554454, 0x00800000, 0x00000001}, + {0x45554543, 0x04000000, 0x00000002}, + {0x45554641, 0x01000000, 0x00000003}, + {0x45554642, 0x01000000, 0x00000001}, + {0x45554854, 0x02000000, 0x00000001}, + {0x45554859, 0x00800000, 0x00000001}, + {0x45554942, 0x01000000, 0x00000001}, + {0x45554943, 0x04000000, 0x00000002}, + {0x45554A59, 0x04000000, 0x00000002}, + {0x45554B41, 0x04000000, 0x00000001}, + {0x45554B42, 0x08000000, 0x00000005}, + {0x45554B56, 0x04000000, 0x00000001}, + {0x45554C54, 0x04000000, 0x00000001}, + {0x45554D41, 0x00800000, 0x00000001}, + {0x45554D42, 0x04000000, 0x00000001}, + {0x45554D43, 0x01000000, 0x00000003}, + {0x45554D59, 0x04000000, 0x00000002}, + {0x45554E41, 0x01000000, 0x00000001}, + {0x45554F43, 0x00800000, 0x00000003}, + {0x45555043, 0x08000000, 0x00000006}, + {0x45555054, 0x01000000, 0x00000001}, + {0x45555159, 0x08000000, 0x00000003}, + {0x45555242, 0x01000000, 0x00000001}, + {0x45555341, 0x04000000, 0x00000003}, + {0x45555343, 0x02000000, 0x00000001}, + {0x45555442, 0x04000000, 0x00000002}, + {0x45555741, 0x02000000, 0x00000001}, + {0x45555742, 0x01000000, 0x00000002}, + {0x45555743, 0x04000000, 0x00000001}, + {0x45555841, 0x02000000, 0x00000001}, + {0x45555843, 0x08000000, 0x00000002}, + {0x45555943, 0x01000000, 0x00000002}, + {0x45555959, 0x04000000, 0x00000001}, + {0x45555A42, 0x02000000, 0x00000002}, + {0x45555A56, 0x02000000, 0x00000002}, + {0x45563241, 0x00800000, 0x00000001}, + {0x45563242, 0x01000000, 0x00000001}, + {0x45563341, 0x04000000, 0x00000003}, + {0x45563342, 0x02000000, 0x00000001}, + {0x45563542, 0x04000000, 0x00000001}, + {0x45563559, 0x00800000, 0x00000008}, + {0x45563642, 0x00800000, 0x00000001}, + {0x45563643, 0x02000000, 0x00000001}, + {0x45563742, 0x00800000, 0x00000001}, + {0x45564142, 0x04000000, 0x00000001}, + {0x45564143, 0x02000000, 0x00000002}, + {0x45564156, 0x04000000, 0x00000001}, + {0x45564159, 0x04000000, 0x00000002}, + {0x45564242, 0x00800000, 0x00000001}, + {0x45564256, 0x02000000, 0x00000001}, + {0x45564259, 0x02000000, 0x00000002}, + {0x45564341, 0x04000000, 0x00000002}, + {0x45564359, 0x01000000, 0x00000003}, + {0x45564441, 0x01000000, 0x00000001}, + {0x45564442, 0x02000000, 0x00000001}, + {0x45564443, 0x01000000, 0x00000001}, + {0x45564454, 0x08000000, 0x00000003}, + {0x45564459, 0x00800000, 0x00000002}, + {0x45564641, 0x04000000, 0x00000001}, + {0x45564643, 0x02000000, 0x00000002}, + {0x45564741, 0x02000000, 0x00000002}, + {0x45564841, 0x01000000, 0x00000001}, + {0x45564842, 0x02000000, 0x00000001}, + {0x45564843, 0x02000000, 0x00000003}, + {0x45564854, 0x04000000, 0x00000001}, + {0x45564942, 0x00800000, 0x00000001}, + {0x45564959, 0x08000000, 0x00000003}, + {0x45564A59, 0x01000000, 0x00000002}, + {0x45564C41, 0x01000000, 0x00000002}, + {0x45564C54, 0x02000000, 0x00000002}, + {0x45564D41, 0x04000000, 0x00000001}, + {0x45564D42, 0x00800000, 0x00000001}, + {0x45564D43, 0x00800000, 0x00000001}, + {0x45564D59, 0x00800000, 0x00000001}, + {0x45564E43, 0x10000000, 0x00000005}, + {0x45564F59, 0x00800000, 0x00000001}, + {0x45565041, 0x00800000, 0x00000002}, + {0x45565042, 0x00800000, 0x00000004}, + {0x45565043, 0x04000000, 0x00000002}, + {0x45565056, 0x04000000, 0x00000002}, + {0x45565059, 0x04000000, 0x00000001}, + {0x45565141, 0x01000000, 0x00000002}, + {0x45565143, 0x04000000, 0x00000001}, + {0x45565159, 0x01000000, 0x00000001}, + {0x45565241, 0x02000000, 0x00000003}, + {0x45565242, 0x01000000, 0x00000002}, + {0x45565259, 0x02000000, 0x00000005}, + {0x45565341, 0x00800000, 0x00000001}, + {0x45565342, 0x02000000, 0x00000001}, + {0x45565343, 0x02000000, 0x00000005}, + {0x45565441, 0x01000000, 0x00000001}, + {0x45565442, 0x02000000, 0x00000002}, + {0x45565459, 0x08000000, 0x00000003}, + {0x45565642, 0x01000000, 0x00000002}, + {0x45565741, 0x01000000, 0x00000001}, + {0x45565742, 0x02000000, 0x00000001}, + {0x45565756, 0x04000000, 0x00000001}, + {0x45565841, 0x04000000, 0x00000003}, + {0x45565842, 0x02000000, 0x00000001}, + {0x45565A41, 0x00800000, 0x00000001}, + {0x45565A42, 0x04000000, 0x00000002}, + {0x45565A43, 0x02000000, 0x00000001}, + {0x45573241, 0x04000000, 0x00000001}, + {0x45573259, 0x04000000, 0x00000008}, + {0x45573341, 0x04000000, 0x00000002}, + {0x45573342, 0x04000000, 0x00000002}, + {0x45573543, 0x01000000, 0x00000002}, + {0x45573641, 0x02000000, 0x00000002}, + {0x45573642, 0x08000000, 0x00000002}, + {0x45573643, 0x02000000, 0x00000002}, + {0x45573742, 0x01000000, 0x00000002}, + {0x45573759, 0x00800000, 0x00000001}, + {0x45574159, 0x04000000, 0x00000002}, + {0x45574259, 0x01000000, 0x00000002}, + {0x45574343, 0x02000000, 0x00000002}, + {0x45574354, 0x02000000, 0x00000001}, + {0x45574356, 0x02000000, 0x00000002}, + {0x45574442, 0x02000000, 0x00000001}, + {0x45574459, 0x02000000, 0x00000005}, + {0x45574542, 0x04000000, 0x00000002}, + {0x45574641, 0x01000000, 0x00000001}, + {0x45574643, 0x01000000, 0x00000001}, + {0x45574659, 0x00800000, 0x00000001}, + {0x45574741, 0x01000000, 0x00000002}, + {0x45574743, 0x00800000, 0x00000001}, + {0x45574759, 0x00800000, 0x00000001}, + {0x45574842, 0x00800000, 0x00000001}, + {0x45574856, 0x04000000, 0x00000002}, + {0x45574859, 0x02000000, 0x00000001}, + {0x45574942, 0x02000000, 0x00000002}, + {0x45574A43, 0x00800000, 0x00000001}, + {0x45574A56, 0x02000000, 0x00000003}, + {0x45574B41, 0x04000000, 0x00000002}, + {0x45574B42, 0x00800000, 0x00000002}, + {0x45574B59, 0x08000000, 0x00000003}, + {0x45574C41, 0x02000000, 0x00000001}, + {0x45574C43, 0x10000000, 0x00000002}, + {0x45574D41, 0x04000000, 0x00000002}, + {0x45574D49, 0x04000000, 0x00000007}, + {0x45574E41, 0x02000000, 0x00000002}, + {0x45574E59, 0x02000000, 0x00000001}, + {0x45574F41, 0x00800000, 0x00000001}, + {0x45575041, 0x02000000, 0x00000001}, + {0x45575042, 0x01000000, 0x00000001}, + {0x45575043, 0x04000000, 0x00000002}, + {0x45575141, 0x01000000, 0x00000001}, + {0x45575243, 0x02000000, 0x00000002}, + {0x45575254, 0x02000000, 0x00000002}, + {0x45575259, 0x02000000, 0x00000005}, + {0x45575341, 0x02000000, 0x00000001}, + {0x45575343, 0x04000000, 0x00000001}, + {0x45575359, 0x00800000, 0x00000001}, + {0x45575441, 0x02000000, 0x00000002}, + {0x45575442, 0x02000000, 0x00000001}, + {0x45575443, 0x08000000, 0x00000001}, + {0x45575641, 0x02000000, 0x00000002}, + {0x45575741, 0x02000000, 0x00000001}, + {0x45575842, 0x00800000, 0x00000001}, + {0x45575941, 0x02000000, 0x00000002}, + {0x45575943, 0x01000000, 0x00000001}, + {0x45575959, 0x02000000, 0x00000001}, + {0x45575A41, 0x02000000, 0x00000002}, + {0x45583242, 0x02000000, 0x00000002}, + {0x45583341, 0x04000000, 0x00000001}, + {0x45583342, 0x01000000, 0x00000001}, + {0x45583659, 0x00800000, 0x00000000}, + {0x45584154, 0x00800000, 0x00000001}, + {0x45584241, 0x02000000, 0x00000002}, + {0x45584242, 0x00800000, 0x00000001}, + {0x45584243, 0x01000000, 0x00000003}, + {0x45584259, 0x00800000, 0x00000001}, + {0x45584341, 0x01000000, 0x00000003}, + {0x45584343, 0x01000000, 0x00000003}, + {0x45584359, 0x02000000, 0x00000002}, + {0x45584456, 0x04000000, 0x00000001}, + {0x45584542, 0x01000000, 0x00000001}, + {0x45584559, 0x02000000, 0x00000002}, + {0x45584641, 0x08000000, 0x00000003}, + {0x45584642, 0x04000000, 0x00000002}, + {0x45584643, 0x01000000, 0x00000001}, + {0x45584659, 0x02000000, 0x00000001}, + {0x45584741, 0x08000000, 0x00000003}, + {0x45584759, 0x08000000, 0x00000002}, + {0x45584841, 0x00800000, 0x00000001}, + {0x45584843, 0x02000000, 0x00000003}, + {0x45584859, 0x01000000, 0x00000001}, + {0x45584A43, 0x01000000, 0x00000001}, + {0x45584B43, 0x01000000, 0x00000001}, + {0x45584C41, 0x02000000, 0x00000001}, + {0x45584C59, 0x00800000, 0x00000001}, + {0x45584D41, 0x01000000, 0x00000001}, + {0x45584D42, 0x02000000, 0x00000001}, + {0x45584D43, 0x01000000, 0x00000001}, + {0x45584D59, 0x00800000, 0x00000001}, + {0x45584E41, 0x02000000, 0x00000001}, + {0x45584E42, 0x04000000, 0x00000002}, + {0x45584E59, 0x00800000, 0x00000002}, + {0x45585159, 0x01000000, 0x00000001}, + {0x45585343, 0x01000000, 0x00000001}, + {0x45585359, 0x01000000, 0x00000001}, + {0x45585441, 0x01000000, 0x00000002}, + {0x45585442, 0x04000000, 0x00000001}, + {0x45585443, 0x01000000, 0x00000001}, + {0x45585543, 0x04000000, 0x00000001}, + {0x45585559, 0x04000000, 0x00000003}, + {0x45585641, 0x01000000, 0x00000001}, + {0x45585643, 0x04000000, 0x00000002}, + {0x45585741, 0x01000000, 0x00000002}, + {0x45585842, 0x02000000, 0x00000001}, + {0x45585859, 0x04000000, 0x00000002}, + {0x45585941, 0x08000000, 0x00000005}, + {0x45585942, 0x10000000, 0x00000003}, + {0x45585943, 0x02000000, 0x00000001}, + {0x45585A42, 0x02000000, 0x00000001}, + {0x45585A59, 0x04000000, 0x00000002}, + {0x45593341, 0x04000000, 0x00000003}, + {0x45593342, 0x02000000, 0x00000001}, + {0x45593459, 0x01000000, 0x00000008}, + {0x45593559, 0x01000000, 0x00000008}, + {0x45593641, 0x01000000, 0x00000002}, + {0x45593742, 0x01000000, 0x00000002}, + {0x45593759, 0x00800000, 0x00000008}, + {0x45594143, 0x02000000, 0x00000001}, + {0x45594159, 0x02000000, 0x00000001}, + {0x45594242, 0x00800000, 0x00000001}, + {0x45594243, 0x02000000, 0x00000001}, + {0x45594259, 0x02000000, 0x00000001}, + {0x45594343, 0x01000000, 0x00000001}, + {0x45594354, 0x04000000, 0x00000002}, + {0x45594359, 0x00800000, 0x00000001}, + {0x45594442, 0x04000000, 0x00000002}, + {0x45594542, 0x01000000, 0x00000001}, + {0x45594543, 0x02000000, 0x00000001}, + {0x45594641, 0x04000000, 0x00000001}, + {0x45594659, 0x04000000, 0x00000005}, + {0x45594741, 0x04000000, 0x00000005}, + {0x45594756, 0x02000000, 0x00000002}, + {0x45594842, 0x01000000, 0x00000001}, + {0x45594843, 0x01000000, 0x00000001}, + {0x45594941, 0x02000000, 0x00000001}, + {0x45594943, 0x04000000, 0x00000002}, + {0x45594959, 0x01000000, 0x00000001}, + {0x45594B41, 0x01000000, 0x00000003}, + {0x45594B42, 0x02000000, 0x00000002}, + {0x45594C41, 0x04000000, 0x00000001}, + {0x45594C59, 0x02000000, 0x00000002}, + {0x45594D42, 0x01000000, 0x00000002}, + {0x45594D56, 0x04000000, 0x00000001}, + {0x45594D59, 0x08000000, 0x00000002}, + {0x45594E41, 0x04000000, 0x00000003}, + {0x45594E42, 0x04000000, 0x00000001}, + {0x45594E43, 0x04000000, 0x00000002}, + {0x45594E59, 0x00800000, 0x00000001}, + {0x45594F41, 0x01000000, 0x00000002}, + {0x45594F43, 0x04000000, 0x00000002}, + {0x45595041, 0x02000000, 0x00000002}, + {0x45595042, 0x00800000, 0x00000001}, + {0x45595142, 0x04000000, 0x00000001}, + {0x45595241, 0x02000000, 0x00000002}, + {0x45595243, 0x01000000, 0x00000001}, + {0x45595254, 0x02000000, 0x00000001}, + {0x45595342, 0x02000000, 0x00000002}, + {0x45595343, 0x01000000, 0x00000001}, + {0x45595344, 0x02000000, 0x00000001}, + {0x45595359, 0x01000000, 0x00000001}, + {0x45595543, 0x02000000, 0x00000001}, + {0x45595642, 0x08000000, 0x00000001}, + {0x45595842, 0x04000000, 0x00000002}, + {0x45595859, 0x00800000, 0x00000001}, + {0x45595941, 0x01000000, 0x00000002}, + {0x45595942, 0x08000000, 0x00000003}, + {0x45595A41, 0x04000000, 0x00000002}, + {0x45595A42, 0x00800000, 0x00000001}, + {0x45595A59, 0x01000000, 0x00000002}, + {0x455A3441, 0x00800000, 0x00000001}, + {0x455A3443, 0x04000000, 0x00000002}, + {0x455A3541, 0x04000000, 0x00000001}, + {0x455A3542, 0x00800000, 0x00000001}, + {0x455A3543, 0x00800000, 0x00000001}, + {0x455A3642, 0x04000000, 0x00000003}, + {0x455A3659, 0x08000000, 0x00000000}, + {0x455A3742, 0x04000000, 0x00000001}, + {0x455A4159, 0x01000000, 0x00000001}, + {0x455A4241, 0x08000000, 0x00000003}, + {0x455A4242, 0x01000000, 0x00000001}, + {0x455A4259, 0x01000000, 0x00000001}, + {0x455A4341, 0x01000000, 0x00000001}, + {0x455A4343, 0x00800000, 0x00000001}, + {0x455A4354, 0x04000000, 0x00000002}, + {0x455A4441, 0x02000000, 0x00000002}, + {0x455A4442, 0x04000000, 0x00000003}, + {0x455A4443, 0x04000000, 0x00000002}, + {0x455A4641, 0x04000000, 0x00000001}, + {0x455A4642, 0x00800000, 0x00000001}, + {0x455A4656, 0x02000000, 0x00000001}, + {0x455A4742, 0x01000000, 0x00000002}, + {0x455A4841, 0x04000000, 0x00000001}, + {0x455A4842, 0x02000000, 0x00000003}, + {0x455A4859, 0x04000000, 0x00000002}, + {0x455A4941, 0x01000000, 0x00000002}, + {0x455A4943, 0x02000000, 0x00000001}, + {0x455A4959, 0x04000000, 0x00000002}, + {0x455A4A59, 0x04000000, 0x00000005}, + {0x455A4B43, 0x01000000, 0x00000005}, + {0x455A4C43, 0x04000000, 0x00000001}, + {0x455A4C59, 0x08000000, 0x00000002}, + {0x455A4D56, 0x04000000, 0x00000001}, + {0x455A4D59, 0x01000000, 0x00000001}, + {0x455A4E41, 0x01000000, 0x00000001}, + {0x455A4E59, 0x04000000, 0x00000002}, + {0x455A4F41, 0x01000000, 0x00000002}, + {0x455A4F42, 0x02000000, 0x00000001}, + {0x455A4F43, 0x08000000, 0x00000002}, + {0x455A5042, 0x00800000, 0x00000001}, + {0x455A5043, 0x02000000, 0x00000002}, + {0x455A5143, 0x02000000, 0x00000001}, + {0x455A5241, 0x04000000, 0x00000002}, + {0x455A5242, 0x04000000, 0x00000003}, + {0x455A5243, 0x00800000, 0x00000002}, + {0x455A5254, 0x02000000, 0x00000002}, + {0x455A5341, 0x01000000, 0x00000001}, + {0x455A5343, 0x02000000, 0x00000005}, + {0x455A5359, 0x08000000, 0x00000001}, + {0x455A5442, 0x02000000, 0x00000001}, + {0x455A5443, 0x02000000, 0x00000003}, + {0x455A5459, 0x02000000, 0x00000001}, + {0x455A5541, 0x04000000, 0x00000005}, + {0x455A5543, 0x04000000, 0x00000001}, + {0x455A5759, 0x04000000, 0x00000001}, + {0x455A5A42, 0x00800000, 0x00000001}, + {0x46323643, 0x04000000, 0x00000001}, + {0x46324543, 0x02000000, 0x00000001}, + {0x46324C42, 0x01000000, 0x00000001}, + {0x46324E42, 0x01000000, 0x00000002}, + {0x46325959, 0x00800000, 0x00000001}, + {0x46334343, 0x01000000, 0x00000001}, + {0x46334E42, 0x01000000, 0x00000002}, + {0x46335141, 0x04000000, 0x00000002}, + {0x46335159, 0x04000000, 0x00000002}, + {0x46335742, 0x08000000, 0x00000002}, + {0x46344259, 0x02000000, 0x00000001}, + {0x46344559, 0x02000000, 0x00000001}, + {0x46344E42, 0x01000000, 0x00000002}, + {0x46354243, 0x01000000, 0x00000001}, + {0x46354841, 0x02000000, 0x00000002}, + {0x46354E42, 0x01000000, 0x00000002}, + {0x46363443, 0x00800000, 0x00000001}, + {0x46364E42, 0x01000000, 0x00000002}, + {0x46373343, 0x02000000, 0x00000001}, + {0x46373443, 0x02000000, 0x00000001}, + {0x46373543, 0x02000000, 0x00000001}, + {0x46373742, 0x00800000, 0x00000001}, + {0x46374559, 0x00800000, 0x00000001}, + {0x46375443, 0x00800000, 0x00000002}, + {0x46375959, 0x01000000, 0x00000001}, + {0x46383643, 0x02000000, 0x00000001}, + {0x46383742, 0x00800000, 0x00000001}, + {0x46384343, 0x02000000, 0x00000001}, + {0x46384543, 0x02000000, 0x00000001}, + {0x46384C59, 0x01000000, 0x00000001}, + {0x46394341, 0x04000000, 0x00000001}, + {0x46394343, 0x02000000, 0x00000001}, + {0x46394943, 0x01000000, 0x00000002}, + {0x46395342, 0x00800000, 0x00000001}, + {0x46395942, 0x00800000, 0x00000001}, + {0x46413343, 0x00800000, 0x00000001}, + {0x46414441, 0x04000000, 0x00000006}, + {0x46414759, 0x01000000, 0x00000001}, + {0x46414C59, 0x00800000, 0x00000002}, + {0x46414E43, 0x02000000, 0x00000001}, + {0x46414F43, 0x00800000, 0x00000001}, + {0x46415041, 0x04000000, 0x00000006}, + {0x46415249, 0x10000000, 0x00000006}, + {0x46415843, 0x00800000, 0x00000001}, + {0x46423542, 0x04000000, 0x00000002}, + {0x46424354, 0x08000000, 0x00000001}, + {0x46424542, 0x10000000, 0x00000003}, + {0x46424659, 0x01000000, 0x00000001}, + {0x46424A42, 0x04000000, 0x00000001}, + {0x46424D43, 0x01000000, 0x00000001}, + {0x46424F43, 0x00800000, 0x00000001}, + {0x46425042, 0x01000000, 0x00000001}, + {0x46425043, 0x01000000, 0x00000001}, + {0x46425249, 0x10000000, 0x00000006}, + {0x46425254, 0x00800000, 0x00000001}, + {0x46425843, 0x00800000, 0x00000001}, + {0x46433243, 0x00800000, 0x00000001}, + {0x46434143, 0x01000000, 0x00000002}, + {0x46434A42, 0x04000000, 0x00000002}, + {0x46435843, 0x00800000, 0x00000001}, + {0x46435943, 0x02000000, 0x00000002}, + {0x46444143, 0x01000000, 0x00000002}, + {0x46444359, 0x02000000, 0x00000001}, + {0x46445054, 0x08000000, 0x00000001}, + {0x46445249, 0x20000000, 0x00000006}, + {0x46445443, 0x04000000, 0x00000002}, + {0x46445641, 0x01000000, 0x00000002}, + {0x46445843, 0x00800000, 0x00000001}, + {0x46454143, 0x01000000, 0x00000002}, + {0x46454542, 0x10000000, 0x00000003}, + {0x46454543, 0x00800000, 0x00000001}, + {0x46454559, 0x10000000, 0x00000003}, + {0x46454741, 0x01000000, 0x00000001}, + {0x46454959, 0x02000000, 0x00000002}, + {0x46455249, 0x20000000, 0x00000006}, + {0x46455542, 0x02000000, 0x00000001}, + {0x46455843, 0x00800000, 0x00000001}, + {0x46464143, 0x01000000, 0x00000001}, + {0x46464459, 0x01000000, 0x00000001}, + {0x46464A43, 0x01000000, 0x00000001}, + {0x46464B59, 0x02000000, 0x00000001}, + {0x46464C42, 0x10000000, 0x00000003}, + {0x46464D43, 0x00800000, 0x00000001}, + {0x46465059, 0x02000000, 0x00000001}, + {0x46465359, 0x04000000, 0x00000001}, + {0x46465843, 0x00800000, 0x00000001}, + {0x46465959, 0x00800000, 0x00000001}, + {0x46474D41, 0x01000000, 0x00000001}, + {0x46474D43, 0x04000000, 0x00000001}, + {0x46475049, 0x08000000, 0x00000006}, + {0x46483842, 0x04000000, 0x00000002}, + {0x46484143, 0x00800000, 0x00000001}, + {0x46484259, 0x02000000, 0x00000002}, + {0x46484A42, 0x01000000, 0x00000001}, + {0x46495443, 0x02000000, 0x00000002}, + {0x464A3343, 0x10000000, 0x00000003}, + {0x464A3743, 0x00800000, 0x00000001}, + {0x464A4754, 0x00800000, 0x00000001}, + {0x464A4959, 0x04000000, 0x00000002}, + {0x464A4F41, 0x02000000, 0x00000002}, + {0x464A4F42, 0x04000000, 0x00000002}, + {0x464A4F43, 0x00800000, 0x00000001}, + {0x464A5641, 0x04000000, 0x00000002}, + {0x464A5759, 0x00800000, 0x00000002}, + {0x464B4159, 0x08000000, 0x00000002}, + {0x464B4356, 0x08000000, 0x00000002}, + {0x464B4841, 0x04000000, 0x00000003}, + {0x464B5049, 0x08000000, 0x00000006}, + {0x464C4343, 0x02000000, 0x00000002}, + {0x464C4359, 0x01000000, 0x00000002}, + {0x464C4842, 0x04000000, 0x00000002}, + {0x464C4D59, 0x00800000, 0x00000001}, + {0x464C4F41, 0x00800000, 0x00000001}, + {0x464D4443, 0x00800000, 0x00000001}, + {0x464D4C54, 0x08000000, 0x00000001}, + {0x464D5141, 0x00800000, 0x00000001}, + {0x464E4243, 0x02000000, 0x00000001}, + {0x464E4259, 0x04000000, 0x00000007}, + {0x464E5243, 0x01000000, 0x00000001}, + {0x464E5759, 0x02000000, 0x00000001}, + {0x464F4359, 0x04000000, 0x00000001}, + {0x46504242, 0x00800000, 0x00000001}, + {0x46504A59, 0x01000000, 0x00000001}, + {0x46504B43, 0x02000000, 0x00000001}, + {0x46504C43, 0x04000000, 0x00000003}, + {0x46504F42, 0x01000000, 0x00000001}, + {0x46505041, 0x01000000, 0x00000002}, + {0x46505942, 0x02000000, 0x00000001}, + {0x46505A55, 0x08000000, 0x00000003}, + {0x46514343, 0x02000000, 0x00000001}, + {0x46514C59, 0x04000000, 0x00000001}, + {0x46514D43, 0x02000000, 0x00000001}, + {0x46524359, 0x02000000, 0x00000001}, + {0x46525141, 0x01000000, 0x00000002}, + {0x46525359, 0x01000000, 0x00000005}, + {0x46533341, 0x02000000, 0x00000001}, + {0x46534343, 0x02000000, 0x00000001}, + {0x46534959, 0x02000000, 0x00000002}, + {0x46534F41, 0x08000000, 0x00000005}, + {0x46535541, 0x04000000, 0x00000001}, + {0x46543242, 0x00800000, 0x00000001}, + {0x46543743, 0x01000000, 0x00000002}, + {0x46544159, 0x01000000, 0x00000002}, + {0x46544443, 0x02000000, 0x00000001}, + {0x46544C43, 0x00800000, 0x00000001}, + {0x46544C59, 0x08000000, 0x00000002}, + {0x46545643, 0x02000000, 0x00000001}, + {0x46554243, 0x01000000, 0x00000001}, + {0x46554259, 0x08000000, 0x00000003}, + {0x46554559, 0x01000000, 0x00000001}, + {0x46554743, 0x01000000, 0x00000002}, + {0x46554F59, 0x02000000, 0x00000001}, + {0x46555043, 0x08000000, 0x00000006}, + {0x46555643, 0x01000000, 0x00000001}, + {0x46563742, 0x01000000, 0x00000001}, + {0x46564559, 0x01000000, 0x00000001}, + {0x46564643, 0x02000000, 0x00000002}, + {0x46564859, 0x04000000, 0x00000001}, + {0x46564E43, 0x10000000, 0x00000005}, + {0x46565841, 0x04000000, 0x00000003}, + {0x46573743, 0x00800000, 0x00000001}, + {0x46574243, 0x02000000, 0x00000001}, + {0x46574356, 0x02000000, 0x00000002}, + {0x46574959, 0x04000000, 0x00000001}, + {0x46575959, 0x02000000, 0x00000001}, + {0x46583543, 0x02000000, 0x00000001}, + {0x46583743, 0x00800000, 0x00000001}, + {0x46585059, 0x00800000, 0x00000003}, + {0x46585441, 0x01000000, 0x00000002}, + {0x46585959, 0x01000000, 0x00000001}, + {0x46593743, 0x00800000, 0x00000001}, + {0x46594342, 0x04000000, 0x00000001}, + {0x46594442, 0x04000000, 0x00000002}, + {0x46594443, 0x02000000, 0x00000002}, + {0x46594641, 0x04000000, 0x00000001}, + {0x46594642, 0x01000000, 0x00000001}, + {0x46594A59, 0x00800000, 0x00000001}, + {0x46594C41, 0x04000000, 0x00000001}, + {0x46595559, 0x00800000, 0x00000001}, + {0x46595A41, 0x04000000, 0x00000002}, + {0x465A3659, 0x08000000, 0x00000008}, + {0x465A3743, 0x00800000, 0x00000001}, + {0x465A4142, 0x04000000, 0x00000001}, + {0x465A4641, 0x04000000, 0x00000001}, + {0x465A4F41, 0x01000000, 0x00000002}, + {0x465A5359, 0x08000000, 0x00000001}, + {0x474C4443, 0x02000000, 0x00000004}, + {0x47595543, 0x02000000, 0x00000001}, + {0x48334B54, 0x01000000, 0x00000001}, + {0x48335159, 0x04000000, 0x00000002}, + {0x48344259, 0x02000000, 0x00000001}, + {0x48344559, 0x02000000, 0x00000001}, + {0x48354841, 0x02000000, 0x00000002}, + {0x48373642, 0x01000000, 0x00000002}, + {0x48374E43, 0x01000000, 0x00000002}, + {0x48384C59, 0x01000000, 0x00000001}, + {0x48414B54, 0x02000000, 0x00000001}, + {0x48414C59, 0x00800000, 0x00000002}, + {0x48434842, 0x01000000, 0x00000001}, + {0x48435943, 0x02000000, 0x00000002}, + {0x48454E42, 0x02000000, 0x00000001}, + {0x48455142, 0x02000000, 0x00000002}, + {0x48464B59, 0x02000000, 0x00000001}, + {0x48464C42, 0x10000000, 0x00000003}, + {0x48464E42, 0x02000000, 0x00000001}, + {0x48474D41, 0x01000000, 0x00000001}, + {0x48474D43, 0x04000000, 0x00000001}, + {0x48494759, 0x00800000, 0x00000002}, + {0x48495959, 0x01000000, 0x00000001}, + {0x484A3343, 0x10000000, 0x00000003}, + {0x484A4D43, 0x01000000, 0x00000002}, + {0x484B5242, 0x00800000, 0x00000002}, + {0x484C3542, 0x01000000, 0x00000001}, + {0x484C4842, 0x04000000, 0x00000002}, + {0x484C5143, 0x00800000, 0x00000002}, + {0x484C5442, 0x00800000, 0x00000002}, + {0x484C5459, 0x00800000, 0x00000002}, + {0x484D5742, 0x01000000, 0x00000001}, + {0x484E4242, 0x00800000, 0x00000002}, + {0x48504A59, 0x01000000, 0x00000001}, + {0x48505443, 0x00800000, 0x00000002}, + {0x48515443, 0x00800000, 0x00000001}, + {0x48533341, 0x02000000, 0x00000001}, + {0x48544C59, 0x08000000, 0x00000002}, + {0x48565742, 0x02000000, 0x00000001}, + {0x48565841, 0x04000000, 0x00000003}, + {0x48575143, 0x02000000, 0x00000008}, + {0x48594559, 0x01000000, 0x00000001}, + {0x48595759, 0x04000000, 0x00000002}, + {0x485A3243, 0x00800000, 0x00000002}, + {0x485A4841, 0x04000000, 0x00000001}, + {0x485A4942, 0x01000000, 0x00000001}, + {0x49323643, 0x04000000, 0x00000001}, + {0x49334943, 0x04000000, 0x00000001}, + {0x49335141, 0x04000000, 0x00000002}, + {0x49335159, 0x04000000, 0x00000002}, + {0x49335742, 0x08000000, 0x00000002}, + {0x49344259, 0x02000000, 0x00000001}, + {0x49354841, 0x02000000, 0x00000002}, + {0x49364959, 0x04000000, 0x00000002}, + {0x49384C59, 0x01000000, 0x00000001}, + {0x49394341, 0x04000000, 0x00000001}, + {0x49413643, 0x00800000, 0x00000001}, + {0x49414441, 0x04000000, 0x00000006}, + {0x49414C59, 0x00800000, 0x00000002}, + {0x49415041, 0x04000000, 0x00000006}, + {0x49415249, 0x10000000, 0x00000006}, + {0x49424542, 0x10000000, 0x00000003}, + {0x49425249, 0x10000000, 0x00000006}, + {0x49434A42, 0x04000000, 0x00000002}, + {0x49434D43, 0x02000000, 0x00000002}, + {0x49435141, 0x02000000, 0x00000002}, + {0x49435943, 0x02000000, 0x00000002}, + {0x49445249, 0x20000000, 0x00000006}, + {0x49445641, 0x01000000, 0x00000002}, + {0x49454542, 0x10000000, 0x00000003}, + {0x49454559, 0x10000000, 0x00000003}, + {0x49455249, 0x20000000, 0x00000006}, + {0x49464B59, 0x02000000, 0x00000001}, + {0x49464C42, 0x10000000, 0x00000003}, + {0x49465359, 0x04000000, 0x00000001}, + {0x49474354, 0x04000000, 0x00000001}, + {0x49474D41, 0x01000000, 0x00000001}, + {0x49474D43, 0x04000000, 0x00000001}, + {0x49475049, 0x08000000, 0x00000006}, + {0x49483642, 0x02000000, 0x00000001}, + {0x494A3343, 0x10000000, 0x00000003}, + {0x494A4D54, 0x02000000, 0x00000001}, + {0x494A4F41, 0x02000000, 0x00000002}, + {0x494A5641, 0x04000000, 0x00000002}, + {0x494B4356, 0x08000000, 0x00000002}, + {0x494B5049, 0x08000000, 0x00000006}, + {0x494B5356, 0x04000000, 0x00000001}, + {0x494C4C43, 0x00800000, 0x00000002}, + {0x494C5842, 0x01000000, 0x00000002}, + {0x494D4359, 0x02000000, 0x00000001}, + {0x494E5243, 0x01000000, 0x00000001}, + {0x494F4359, 0x04000000, 0x00000001}, + {0x49505A55, 0x08000000, 0xFFFFFFFF}, + {0x49525359, 0x01000000, 0x00000005}, + {0x49525643, 0x00800000, 0x00000001}, + {0x49533341, 0x02000000, 0x00000001}, + {0x49534F41, 0x08000000, 0x00000005}, + {0x49535541, 0x04000000, 0x00000001}, + {0x49544C59, 0x08000000, 0x00000002}, + {0x49554259, 0x08000000, 0x00000003}, + {0x49555043, 0x08000000, 0x00000006}, + {0x49564E43, 0x10000000, 0x00000005}, + {0x49565841, 0x04000000, 0x00000003}, + {0x49574342, 0x01000000, 0x00000001}, + {0x49585059, 0x00800000, 0x00000003}, + {0x49594641, 0x04000000, 0x00000001}, + {0x49594C41, 0x04000000, 0x00000001}, + {0x49595543, 0x02000000, 0x00000001}, + {0x495A3659, 0x08000000, 0x00000008}, + {0x495A4341, 0x01000000, 0x00000001}, + {0x495A4641, 0x04000000, 0x00000001}, + {0x495A4F41, 0x01000000, 0x00000002}, + {0x495A5359, 0x08000000, 0x00000001}, + {0x4A323242, 0x08000000, 0x00000003}, + {0x4A323243, 0x04000000, 0x00000002}, + {0x4A323342, 0x04000000, 0x00000001}, + {0x4A323343, 0x04000000, 0x00000003}, + {0x4A323442, 0x04000000, 0x00000002}, + {0x4A323443, 0x04000000, 0x00000002}, + {0x4A323543, 0x04000000, 0x00000002}, + {0x4A323642, 0x04000000, 0x00000005}, + {0x4A323742, 0x01000000, 0x00000001}, + {0x4A324143, 0x08000000, 0x00000003}, + {0x4A324159, 0x08000000, 0x00000001}, + {0x4A324243, 0x02000000, 0x00000002}, + {0x4A324259, 0x02000000, 0x00000002}, + {0x4A324341, 0x04000000, 0x00000001}, + {0x4A324359, 0x04000000, 0x00000006}, + {0x4A324441, 0x02000000, 0x00000005}, + {0x4A324442, 0x01000000, 0x00000002}, + {0x4A324443, 0x04000000, 0x00000002}, + {0x4A324541, 0x08000000, 0x00000001}, + {0x4A324559, 0x04000000, 0x00000002}, + {0x4A324641, 0x01000000, 0x00000002}, + {0x4A324642, 0x04000000, 0x00000005}, + {0x4A324659, 0x10000000, 0x00000003}, + {0x4A324742, 0x08000000, 0x00000005}, + {0x4A324759, 0x01000000, 0x00000001}, + {0x4A324841, 0x00800000, 0x00000003}, + {0x4A324842, 0x02000000, 0x00000003}, + {0x4A324843, 0x04000000, 0x00000002}, + {0x4A324956, 0x08000000, 0x00000005}, + {0x4A324A43, 0x01000000, 0x00000002}, + {0x4A324B41, 0x02000000, 0x00000001}, + {0x4A324B54, 0x04000000, 0x00000001}, + {0x4A324B59, 0x02000000, 0x00000003}, + {0x4A324C41, 0x04000000, 0x00000002}, + {0x4A324C59, 0x08000000, 0x00000003}, + {0x4A324D41, 0x04000000, 0x00000005}, + {0x4A324D42, 0x02000000, 0x00000003}, + {0x4A324E41, 0x02000000, 0x00000002}, + {0x4A324E43, 0x04000000, 0x00000005}, + {0x4A324F41, 0x08000000, 0x00000005}, + {0x4A324F42, 0x04000000, 0x00000002}, + {0x4A324F43, 0x10000000, 0x00000001}, + {0x4A324F59, 0x02000000, 0x00000002}, + {0x4A325041, 0x02000000, 0x00000001}, + {0x4A325043, 0x04000000, 0x00000003}, + {0x4A325054, 0x08000000, 0x00000002}, + {0x4A325059, 0x04000000, 0x00000005}, + {0x4A325142, 0x10000000, 0x00000003}, + {0x4A325143, 0x01000000, 0x00000003}, + {0x4A325159, 0x04000000, 0x00000002}, + {0x4A325241, 0x02000000, 0x00000005}, + {0x4A325243, 0x04000000, 0x00000002}, + {0x4A325341, 0x01000000, 0x00000001}, + {0x4A325359, 0x04000000, 0x00000005}, + {0x4A325443, 0x04000000, 0x00000002}, + {0x4A325541, 0x04000000, 0x00000001}, + {0x4A325543, 0x01000000, 0x00000002}, + {0x4A325559, 0x01000000, 0x00000005}, + {0x4A325641, 0x02000000, 0x00000001}, + {0x4A325659, 0x02000000, 0x00000002}, + {0x4A325743, 0x01000000, 0x00000001}, + {0x4A325843, 0x04000000, 0x00000003}, + {0x4A325859, 0x00800000, 0x00000002}, + {0x4A325943, 0x04000000, 0x00000001}, + {0x4A325A41, 0x02000000, 0x00000002}, + {0x4A325A42, 0x04000000, 0x00000002}, + {0x4A325A59, 0x00800000, 0x00000002}, + {0x4A333242, 0x04000000, 0x00000005}, + {0x4A333243, 0x02000000, 0x00000002}, + {0x4A333342, 0x04000000, 0x00000002}, + {0x4A333343, 0x04000000, 0x00000001}, + {0x4A333441, 0x00800000, 0x00000000}, + {0x4A333442, 0x04000000, 0x00000003}, + {0x4A333542, 0x02000000, 0x00000003}, + {0x4A333643, 0x02000000, 0x00000002}, + {0x4A334241, 0x04000000, 0x00000003}, + {0x4A334259, 0x04000000, 0x00000005}, + {0x4A334341, 0x02000000, 0x00000005}, + {0x4A334441, 0x02000000, 0x00000005}, + {0x4A334543, 0x10000000, 0x00000003}, + {0x4A334559, 0x02000000, 0x00000002}, + {0x4A334741, 0x02000000, 0x00000005}, + {0x4A334742, 0x04000000, 0x00000002}, + {0x4A334743, 0x02000000, 0x00000002}, + {0x4A334759, 0x02000000, 0x00000003}, + {0x4A334841, 0x02000000, 0x00000003}, + {0x4A334843, 0x04000000, 0x00000002}, + {0x4A334854, 0x20000000, 0x00000002}, + {0x4A334859, 0x10000000, 0x00000002}, + {0x4A334A42, 0x02000000, 0x00000005}, + {0x4A334A59, 0x04000000, 0x00000002}, + {0x4A334B41, 0x02000000, 0x00000002}, + {0x4A334B42, 0x02000000, 0x00000003}, + {0x4A334B59, 0x02000000, 0x00000003}, + {0x4A334C41, 0x02000000, 0x00000001}, + {0x4A334C42, 0x08000000, 0x00000002}, + {0x4A334C56, 0x08000000, 0x00000005}, + {0x4A334C59, 0x04000000, 0x00000002}, + {0x4A334D42, 0x08000000, 0x00000003}, + {0x4A334D43, 0x08000000, 0x00000003}, + {0x4A334D59, 0x02000000, 0x00000002}, + {0x4A334E43, 0x08000000, 0x00000002}, + {0x4A334E54, 0x20000000, 0x00000005}, + {0x4A334F43, 0x10000000, 0x00000001}, + {0x4A334F59, 0x02000000, 0x00000001}, + {0x4A335141, 0x04000000, 0x00000001}, + {0x4A335142, 0x04000000, 0x00000002}, + {0x4A335143, 0x01000000, 0x00000003}, + {0x4A335241, 0x04000000, 0x00000003}, + {0x4A335242, 0x08000000, 0x00000002}, + {0x4A335243, 0x08000000, 0x00000002}, + {0x4A335259, 0x10000000, 0x00000003}, + {0x4A335442, 0x00800000, 0x00000003}, + {0x4A335443, 0x04000000, 0x00000003}, + {0x4A335456, 0x04000000, 0x00000001}, + {0x4A335459, 0x04000000, 0x00000003}, + {0x4A335559, 0x01000000, 0x00000001}, + {0x4A335641, 0x02000000, 0x00000001}, + {0x4A335642, 0x01000000, 0x00000002}, + {0x4A335643, 0x01000000, 0x00000001}, + {0x4A335741, 0x04000000, 0x00000001}, + {0x4A335759, 0x01000000, 0x00000001}, + {0x4A335841, 0x08000000, 0x00000001}, + {0x4A335843, 0x02000000, 0x00000002}, + {0x4A335941, 0x04000000, 0x00000002}, + {0x4A335959, 0x02000000, 0x00000002}, + {0x4A335A41, 0x02000000, 0x00000002}, + {0x4A335A42, 0x08000000, 0x00000003}, + {0x4A335A43, 0x02000000, 0x00000003}, + {0x4A335A59, 0x02000000, 0x00000002}, + {0x4A343243, 0x08000000, 0x00000003}, + {0x4A343342, 0x02000000, 0x00000001}, + {0x4A343343, 0x04000000, 0x00000003}, + {0x4A343442, 0x01000000, 0x00000002}, + {0x4A343443, 0x08000000, 0x00000002}, + {0x4A343541, 0x02000000, 0x00000000}, + {0x4A343542, 0x01000000, 0x00000002}, + {0x4A343559, 0x00400000, 0x00000000}, + {0x4A343643, 0x04000000, 0x00000003}, + {0x4A343742, 0x04000000, 0x00000002}, + {0x4A344142, 0x01000000, 0x00000002}, + {0x4A344241, 0x04000000, 0x00000005}, + {0x4A344242, 0x04000000, 0x00000002}, + {0x4A344254, 0x10000000, 0x00000006}, + {0x4A344341, 0x04000000, 0x00000001}, + {0x4A344342, 0x10000000, 0x00000002}, + {0x4A344343, 0x04000000, 0x00000003}, + {0x4A344354, 0x04000000, 0x00000007}, + {0x4A344359, 0x02000000, 0x00000003}, + {0x4A344454, 0x02000000, 0x00000001}, + {0x4A344541, 0x04000000, 0x00000002}, + {0x4A344543, 0x01000000, 0x00000003}, + {0x4A344642, 0x10000000, 0x00000002}, + {0x4A344654, 0x04000000, 0x00000005}, + {0x4A344659, 0x08000000, 0x00000003}, + {0x4A344742, 0x08000000, 0x00000002}, + {0x4A344743, 0x04000000, 0x00000003}, + {0x4A344754, 0x04000000, 0x00000003}, + {0x4A344759, 0x10000000, 0x00000003}, + {0x4A344841, 0x00800000, 0x00000001}, + {0x4A344859, 0x04000000, 0x00000001}, + {0x4A344941, 0x01000000, 0x00000003}, + {0x4A344A59, 0x01000000, 0x00000002}, + {0x4A344B41, 0x02000000, 0x00000003}, + {0x4A344B42, 0x08000000, 0x00000002}, + {0x4A344B43, 0x04000000, 0x00000003}, + {0x4A344B59, 0x04000000, 0x00000002}, + {0x4A344C41, 0x00800000, 0x00000001}, + {0x4A344C42, 0x04000000, 0x00000002}, + {0x4A344C43, 0x08000000, 0x00000002}, + {0x4A344C59, 0x00800000, 0x00000002}, + {0x4A344D54, 0x04000000, 0x00000002}, + {0x4A344D59, 0x04000000, 0x00000002}, + {0x4A344E41, 0x04000000, 0x00000001}, + {0x4A344F41, 0x02000000, 0x00000002}, + {0x4A344F42, 0x04000000, 0x00000003}, + {0x4A344F43, 0x00800000, 0x00000006}, + {0x4A344F59, 0x08000000, 0x00000002}, + {0x4A345043, 0x08000000, 0x00000002}, + {0x4A345054, 0x04000000, 0x00000002}, + {0x4A345056, 0x08000000, 0x00000006}, + {0x4A345059, 0x04000000, 0x00000002}, + {0x4A345142, 0x04000000, 0x00000002}, + {0x4A345159, 0x00800000, 0x00000002}, + {0x4A345241, 0x01000000, 0x00000002}, + {0x4A345259, 0x01000000, 0x00000003}, + {0x4A345343, 0x08000000, 0x00000003}, + {0x4A345359, 0x04000000, 0x00000002}, + {0x4A345541, 0x01000000, 0x00000001}, + {0x4A345559, 0x02000000, 0x00000003}, + {0x4A345641, 0x02000000, 0x00000001}, + {0x4A345659, 0x08000000, 0x00000003}, + {0x4A345743, 0x10000000, 0x00000003}, + {0x4A345759, 0x04000000, 0x00000003}, + {0x4A345841, 0x08000000, 0x00000001}, + {0x4A345843, 0x04000000, 0x00000005}, + {0x4A345941, 0x08000000, 0x00000001}, + {0x4A345959, 0x04000000, 0x00000003}, + {0x4A345A41, 0x00800000, 0x00000002}, + {0x4A345A59, 0x02000000, 0x00000001}, + {0x4A353342, 0x04000000, 0x00000005}, + {0x4A353443, 0x01000000, 0x00000002}, + {0x4A353543, 0x04000000, 0x00000003}, + {0x4A353742, 0x01000000, 0x00000002}, + {0x4A354143, 0x08000000, 0x00000003}, + {0x4A354241, 0x02000000, 0x00000001}, + {0x4A354341, 0x02000000, 0x00000005}, + {0x4A354354, 0x02000000, 0x00000002}, + {0x4A354459, 0x00800000, 0x00000002}, + {0x4A354541, 0x01000000, 0x00000003}, + {0x4A354542, 0x04000000, 0x00000002}, + {0x4A354742, 0x04000000, 0x00000002}, + {0x4A354843, 0x04000000, 0x00000002}, + {0x4A354859, 0x04000000, 0x00000002}, + {0x4A354941, 0x04000000, 0x00000002}, + {0x4A354A43, 0x02000000, 0x00000002}, + {0x4A354B41, 0x01000000, 0x00000001}, + {0x4A354B43, 0x04000000, 0x00000005}, + {0x4A354B54, 0x00800000, 0x00000003}, + {0x4A354B56, 0x04000000, 0x00000003}, + {0x4A354C59, 0x08000000, 0x00000003}, + {0x4A354D41, 0x04000000, 0x00000005}, + {0x4A354E41, 0x01000000, 0x00000003}, + {0x4A354E43, 0x04000000, 0x00000003}, + {0x4A354F41, 0x02000000, 0x00000005}, + {0x4A354F42, 0x10000000, 0x00000005}, + {0x4A354F59, 0x04000000, 0x00000003}, + {0x4A355154, 0x04000000, 0xFFFFFFFF}, + {0x4A355159, 0x01000000, 0x00000002}, + {0x4A355442, 0x08000000, 0x00000002}, + {0x4A355543, 0x04000000, 0x00000002}, + {0x4A355559, 0x08000000, 0x00000002}, + {0x4A355641, 0x02000000, 0x00000001}, + {0x4A355643, 0x02000000, 0x00000001}, + {0x4A355659, 0x08000000, 0x00000003}, + {0x4A355741, 0x01000000, 0x00000003}, + {0x4A355841, 0x08000000, 0x00000001}, + {0x4A355941, 0x08000000, 0x00000003}, + {0x4A355959, 0x04000000, 0x00000003}, + {0x4A355A43, 0x02000000, 0x00000003}, + {0x4A355A59, 0x02000000, 0x00000002}, + {0x4A363243, 0x00800000, 0x00000002}, + {0x4A363341, 0x02000000, 0x00000000}, + {0x4A363343, 0x04000000, 0x00000001}, + {0x4A363542, 0x04000000, 0x00000005}, + {0x4A363643, 0x04000000, 0x00000002}, + {0x4A364143, 0x04000000, 0x00000002}, + {0x4A364241, 0x02000000, 0x00000001}, + {0x4A364243, 0x01000000, 0x00000002}, + {0x4A364259, 0x01000000, 0x00000002}, + {0x4A364359, 0x01000000, 0x00000003}, + {0x4A364443, 0x08000000, 0x00000003}, + {0x4A364541, 0x04000000, 0x00000003}, + {0x4A364543, 0x01000000, 0x00000002}, + {0x4A364559, 0x04000000, 0x00000003}, + {0x4A364659, 0x04000000, 0x00000003}, + {0x4A364741, 0x02000000, 0x00000002}, + {0x4A364841, 0x01000000, 0x00000001}, + {0x4A364842, 0x04000000, 0x00000002}, + {0x4A364843, 0x04000000, 0x00000001}, + {0x4A364859, 0x04000000, 0x00000001}, + {0x4A364943, 0x02000000, 0x00000003}, + {0x4A364A43, 0x08000000, 0x00000002}, + {0x4A364B42, 0x02000000, 0x00000002}, + {0x4A364B59, 0x00800000, 0x00000003}, + {0x4A364C59, 0x04000000, 0x00000001}, + {0x4A364D43, 0x08000000, 0x00000002}, + {0x4A364E43, 0x04000000, 0x00000002}, + {0x4A364F41, 0x08000000, 0x00000001}, + {0x4A364F42, 0x01000000, 0x00000002}, + {0x4A364F43, 0x04000000, 0x00000002}, + {0x4A364F59, 0x02000000, 0x00000001}, + {0x4A365141, 0x00800000, 0x00000002}, + {0x4A365142, 0x02000000, 0x00000003}, + {0x4A365241, 0x00800000, 0x00000002}, + {0x4A365243, 0x04000000, 0x00000002}, + {0x4A365341, 0x04000000, 0x00000005}, + {0x4A365359, 0x04000000, 0x00000005}, + {0x4A365443, 0x04000000, 0x00000002}, + {0x4A365459, 0x01000000, 0x00000003}, + {0x4A365559, 0x02000000, 0x00000002}, + {0x4A365641, 0x02000000, 0x00000001}, + {0x4A365659, 0x00800000, 0x00000001}, + {0x4A365759, 0x02000000, 0x00000002}, + {0x4A365841, 0x08000000, 0x00000001}, + {0x4A365843, 0x08000000, 0x00000002}, + {0x4A365941, 0x00800000, 0x00000005}, + {0x4A365A41, 0x01000000, 0x00000005}, + {0x4A365A59, 0x02000000, 0x00000002}, + {0x4A373243, 0x08000000, 0x00000003}, + {0x4A374142, 0x02000000, 0x00000002}, + {0x4A374341, 0x00800000, 0x00000002}, + {0x4A374359, 0x02000000, 0x00000002}, + {0x4A374459, 0x04000000, 0x00000002}, + {0x4A374541, 0x08000000, 0x00000002}, + {0x4A374741, 0x02000000, 0x00000002}, + {0x4A374743, 0x04000000, 0x00000002}, + {0x4A374759, 0x04000000, 0x00000002}, + {0x4A374841, 0x04000000, 0x00000002}, + {0x4A374843, 0x10000000, 0x00000003}, + {0x4A374859, 0x08000000, 0x00000001}, + {0x4A374A43, 0x04000000, 0x00000001}, + {0x4A374A54, 0x04000000, 0x00000002}, + {0x4A374A59, 0x01000000, 0x00000002}, + {0x4A374B41, 0x02000000, 0x00000005}, + {0x4A374B59, 0x01000000, 0x00000002}, + {0x4A374C41, 0x02000000, 0x00000001}, + {0x4A374C59, 0x04000000, 0x00000003}, + {0x4A374D41, 0x02000000, 0x00000002}, + {0x4A374D42, 0x04000000, 0x00000003}, + {0x4A374D59, 0x04000000, 0x00000002}, + {0x4A374E54, 0x20000000, 0x00000005}, + {0x4A374F41, 0x04000000, 0x00000002}, + {0x4A374F42, 0x01000000, 0x00000005}, + {0x4A374F59, 0x01000000, 0x00000002}, + {0x4A375141, 0x00800000, 0x00000002}, + {0x4A375241, 0x04000000, 0x00000002}, + {0x4A375259, 0x04000000, 0x00000002}, + {0x4A375341, 0x08000000, 0x00000003}, + {0x4A375342, 0x04000000, 0x00000001}, + {0x4A375343, 0x10000000, 0x00000003}, + {0x4A375541, 0x02000000, 0x00000002}, + {0x4A375641, 0x02000000, 0x00000002}, + {0x4A375659, 0x00800000, 0x00000001}, + {0x4A375741, 0x02000000, 0x00000002}, + {0x4A375841, 0x08000000, 0x00000003}, + {0x4A375859, 0x01000000, 0x00000003}, + {0x4A375941, 0x08000000, 0x00000005}, + {0x4A375A41, 0x01000000, 0x00000002}, + {0x4A375A59, 0x02000000, 0x00000001}, + {0x4A383343, 0x04000000, 0x00000005}, + {0x4A383442, 0x00800000, 0x00000002}, + {0x4A384154, 0x01000000, 0x00000001}, + {0x4A384259, 0x02000000, 0x00000003}, + {0x4A384359, 0x01000000, 0x00000002}, + {0x4A384441, 0x01000000, 0x00000002}, + {0x4A384443, 0x02000000, 0x00000002}, + {0x4A384459, 0x04000000, 0x00000003}, + {0x4A384541, 0x04000000, 0x00000002}, + {0x4A384542, 0x20000000, 0x00000003}, + {0x4A384641, 0x01000000, 0x00000002}, + {0x4A384741, 0x04000000, 0x00000003}, + {0x4A384742, 0x01000000, 0x00000003}, + {0x4A384743, 0x02000000, 0x00000002}, + {0x4A384759, 0x08000000, 0x00000005}, + {0x4A384841, 0x02000000, 0x00000001}, + {0x4A384943, 0x04000000, 0x00000002}, + {0x4A384A43, 0x04000000, 0x00000002}, + {0x4A384A54, 0x04000000, 0x00000002}, + {0x4A384B43, 0x02000000, 0x00000003}, + {0x4A384B59, 0x04000000, 0x00000003}, + {0x4A384D41, 0x01000000, 0x00000001}, + {0x4A384D43, 0x02000000, 0x00000002}, + {0x4A384D59, 0x01000000, 0x00000002}, + {0x4A384E43, 0x10000000, 0x00000003}, + {0x4A385041, 0x02000000, 0x00000005}, + {0x4A385043, 0x02000000, 0x00000002}, + {0x4A385141, 0x00800000, 0x00000002}, + {0x4A385142, 0x04000000, 0x00000002}, + {0x4A385154, 0x04000000, 0x00000003}, + {0x4A385159, 0x04000000, 0x00000003}, + {0x4A385241, 0x04000000, 0x00000002}, + {0x4A385242, 0x01000000, 0x00000001}, + {0x4A385341, 0x00800000, 0x00000002}, + {0x4A385443, 0x04000000, 0x00000003}, + {0x4A385541, 0x04000000, 0x00000002}, + {0x4A385641, 0x01000000, 0x00000001}, + {0x4A385643, 0x04000000, 0x00000002}, + {0x4A385659, 0x00800000, 0x00000001}, + {0x4A385759, 0x08000000, 0x00000005}, + {0x4A385843, 0x02000000, 0x00000002}, + {0x4A385943, 0x10000000, 0x00000003}, + {0x4A385959, 0x04000000, 0x00000002}, + {0x4A385A41, 0x00800000, 0x00000002}, + {0x4A385A59, 0x02000000, 0x00000002}, + {0x4A393243, 0x04000000, 0x00000005}, + {0x4A393256, 0x02000000, 0x00000005}, + {0x4A393341, 0x02000000, 0x00000000}, + {0x4A393342, 0x08000000, 0x00000002}, + {0x4A393441, 0x02000000, 0x00000000}, + {0x4A393443, 0x04000000, 0x00000005}, + {0x4A393542, 0x01000000, 0x00000002}, + {0x4A393543, 0x04000000, 0x00000002}, + {0x4A393741, 0x02000000, 0x00000000}, + {0x4A393842, 0x04000000, 0x00000005}, + {0x4A394142, 0x04000000, 0x00000002}, + {0x4A394154, 0x01000000, 0x00000001}, + {0x4A394241, 0x01000000, 0x00000001}, + {0x4A394243, 0x08000000, 0x00000005}, + {0x4A394441, 0x02000000, 0x00000003}, + {0x4A394443, 0x04000000, 0x00000003}, + {0x4A394541, 0x04000000, 0x00000002}, + {0x4A394559, 0x04000000, 0x00000003}, + {0x4A394741, 0x02000000, 0x00000003}, + {0x4A394742, 0x04000000, 0x00000005}, + {0x4A394743, 0x01000000, 0x00000002}, + {0x4A394842, 0x20000000, 0x00000002}, + {0x4A394843, 0x02000000, 0x00000003}, + {0x4A394859, 0x02000000, 0x00000002}, + {0x4A394941, 0x04000000, 0x00000002}, + {0x4A394A42, 0x01000000, 0x00000002}, + {0x4A394A54, 0x04000000, 0x00000002}, + {0x4A394A59, 0x00800000, 0x00000005}, + {0x4A394B41, 0x01000000, 0x00000002}, + {0x4A394B42, 0x10000000, 0x00000003}, + {0x4A394B43, 0x04000000, 0x00000005}, + {0x4A394B54, 0x08000000, 0x00000002}, + {0x4A394B59, 0x08000000, 0x00000002}, + {0x4A394C59, 0x04000000, 0x00000003}, + {0x4A394D41, 0x01000000, 0x00000002}, + {0x4A394D42, 0x04000000, 0x00000003}, + {0x4A394E41, 0x01000000, 0x00000001}, + {0x4A394E59, 0x02000000, 0x00000002}, + {0x4A394F41, 0x04000000, 0x00000002}, + {0x4A394F42, 0x04000000, 0x00000003}, + {0x4A394F59, 0x02000000, 0x00000003}, + {0x4A395041, 0x01000000, 0x00000002}, + {0x4A395059, 0x04000000, 0x00000003}, + {0x4A395141, 0x04000000, 0x00000001}, + {0x4A395142, 0x00800000, 0x00000002}, + {0x4A395143, 0x00800000, 0x00000002}, + {0x4A395241, 0x02000000, 0x00000002}, + {0x4A395243, 0x01000000, 0x00000002}, + {0x4A395259, 0x04000000, 0x00000002}, + {0x4A395359, 0x04000000, 0x00000003}, + {0x4A395541, 0x01000000, 0x00000002}, + {0x4A395559, 0x04000000, 0x00000002}, + {0x4A395659, 0x00800000, 0x00000001}, + {0x4A395841, 0x04000000, 0x00000002}, + {0x4A395843, 0x08000000, 0x00000003}, + {0x4A395859, 0x01000000, 0x00000003}, + {0x4A395941, 0x08000000, 0x00000003}, + {0x4A395959, 0x02000000, 0x00000002}, + {0x4A395A41, 0x02000000, 0x00000003}, + {0x4A395A42, 0x04000000, 0x00000002}, + {0x4A395A59, 0x02000000, 0x00000002}, + {0x4A413241, 0x04000000, 0x00000002}, + {0x4A413243, 0x08000000, 0x00000002}, + {0x4A413341, 0x04000000, 0x00000006}, + {0x4A413442, 0x01000000, 0x00000002}, + {0x4A413443, 0x04000000, 0x00000001}, + {0x4A413541, 0x04000000, 0x00000001}, + {0x4A413641, 0x02000000, 0x00000005}, + {0x4A413841, 0x00800000, 0x00000001}, + {0x4A414154, 0x02000000, 0x00000004}, + {0x4A414156, 0x02000000, 0x00000008}, + {0x4A414159, 0x04000000, 0x00000002}, + {0x4A414259, 0x02000000, 0x00000002}, + {0x4A414356, 0x04000000, 0x00000001}, + {0x4A414441, 0x04000000, 0x00000006}, + {0x4A414459, 0x02000000, 0x00000003}, + {0x4A414543, 0x02000000, 0x00000003}, + {0x4A414559, 0x02000000, 0x00000003}, + {0x4A414641, 0x04000000, 0x00000003}, + {0x4A414659, 0x02000000, 0x00000003}, + {0x4A414843, 0x04000000, 0x00000003}, + {0x4A414859, 0x01000000, 0x00000003}, + {0x4A414941, 0x04000000, 0x00000001}, + {0x4A414943, 0x08000000, 0x00000003}, + {0x4A414A41, 0x08000000, 0x00000003}, + {0x4A414A59, 0x04000000, 0x00000002}, + {0x4A414B41, 0x08000000, 0x00000005}, + {0x4A414B42, 0x08000000, 0x00000003}, + {0x4A414B59, 0x04000000, 0x00000003}, + {0x4A414C41, 0x04000000, 0x00000005}, + {0x4A414D41, 0x01000000, 0x00000002}, + {0x4A414D43, 0x08000000, 0x00000002}, + {0x4A414D59, 0x02000000, 0x00000002}, + {0x4A414E41, 0x02000000, 0x00000002}, + {0x4A414E59, 0x04000000, 0x00000002}, + {0x4A414F59, 0x02000000, 0x00000002}, + {0x4A415041, 0x04000000, 0x00000006}, + {0x4A415142, 0x01000000, 0x00000005}, + {0x4A415154, 0x08000000, 0x00000004}, + {0x4A415242, 0x04000000, 0x00000002}, + {0x4A415249, 0x10000000, 0x00000006}, + {0x4A415342, 0x04000000, 0x00000003}, + {0x4A415441, 0x01000000, 0x00000001}, + {0x4A415442, 0x08000000, 0x00000003}, + {0x4A415541, 0x04000000, 0x00000005}, + {0x4A415559, 0x04000000, 0x00000001}, + {0x4A415643, 0x04000000, 0x00000002}, + {0x4A415741, 0x04000000, 0x00000002}, + {0x4A415841, 0x08000000, 0x00000002}, + {0x4A415859, 0x04000000, 0x00000003}, + {0x4A415941, 0x00800000, 0x00000002}, + {0x4A415943, 0x04000000, 0x00000006}, + {0x4A415959, 0x02000000, 0x00000003}, + {0x4A415A41, 0x02000000, 0x00000002}, + {0x4A415A59, 0x01000000, 0x00000002}, + {0x4A423241, 0x01000000, 0x00000001}, + {0x4A423242, 0x08000000, 0x00000002}, + {0x4A423341, 0x08000000, 0x00000002}, + {0x4A423442, 0x04000000, 0x00000002}, + {0x4A423443, 0x01000000, 0x00000003}, + {0x4A423541, 0x04000000, 0x00000002}, + {0x4A423641, 0x02000000, 0x00000005}, + {0x4A424241, 0x01000000, 0x00000005}, + {0x4A424341, 0x04000000, 0x00000003}, + {0x4A424359, 0x04000000, 0x00000001}, + {0x4A424441, 0x04000000, 0x00000002}, + {0x4A424442, 0x04000000, 0x00000002}, + {0x4A424454, 0x04000000, 0x00000002}, + {0x4A424542, 0x10000000, 0x00000003}, + {0x4A424543, 0x02000000, 0x00000003}, + {0x4A424556, 0x02000000, 0x00000007}, + {0x4A424559, 0x02000000, 0x00000002}, + {0x4A424754, 0x08000000, 0x00000002}, + {0x4A424759, 0x01000000, 0x00000002}, + {0x4A424843, 0x04000000, 0x00000001}, + {0x4A424859, 0x04000000, 0x00000003}, + {0x4A424941, 0x08000000, 0x00000002}, + {0x4A424943, 0x01000000, 0x00000002}, + {0x4A424A41, 0x04000000, 0x00000005}, + {0x4A424A59, 0x04000000, 0x00000001}, + {0x4A424B41, 0x02000000, 0x00000003}, + {0x4A424B59, 0x04000000, 0x00000003}, + {0x4A424C41, 0x08000000, 0x00000003}, + {0x4A424C43, 0x04000000, 0x00000003}, + {0x4A424D41, 0x04000000, 0x00000002}, + {0x4A424E41, 0x04000000, 0x00000005}, + {0x4A424E42, 0x04000000, 0x00000003}, + {0x4A424E59, 0x04000000, 0x00000002}, + {0x4A424F42, 0x02000000, 0x00000001}, + {0x4A425041, 0x02000000, 0x00000001}, + {0x4A425059, 0x08000000, 0x00000003}, + {0x4A425141, 0x01000000, 0x00000001}, + {0x4A425142, 0x04000000, 0x00000002}, + {0x4A425154, 0x02000000, 0x00000003}, + {0x4A425241, 0x02000000, 0x00000001}, + {0x4A425243, 0x02000000, 0x00000005}, + {0x4A425249, 0x10000000, 0x00000006}, + {0x4A425259, 0x08000000, 0x00000003}, + {0x4A425341, 0x04000000, 0x00000002}, + {0x4A425441, 0x04000000, 0x00000002}, + {0x4A425442, 0x04000000, 0x00000002}, + {0x4A425459, 0x08000000, 0x00000003}, + {0x4A425541, 0x04000000, 0x00000005}, + {0x4A425643, 0x02000000, 0x00000003}, + {0x4A425659, 0x08000000, 0x00000002}, + {0x4A425841, 0x04000000, 0x00000008}, + {0x4A425859, 0x08000000, 0x00000003}, + {0x4A425941, 0x02000000, 0x00000002}, + {0x4A425959, 0x04000000, 0x00000005}, + {0x4A425A41, 0x00800000, 0x00000001}, + {0x4A425A42, 0x02000000, 0x00000003}, + {0x4A425A59, 0x02000000, 0x00000002}, + {0x4A433342, 0x04000000, 0x00000002}, + {0x4A433343, 0x02000000, 0x00000001}, + {0x4A433441, 0x01000000, 0x00000003}, + {0x4A433442, 0x08000000, 0x00000002}, + {0x4A433443, 0x01000000, 0x00000002}, + {0x4A433541, 0x01000000, 0x00000001}, + {0x4A433641, 0x02000000, 0x00000005}, + {0x4A433643, 0x10000000, 0x00000005}, + {0x4A433841, 0x02000000, 0x00000002}, + {0x4A434154, 0x02000000, 0x00000002}, + {0x4A434159, 0x04000000, 0x00000003}, + {0x4A434241, 0x02000000, 0x00000005}, + {0x4A434254, 0x00800000, 0x00000001}, + {0x4A434341, 0x02000000, 0x00000001}, + {0x4A434441, 0x01000000, 0x00000001}, + {0x4A434459, 0x08000000, 0x00000003}, + {0x4A434541, 0x00800000, 0x00000001}, + {0x4A434554, 0x08000000, 0x00000005}, + {0x4A434559, 0x02000000, 0x00000001}, + {0x4A434741, 0x04000000, 0x00000003}, + {0x4A434743, 0x04000000, 0x00000002}, + {0x4A434754, 0x04000000, 0x00000003}, + {0x4A434941, 0x01000000, 0x00000001}, + {0x4A434A41, 0x00800000, 0x00000002}, + {0x4A434B59, 0x02000000, 0x00000002}, + {0x4A434C56, 0x04000000, 0x00000002}, + {0x4A434D41, 0x02000000, 0x00000005}, + {0x4A434E41, 0x04000000, 0x00000002}, + {0x4A434E42, 0x08000000, 0x00000002}, + {0x4A434E43, 0x04000000, 0x00000002}, + {0x4A434F41, 0x01000000, 0x00000003}, + {0x4A434F42, 0x00800000, 0x00000003}, + {0x4A434F59, 0x02000000, 0x00000002}, + {0x4A435041, 0x01000000, 0x00000001}, + {0x4A435054, 0x08000000, 0x00000002}, + {0x4A435141, 0x04000000, 0x00000002}, + {0x4A435154, 0x08000000, 0x00000004}, + {0x4A435259, 0x08000000, 0x00000002}, + {0x4A435341, 0x04000000, 0x00000002}, + {0x4A435459, 0x08000000, 0x00000003}, + {0x4A435541, 0x04000000, 0x00000005}, + {0x4A435542, 0x04000000, 0x00000002}, + {0x4A435641, 0x04000000, 0x00000005}, + {0x4A435643, 0x02000000, 0x00000001}, + {0x4A435741, 0x04000000, 0x00000002}, + {0x4A435742, 0x02000000, 0x00000002}, + {0x4A435743, 0x02000000, 0x00000001}, + {0x4A435841, 0x02000000, 0x00000003}, + {0x4A435859, 0x04000000, 0x00000003}, + {0x4A435941, 0x04000000, 0x00000003}, + {0x4A435A41, 0x00800000, 0x00000001}, + {0x4A435A42, 0x02000000, 0x00000003}, + {0x4A435A43, 0x02000000, 0x00000002}, + {0x4A435A55, 0x08000000, 0xFFFFFFFF}, + {0x4A435A59, 0x01000000, 0x00000002}, + {0x4A443241, 0x02000000, 0x00000002}, + {0x4A443243, 0x04000000, 0x00000002}, + {0x4A443341, 0x08000000, 0x00000003}, + {0x4A443342, 0x04000000, 0x00000002}, + {0x4A443441, 0x04000000, 0x00000003}, + {0x4A443443, 0x04000000, 0x00000002}, + {0x4A443541, 0x00800000, 0x00000002}, + {0x4A443542, 0x04000000, 0x00000002}, + {0x4A443543, 0x02000000, 0x00000001}, + {0x4A443641, 0x04000000, 0x00000002}, + {0x4A443841, 0x04000000, 0x00000002}, + {0x4A444154, 0x08000000, 0x00000005}, + {0x4A444259, 0x08000000, 0x00000002}, + {0x4A444342, 0x04000000, 0x00000002}, + {0x4A444356, 0x04000000, 0x00000002}, + {0x4A444441, 0x01000000, 0x00000001}, + {0x4A444443, 0x04000000, 0x00000002}, + {0x4A444459, 0x01000000, 0x00000001}, + {0x4A444543, 0x04000000, 0x00000002}, + {0x4A444554, 0x02000000, 0x00000003}, + {0x4A444741, 0x02000000, 0x00000003}, + {0x4A444754, 0x10000000, 0x00000002}, + {0x4A444841, 0x04000000, 0x00000002}, + {0x4A444843, 0x08000000, 0x00000002}, + {0x4A444941, 0x02000000, 0x00000002}, + {0x4A444942, 0x08000000, 0x00000003}, + {0x4A444A41, 0x00800000, 0x00000002}, + {0x4A444A43, 0x00800000, 0x00000001}, + {0x4A444B41, 0x01000000, 0x00000002}, + {0x4A444B43, 0x02000000, 0x00000002}, + {0x4A444B54, 0x02000000, 0x00000002}, + {0x4A444B59, 0x08000000, 0x00000005}, + {0x4A444C41, 0x04000000, 0x00000005}, + {0x4A444C59, 0x04000000, 0x00000005}, + {0x4A444D59, 0x02000000, 0x00000003}, + {0x4A444E41, 0x01000000, 0x00000005}, + {0x4A444F41, 0x02000000, 0x00000003}, + {0x4A444F59, 0x04000000, 0x00000002}, + {0x4A445041, 0x01000000, 0x00000002}, + {0x4A445059, 0x02000000, 0x00000005}, + {0x4A445141, 0x02000000, 0x00000003}, + {0x4A445142, 0x04000000, 0x00000002}, + {0x4A445143, 0x01000000, 0x00000002}, + {0x4A445154, 0x02000000, 0x00000003}, + {0x4A445159, 0x02000000, 0x00000002}, + {0x4A445249, 0x20000000, 0x00000006}, + {0x4A445342, 0x04000000, 0x00000002}, + {0x4A445359, 0x04000000, 0x00000005}, + {0x4A445441, 0x01000000, 0x00000002}, + {0x4A445541, 0x04000000, 0x00000005}, + {0x4A445542, 0x01000000, 0x00000001}, + {0x4A445559, 0x01000000, 0x00000005}, + {0x4A445841, 0x01000000, 0x00000002}, + {0x4A445859, 0x02000000, 0x00000003}, + {0x4A445941, 0x04000000, 0x00000002}, + {0x4A445A43, 0x02000000, 0x00000002}, + {0x4A445A59, 0x04000000, 0x00000002}, + {0x4A453243, 0x02000000, 0x00000003}, + {0x4A453343, 0x02000000, 0x00000002}, + {0x4A453541, 0x04000000, 0x00000001}, + {0x4A453542, 0x10000000, 0x00000003}, + {0x4A453543, 0x02000000, 0x00000005}, + {0x4A453641, 0x04000000, 0x00000003}, + {0x4A453841, 0x00800000, 0x00000001}, + {0x4A454159, 0x08000000, 0x00000002}, + {0x4A454243, 0x02000000, 0x00000001}, + {0x4A454341, 0x01000000, 0x00000002}, + {0x4A454441, 0x08000000, 0x00000003}, + {0x4A454442, 0x04000000, 0x00000002}, + {0x4A454456, 0x10000000, 0x00000006}, + {0x4A454541, 0x04000000, 0x00000003}, + {0x4A454542, 0x10000000, 0x00000003}, + {0x4A454559, 0x08000000, 0x00000003}, + {0x4A454641, 0x04000000, 0x00000003}, + {0x4A454643, 0x02000000, 0x00000001}, + {0x4A454659, 0x04000000, 0x00000005}, + {0x4A454741, 0x01000000, 0x00000001}, + {0x4A454759, 0x04000000, 0x00000002}, + {0x4A454841, 0x08000000, 0x00000005}, + {0x4A454859, 0x08000000, 0x00000003}, + {0x4A454A41, 0x08000000, 0x00000003}, + {0x4A454A42, 0x02000000, 0x00000003}, + {0x4A454A43, 0x02000000, 0x00000003}, + {0x4A454B41, 0x04000000, 0x00000002}, + {0x4A454B43, 0x01000000, 0x00000002}, + {0x4A454B59, 0x04000000, 0x00000002}, + {0x4A454C41, 0x08000000, 0x00000002}, + {0x4A454C42, 0x04000000, 0x00000003}, + {0x4A454C59, 0x02000000, 0x00000001}, + {0x4A454D41, 0x02000000, 0x00000002}, + {0x4A454D42, 0x10000000, 0x00000003}, + {0x4A454D43, 0x04000000, 0x00000002}, + {0x4A454D59, 0x00800000, 0x00000002}, + {0x4A454E41, 0x04000000, 0x00000002}, + {0x4A454E43, 0x02000000, 0x00000002}, + {0x4A454F41, 0x04000000, 0x00000003}, + {0x4A454F42, 0x20000000, 0x00000003}, + {0x4A454F43, 0x01000000, 0x00000002}, + {0x4A455041, 0x04000000, 0x00000001}, + {0x4A455043, 0x02000000, 0x00000002}, + {0x4A455059, 0x04000000, 0x00000002}, + {0x4A455241, 0x02000000, 0x00000001}, + {0x4A455249, 0x20000000, 0x00000006}, + {0x4A455259, 0x02000000, 0x00000002}, + {0x4A455341, 0x04000000, 0x00000002}, + {0x4A455343, 0x04000000, 0x00000002}, + {0x4A455441, 0x02000000, 0x00000001}, + {0x4A455541, 0x04000000, 0x00000005}, + {0x4A455643, 0x04000000, 0x00000002}, + {0x4A455741, 0x04000000, 0x00000005}, + {0x4A455759, 0x01000000, 0x00000002}, + {0x4A455841, 0x00800000, 0x00000002}, + {0x4A455859, 0x02000000, 0x00000003}, + {0x4A455941, 0x04000000, 0x00000002}, + {0x4A455A41, 0x04000000, 0x00000006}, + {0x4A455A59, 0x02000000, 0x00000003}, + {0x4A463241, 0x08000000, 0x00000003}, + {0x4A463243, 0x08000000, 0x00000002}, + {0x4A463341, 0x04000000, 0x00000005}, + {0x4A463442, 0x04000000, 0x00000003}, + {0x4A463443, 0x01000000, 0x00000003}, + {0x4A463541, 0x04000000, 0x00000003}, + {0x4A463542, 0x04000000, 0x00000005}, + {0x4A463543, 0x04000000, 0x00000002}, + {0x4A463641, 0x08000000, 0x00000003}, + {0x4A463643, 0x10000000, 0x00000002}, + {0x4A463841, 0x00800000, 0x00000001}, + {0x4A464241, 0x01000000, 0x00000005}, + {0x4A464254, 0x04000000, 0x00000003}, + {0x4A464259, 0x08000000, 0x00000003}, + {0x4A464341, 0x04000000, 0x00000002}, + {0x4A464443, 0x04000000, 0x00000002}, + {0x4A464641, 0x08000000, 0x00000003}, + {0x4A464741, 0x04000000, 0x00000002}, + {0x4A464842, 0x10000000, 0x00000003}, + {0x4A464941, 0x04000000, 0x00000002}, + {0x4A464B41, 0x00800000, 0x00000001}, + {0x4A464B54, 0x04000000, 0x00000005}, + {0x4A464B59, 0x02000000, 0x00000001}, + {0x4A464C42, 0x10000000, 0x00000003}, + {0x4A464D44, 0x02000000, 0xFFFFFFFF}, + {0x4A464F41, 0x02000000, 0x00000003}, + {0x4A464F59, 0x02000000, 0x00000003}, + {0x4A465041, 0x04000000, 0x00000002}, + {0x4A465141, 0x04000000, 0x00000002}, + {0x4A465142, 0x04000000, 0x00000002}, + {0x4A465143, 0x02000000, 0x00000008}, + {0x4A465154, 0x02000000, 0x00000003}, + {0x4A465241, 0x08000000, 0x00000003}, + {0x4A465242, 0x08000000, 0x00000003}, + {0x4A465341, 0x02000000, 0x00000005}, + {0x4A465459, 0x08000000, 0x00000003}, + {0x4A465541, 0x04000000, 0x00000002}, + {0x4A465559, 0x04000000, 0x00000002}, + {0x4A465641, 0x01000000, 0x00000002}, + {0x4A465759, 0x02000000, 0x00000003}, + {0x4A465841, 0x08000000, 0x00000003}, + {0x4A465859, 0x02000000, 0x00000003}, + {0x4A465A59, 0x02000000, 0x00000002}, + {0x4A473241, 0x02000000, 0x00000003}, + {0x4A473243, 0x04000000, 0x00000002}, + {0x4A473256, 0x02000000, 0x00000006}, + {0x4A473341, 0x04000000, 0x00000005}, + {0x4A473342, 0x04000000, 0x00000002}, + {0x4A473441, 0x02000000, 0x00000002}, + {0x4A473442, 0x08000000, 0x00000002}, + {0x4A473443, 0x10000000, 0x00000003}, + {0x4A473542, 0x04000000, 0x00000006}, + {0x4A473543, 0x01000000, 0x00000002}, + {0x4A473641, 0x04000000, 0x00000002}, + {0x4A473643, 0x01000000, 0x00000003}, + {0x4A473841, 0x04000000, 0x00000002}, + {0x4A474342, 0x04000000, 0x00000002}, + {0x4A474343, 0x10000000, 0x00000003}, + {0x4A474356, 0x04000000, 0x00000002}, + {0x4A474441, 0x02000000, 0x00000005}, + {0x4A474442, 0x10000000, 0x00000002}, + {0x4A474443, 0x04000000, 0x00000006}, + {0x4A474543, 0x10000000, 0x00000003}, + {0x4A474559, 0x04000000, 0x00000003}, + {0x4A474643, 0x02000000, 0x00000002}, + {0x4A474741, 0x02000000, 0x00000002}, + {0x4A474743, 0x02000000, 0x00000002}, + {0x4A474841, 0x02000000, 0x00000003}, + {0x4A474843, 0x10000000, 0x00000003}, + {0x4A474854, 0x04000000, 0x00000002}, + {0x4A474859, 0x04000000, 0x00000003}, + {0x4A474941, 0x04000000, 0x00000003}, + {0x4A474943, 0x01000000, 0x00000002}, + {0x4A474A41, 0x00800000, 0x00000005}, + {0x4A474A59, 0x04000000, 0x00000002}, + {0x4A474B41, 0x02000000, 0x00000002}, + {0x4A474B54, 0x04000000, 0x00000002}, + {0x4A474B56, 0x02000000, 0x00000005}, + {0x4A474B59, 0x10000000, 0x00000003}, + {0x4A474C41, 0x04000000, 0x00000001}, + {0x4A474D41, 0x01000000, 0x00000001}, + {0x4A474E41, 0x08000000, 0x00000005}, + {0x4A474E42, 0x04000000, 0x00000005}, + {0x4A474E59, 0x08000000, 0x00000003}, + {0x4A474F59, 0x08000000, 0x00000003}, + {0x4A475041, 0x01000000, 0x00000001}, + {0x4A475043, 0x02000000, 0x00000003}, + {0x4A475049, 0x08000000, 0x00000006}, + {0x4A475054, 0x10000000, 0x00000003}, + {0x4A475056, 0x08000000, 0x00000002}, + {0x4A475141, 0x04000000, 0x00000002}, + {0x4A475143, 0x04000000, 0x00000002}, + {0x4A475154, 0x04000000, 0x00000004}, + {0x4A475241, 0x02000000, 0x00000005}, + {0x4A475242, 0x04000000, 0x00000002}, + {0x4A475254, 0x08000000, 0x00000002}, + {0x4A475259, 0x04000000, 0x00000002}, + {0x4A475341, 0x02000000, 0x00000005}, + {0x4A475343, 0x08000000, 0x00000003}, + {0x4A475441, 0x00800000, 0x00000002}, + {0x4A475442, 0x10000000, 0x00000003}, + {0x4A475443, 0x10000000, 0x00000003}, + {0x4A475459, 0x08000000, 0x00000003}, + {0x4A475559, 0x02000000, 0x00000003}, + {0x4A475641, 0x04000000, 0x00000002}, + {0x4A475659, 0x08000000, 0x00000002}, + {0x4A475741, 0x08000000, 0x00000005}, + {0x4A475743, 0x01000000, 0x00000002}, + {0x4A475859, 0x02000000, 0x00000003}, + {0x4A475941, 0x04000000, 0x00000002}, + {0x4A475942, 0x02000000, 0x00000002}, + {0x4A475943, 0x04000000, 0x00000001}, + {0x4A475959, 0x04000000, 0x00000002}, + {0x4A475A41, 0x01000000, 0x00000003}, + {0x4A475A59, 0x02000000, 0x00000002}, + {0x4A483241, 0x01000000, 0x00000005}, + {0x4A483342, 0x04000000, 0x00000002}, + {0x4A483441, 0x02000000, 0x00000002}, + {0x4A483443, 0x08000000, 0x00000002}, + {0x4A483641, 0x02000000, 0x00000002}, + {0x4A483643, 0x01000000, 0x00000001}, + {0x4A483841, 0x00800000, 0x00000001}, + {0x4A484241, 0x08000000, 0x00000002}, + {0x4A484341, 0x04000000, 0x00000005}, + {0x4A484354, 0x04000000, 0x00000002}, + {0x4A484359, 0x04000000, 0x00000005}, + {0x4A484441, 0x04000000, 0x00000005}, + {0x4A484443, 0x01000000, 0x00000002}, + {0x4A484541, 0x04000000, 0x00000002}, + {0x4A484543, 0x08000000, 0x00000002}, + {0x4A484641, 0x01000000, 0x00000002}, + {0x4A484759, 0x08000000, 0x00000001}, + {0x4A484843, 0x01000000, 0x00000003}, + {0x4A484859, 0x02000000, 0x00000002}, + {0x4A484941, 0x08000000, 0x00000002}, + {0x4A484A41, 0x01000000, 0x00000002}, + {0x4A484A43, 0x04000000, 0x00000003}, + {0x4A484A54, 0x04000000, 0x00000005}, + {0x4A484A59, 0x01000000, 0x00000002}, + {0x4A484B41, 0x04000000, 0x00000002}, + {0x4A484B42, 0x04000000, 0x00000003}, + {0x4A484B59, 0x08000000, 0x00000005}, + {0x4A484C41, 0x02000000, 0x00000001}, + {0x4A484C59, 0x04000000, 0x00000002}, + {0x4A484D41, 0x04000000, 0x00000005}, + {0x4A484D59, 0x04000000, 0x00000003}, + {0x4A484E41, 0x08000000, 0x00000006}, + {0x4A484E42, 0x01000000, 0x00000002}, + {0x4A484E59, 0x02000000, 0x00000003}, + {0x4A484F41, 0x02000000, 0x00000003}, + {0x4A484F42, 0x00800000, 0x00000003}, + {0x4A484F43, 0x10000000, 0x00000002}, + {0x4A484F59, 0x02000000, 0x00000002}, + {0x4A485041, 0x02000000, 0x00000003}, + {0x4A485042, 0x02000000, 0x00000005}, + {0x4A485054, 0x04000000, 0x00000005}, + {0x4A485141, 0x04000000, 0x00000002}, + {0x4A485143, 0x04000000, 0x00000001}, + {0x4A485154, 0x08000000, 0x00000004}, + {0x4A485159, 0x01000000, 0x00000002}, + {0x4A485242, 0x08000000, 0x00000002}, + {0x4A485259, 0x02000000, 0x00000001}, + {0x4A485341, 0x02000000, 0x00000002}, + {0x4A485343, 0x02000000, 0x00000002}, + {0x4A485443, 0x01000000, 0x00000002}, + {0x4A485459, 0x08000000, 0x00000003}, + {0x4A485541, 0x01000000, 0x00000001}, + {0x4A485543, 0x02000000, 0x00000003}, + {0x4A485659, 0x01000000, 0x00000003}, + {0x4A485841, 0x01000000, 0x00000003}, + {0x4A485856, 0x08000000, 0x00000002}, + {0x4A485859, 0x02000000, 0x00000003}, + {0x4A485941, 0x04000000, 0x00000002}, + {0x4A485A41, 0x04000000, 0x00000002}, + {0x4A493241, 0x01000000, 0x00000005}, + {0x4A493341, 0x08000000, 0x00000002}, + {0x4A493342, 0x04000000, 0x00000002}, + {0x4A493442, 0x08000000, 0x00000005}, + {0x4A493443, 0x04000000, 0x00000002}, + {0x4A493543, 0x04000000, 0x00000002}, + {0x4A493641, 0x08000000, 0x00000003}, + {0x4A493841, 0x02000000, 0x00000002}, + {0x4A494143, 0x02000000, 0x00000002}, + {0x4A494241, 0x00800000, 0x00000005}, + {0x4A494259, 0x04000000, 0x00000002}, + {0x4A494341, 0x01000000, 0x00000002}, + {0x4A494441, 0x08000000, 0x00000001}, + {0x4A494459, 0x04000000, 0x00000002}, + {0x4A494555, 0x04000000, 0x00000002}, + {0x4A494559, 0x04000000, 0x00000002}, + {0x4A494643, 0x08000000, 0x00000003}, + {0x4A494841, 0x04000000, 0x00000003}, + {0x4A494843, 0x10000000, 0x00000003}, + {0x4A494859, 0x04000000, 0x00000001}, + {0x4A494941, 0x01000000, 0x00000002}, + {0x4A494959, 0x00800000, 0x00000001}, + {0x4A494B42, 0x08000000, 0x00000007}, + {0x4A494B59, 0x04000000, 0x00000003}, + {0x4A494C42, 0x04000000, 0x00000003}, + {0x4A494C59, 0x04000000, 0x00000002}, + {0x4A494D41, 0x00800000, 0x00000002}, + {0x4A494E41, 0x08000000, 0x00000005}, + {0x4A494F41, 0x02000000, 0x00000006}, + {0x4A494F43, 0x10000000, 0x00000002}, + {0x4A495041, 0x04000000, 0x00000005}, + {0x4A495059, 0x01000000, 0x00000003}, + {0x4A495141, 0x02000000, 0x00000005}, + {0x4A495142, 0x08000000, 0x00000002}, + {0x4A495143, 0x01000000, 0x00000002}, + {0x4A495241, 0x01000000, 0x00000001}, + {0x4A495242, 0x04000000, 0x00000001}, + {0x4A495243, 0x02000000, 0x00000002}, + {0x4A495341, 0x02000000, 0x00000002}, + {0x4A495441, 0x01000000, 0x00000008}, + {0x4A495459, 0x08000000, 0x00000003}, + {0x4A495559, 0x01000000, 0x00000002}, + {0x4A495641, 0x02000000, 0x00000001}, + {0x4A495642, 0x04000000, 0x00000002}, + {0x4A495643, 0x04000000, 0x00000002}, + {0x4A495659, 0x08000000, 0x00000003}, + {0x4A495741, 0x08000000, 0x00000005}, + {0x4A495759, 0x02000000, 0x00000002}, + {0x4A495841, 0x02000000, 0x00000002}, + {0x4A495843, 0x04000000, 0x00000005}, + {0x4A495859, 0x02000000, 0x00000003}, + {0x4A495941, 0x01000000, 0x00000001}, + {0x4A495A41, 0x00800000, 0x00000002}, + {0x4A495A59, 0x01000000, 0x00000002}, + {0x4A4A3241, 0x04000000, 0x00000003}, + {0x4A4A3242, 0x10000000, 0x00000003}, + {0x4A4A3343, 0x10000000, 0x00000003}, + {0x4A4A3441, 0x00800000, 0x00000002}, + {0x4A4A3543, 0x01000000, 0x00000002}, + {0x4A4A3641, 0x04000000, 0x00000002}, + {0x4A4A3842, 0x10000000, 0x00000005}, + {0x4A4A4241, 0x04000000, 0x00000005}, + {0x4A4A4242, 0x04000000, 0x00000003}, + {0x4A4A4441, 0x04000000, 0x00000005}, + {0x4A4A4541, 0x02000000, 0x00000002}, + {0x4A4A4659, 0x04000000, 0x00000003}, + {0x4A4A4843, 0x04000000, 0x00000002}, + {0x4A4A4859, 0x00800000, 0x00000003}, + {0x4A4A4941, 0x02000000, 0x00000003}, + {0x4A4A4A59, 0x04000000, 0x00000002}, + {0x4A4A4B41, 0x01000000, 0x00000003}, + {0x4A4A4B42, 0x01000000, 0x00000002}, + {0x4A4A4B59, 0x08000000, 0x00000002}, + {0x4A4A4C43, 0x08000000, 0x00000002}, + {0x4A4A4D41, 0x02000000, 0x00000005}, + {0x4A4A4D59, 0x04000000, 0x00000001}, + {0x4A4A4F41, 0x02000000, 0x00000002}, + {0x4A4A4F42, 0x04000000, 0x00000002}, + {0x4A4A4F59, 0x01000000, 0x00000002}, + {0x4A4A5041, 0x04000000, 0x00000005}, + {0x4A4A5059, 0x04000000, 0x00000005}, + {0x4A4A5142, 0x02000000, 0x00000003}, + {0x4A4A5154, 0x04000000, 0x00000003}, + {0x4A4A5241, 0x08000000, 0x00000003}, + {0x4A4A5242, 0x08000000, 0x00000003}, + {0x4A4A5341, 0x04000000, 0x00000005}, + {0x4A4A5343, 0x08000000, 0x00000002}, + {0x4A4A5443, 0x08000000, 0x00000002}, + {0x4A4A5559, 0x04000000, 0x00000001}, + {0x4A4A5641, 0x04000000, 0x00000002}, + {0x4A4A5643, 0x04000000, 0x00000002}, + {0x4A4A5841, 0x04000000, 0x00000003}, + {0x4A4A5859, 0x08000000, 0x00000005}, + {0x4A4A5941, 0x02000000, 0x00000005}, + {0x4A4A5943, 0x04000000, 0x00000002}, + {0x4A4A5959, 0x01000000, 0x00000002}, + {0x4A4A5A59, 0x01000000, 0x00000002}, + {0x4A4B3241, 0x04000000, 0x00000005}, + {0x4A4B3242, 0x20000000, 0x00000003}, + {0x4A4B3341, 0x00800000, 0x00000003}, + {0x4A4B3343, 0x00800000, 0x00000003}, + {0x4A4B3441, 0x00800000, 0x00000002}, + {0x4A4B3442, 0x01000000, 0x00000002}, + {0x4A4B3541, 0x01000000, 0x00000003}, + {0x4A4B3542, 0x04000000, 0x00000002}, + {0x4A4B3543, 0x04000000, 0x00000002}, + {0x4A4B3641, 0x08000000, 0x00000003}, + {0x4A4B3643, 0x04000000, 0x00000002}, + {0x4A4B3742, 0x04000000, 0x00000002}, + {0x4A4B3743, 0x04000000, 0x00000002}, + {0x4A4B3841, 0x02000000, 0x00000003}, + {0x4A4B4154, 0x04000000, 0x00000002}, + {0x4A4B4241, 0x01000000, 0x00000001}, + {0x4A4B4243, 0x04000000, 0x00000002}, + {0x4A4B4341, 0x02000000, 0x00000005}, + {0x4A4B4342, 0x04000000, 0x00000002}, + {0x4A4B4354, 0x02000000, 0x00000001}, + {0x4A4B4441, 0x04000000, 0x00000005}, + {0x4A4B4443, 0x01000000, 0x00000002}, + {0x4A4B4459, 0x01000000, 0x00000002}, + {0x4A4B4542, 0x08000000, 0x00000003}, + {0x4A4B4543, 0x04000000, 0x00000002}, + {0x4A4B4559, 0x08000000, 0x00000005}, + {0x4A4B4659, 0x04000000, 0x00000002}, + {0x4A4B4743, 0x02000000, 0x00000001}, + {0x4A4B4754, 0x04000000, 0x00000001}, + {0x4A4B4841, 0x04000000, 0x00000003}, + {0x4A4B4842, 0x01000000, 0x00000002}, + {0x4A4B4859, 0x01000000, 0x00000002}, + {0x4A4B4941, 0x02000000, 0x00000002}, + {0x4A4B4942, 0x04000000, 0x00000005}, + {0x4A4B4943, 0x04000000, 0x00000001}, + {0x4A4B4959, 0x02000000, 0x00000005}, + {0x4A4B4A41, 0x08000000, 0x00000002}, + {0x4A4B4A42, 0x01000000, 0x00000002}, + {0x4A4B4A43, 0x08000000, 0x00000003}, + {0x4A4B4B41, 0x01000000, 0x00000003}, + {0x4A4B4B42, 0x08000000, 0x00000003}, + {0x4A4B4B43, 0x10000000, 0x00000002}, + {0x4A4B4B59, 0x02000000, 0x00000002}, + {0x4A4B4C41, 0x08000000, 0x00000003}, + {0x4A4B4C59, 0x02000000, 0x00000002}, + {0x4A4B4D41, 0x00800000, 0x00000002}, + {0x4A4B4D54, 0x04000000, 0x00000002}, + {0x4A4B4D59, 0x08000000, 0x00000001}, + {0x4A4B4E41, 0x00800000, 0x00000001}, + {0x4A4B4E42, 0x02000000, 0x00000003}, + {0x4A4B4E43, 0x04000000, 0x00000002}, + {0x4A4B4E59, 0x04000000, 0x00000002}, + {0x4A4B4F42, 0x10000000, 0x00000002}, + {0x4A4B4F43, 0x00800000, 0x00000002}, + {0x4A4B4F59, 0x01000000, 0x00000002}, + {0x4A4B5041, 0x02000000, 0x00000005}, + {0x4A4B5049, 0x08000000, 0x00000006}, + {0x4A4B5059, 0x04000000, 0x00000002}, + {0x4A4B5141, 0x02000000, 0x00000002}, + {0x4A4B5154, 0x02000000, 0x00000003}, + {0x4A4B5241, 0x04000000, 0x00000002}, + {0x4A4B5341, 0x04000000, 0x00000002}, + {0x4A4B5342, 0x08000000, 0x00000003}, + {0x4A4B5343, 0x08000000, 0x00000003}, + {0x4A4B5359, 0x08000000, 0x00000003}, + {0x4A4B5441, 0x04000000, 0x00000002}, + {0x4A4B5443, 0x08000000, 0x00000002}, + {0x4A4B5459, 0x04000000, 0x00000003}, + {0x4A4B5541, 0x01000000, 0x00000001}, + {0x4A4B5542, 0x08000000, 0x00000002}, + {0x4A4B5543, 0x08000000, 0x00000002}, + {0x4A4B5641, 0x01000000, 0x00000001}, + {0x4A4B5743, 0x02000000, 0x00000003}, + {0x4A4B5841, 0x01000000, 0x00000002}, + {0x4A4B5859, 0x08000000, 0x00000005}, + {0x4A4B5941, 0x02000000, 0x00000005}, + {0x4A4B5959, 0x04000000, 0x00000002}, + {0x4A4B5A41, 0x00800000, 0x00000002}, + {0x4A4B5A42, 0x02000000, 0x00000003}, + {0x4A4B5A43, 0x04000000, 0x00000002}, + {0x4A4B5A59, 0x10000000, 0x00000003}, + {0x4A4C3243, 0x04000000, 0x00000002}, + {0x4A4C3341, 0x00800000, 0x00000002}, + {0x4A4C3342, 0x20000000, 0x00000003}, + {0x4A4C3441, 0x01000000, 0x00000002}, + {0x4A4C3442, 0x02000000, 0x00000002}, + {0x4A4C3641, 0x00800000, 0x00000002}, + {0x4A4C4142, 0x10000000, 0x00000003}, + {0x4A4C4159, 0x02000000, 0x00000003}, + {0x4A4C4241, 0x08000000, 0x00000002}, + {0x4A4C4341, 0x04000000, 0x00000003}, + {0x4A4C4342, 0x01000000, 0x00000002}, + {0x4A4C4441, 0x04000000, 0x00000003}, + {0x4A4C4541, 0x04000000, 0x00000002}, + {0x4A4C4542, 0x02000000, 0x00000002}, + {0x4A4C4559, 0x02000000, 0x00000001}, + {0x4A4C4654, 0x08000000, 0x00000003}, + {0x4A4C4659, 0x04000000, 0x00000003}, + {0x4A4C4741, 0x02000000, 0x00000001}, + {0x4A4C4841, 0x01000000, 0x00000003}, + {0x4A4C4843, 0x04000000, 0x00000002}, + {0x4A4C4854, 0x20000000, 0x00000002}, + {0x4A4C4859, 0x08000000, 0x00000003}, + {0x4A4C4941, 0x00800000, 0x00000002}, + {0x4A4C4943, 0x02000000, 0x00000001}, + {0x4A4C4959, 0x10000000, 0x00000002}, + {0x4A4C4B41, 0x04000000, 0x00000005}, + {0x4A4C4B42, 0x10000000, 0x00000002}, + {0x4A4C4C41, 0x00800000, 0x00000003}, + {0x4A4C4C59, 0x00800000, 0x00000002}, + {0x4A4C4E43, 0x04000000, 0x00000001}, + {0x4A4C4F42, 0x01000000, 0x00000003}, + {0x4A4C4F43, 0x08000000, 0x00000003}, + {0x4A4C4F59, 0x08000000, 0x00000002}, + {0x4A4C5041, 0x00800000, 0x00000002}, + {0x4A4C5056, 0x08000000, 0x00000006}, + {0x4A4C5154, 0x02000000, 0x00000003}, + {0x4A4C5241, 0x01000000, 0x00000005}, + {0x4A4C5342, 0x02000000, 0x00000003}, + {0x4A4C5359, 0x10000000, 0x00000005}, + {0x4A4C5559, 0x04000000, 0x00000002}, + {0x4A4C5641, 0x02000000, 0x00000002}, + {0x4A4C5642, 0x04000000, 0x00000002}, + {0x4A4C5659, 0x04000000, 0x00000003}, + {0x4A4C5741, 0x08000000, 0x00000003}, + {0x4A4C5759, 0x02000000, 0x00000001}, + {0x4A4C5859, 0x08000000, 0x00000005}, + {0x4A4C5A41, 0x08000000, 0x00000007}, + {0x4A4C5A59, 0x08000000, 0x00000001}, + {0x4A4D3341, 0x08000000, 0x00000002}, + {0x4A4D3541, 0x02000000, 0x00000002}, + {0x4A4D3842, 0x10000000, 0x00000005}, + {0x4A4D4241, 0x00800000, 0x00000001}, + {0x4A4D4259, 0x01000000, 0x00000002}, + {0x4A4D4341, 0x01000000, 0x00000001}, + {0x4A4D4354, 0x04000000, 0x00000002}, + {0x4A4D4441, 0x02000000, 0x00000005}, + {0x4A4D4541, 0x08000000, 0x00000003}, + {0x4A4D4559, 0x02000000, 0x00000003}, + {0x4A4D4641, 0x04000000, 0x00000002}, + {0x4A4D4643, 0x04000000, 0x00000003}, + {0x4A4D4659, 0x04000000, 0x00000003}, + {0x4A4D4743, 0x08000000, 0x00000003}, + {0x4A4D4759, 0x04000000, 0x00000002}, + {0x4A4D4841, 0x02000000, 0x00000002}, + {0x4A4D4854, 0x10000000, 0x00000005}, + {0x4A4D4859, 0x02000000, 0x00000002}, + {0x4A4D4941, 0x01000000, 0x00000005}, + {0x4A4D4942, 0x04000000, 0x00000005}, + {0x4A4D4956, 0x10000000, 0x00000003}, + {0x4A4D4A41, 0x01000000, 0x00000003}, + {0x4A4D4A42, 0x04000000, 0x00000001}, + {0x4A4D4B41, 0x08000000, 0x00000003}, + {0x4A4D4B42, 0x02000000, 0x00000002}, + {0x4A4D4B43, 0x01000000, 0x00000003}, + {0x4A4D4B54, 0x04000000, 0x00000005}, + {0x4A4D4B59, 0x01000000, 0x00000005}, + {0x4A4D4C43, 0x08000000, 0x00000003}, + {0x4A4D4D41, 0x00800000, 0x00000001}, + {0x4A4D4D43, 0x02000000, 0x00000003}, + {0x4A4D4D56, 0x04000000, 0x00000003}, + {0x4A4D4E41, 0x02000000, 0x00000005}, + {0x4A4D4E59, 0x01000000, 0x00000002}, + {0x4A4D4F41, 0x01000000, 0x00000002}, + {0x4A4D4F59, 0x04000000, 0x00000002}, + {0x4A4D5041, 0x01000000, 0x00000001}, + {0x4A4D5043, 0x04000000, 0x00000002}, + {0x4A4D5142, 0x01000000, 0x00000001}, + {0x4A4D5154, 0x08000000, 0x00000004}, + {0x4A4D5159, 0x04000000, 0x00000002}, + {0x4A4D5241, 0x04000000, 0x00000002}, + {0x4A4D5242, 0x01000000, 0x00000002}, + {0x4A4D5243, 0x02000000, 0x00000003}, + {0x4A4D5341, 0x01000000, 0x00000002}, + {0x4A4D5359, 0x08000000, 0x00000003}, + {0x4A4D5441, 0x08000000, 0x00000002}, + {0x4A4D5443, 0x04000000, 0x00000002}, + {0x4A4D5459, 0x04000000, 0x00000002}, + {0x4A4D5541, 0x02000000, 0x00000005}, + {0x4A4D5543, 0x02000000, 0x00000002}, + {0x4A4D5559, 0x00800000, 0x00000002}, + {0x4A4D5641, 0x04000000, 0x00000006}, + {0x4A4D5743, 0x10000000, 0x00000003}, + {0x4A4D5843, 0x04000000, 0x00000003}, + {0x4A4D5859, 0x02000000, 0x00000003}, + {0x4A4D5941, 0x01000000, 0x00000003}, + {0x4A4D5942, 0x04000000, 0x00000002}, + {0x4A4D5943, 0x02000000, 0x00000002}, + {0x4A4D5959, 0x10000000, 0x00000003}, + {0x4A4D5A41, 0x01000000, 0x00000002}, + {0x4A4D5A42, 0x04000000, 0x00000006}, + {0x4A4D5A59, 0x01000000, 0x00000002}, + {0x4A4E3242, 0x02000000, 0x00000001}, + {0x4A4E3343, 0x04000000, 0x00000003}, + {0x4A4E3441, 0x00800000, 0x00000002}, + {0x4A4E3442, 0x00800000, 0x00000002}, + {0x4A4E3443, 0x04000000, 0x00000003}, + {0x4A4E3641, 0x08000000, 0x00000003}, + {0x4A4E3841, 0x02000000, 0x00000005}, + {0x4A4E4156, 0x02000000, 0x00000007}, + {0x4A4E4159, 0x04000000, 0x00000002}, + {0x4A4E4241, 0x04000000, 0x00000002}, + {0x4A4E4259, 0x02000000, 0x00000007}, + {0x4A4E4341, 0x01000000, 0x00000002}, + {0x4A4E4342, 0x08000000, 0x00000005}, + {0x4A4E4359, 0x08000000, 0x00000001}, + {0x4A4E4441, 0x04000000, 0x00000003}, + {0x4A4E4442, 0x04000000, 0x00000003}, + {0x4A4E4459, 0x04000000, 0x00000002}, + {0x4A4E4541, 0x04000000, 0x00000002}, + {0x4A4E4554, 0x20000000, 0x00000002}, + {0x4A4E4641, 0x02000000, 0x00000002}, + {0x4A4E4643, 0x04000000, 0x00000002}, + {0x4A4E4842, 0x10000000, 0x00000002}, + {0x4A4E4859, 0x04000000, 0x00000003}, + {0x4A4E4941, 0x04000000, 0x00000002}, + {0x4A4E4943, 0x08000000, 0x00000002}, + {0x4A4E4959, 0x00800000, 0x00000001}, + {0x4A4E4A41, 0x02000000, 0x00000002}, + {0x4A4E4A59, 0x04000000, 0x00000002}, + {0x4A4E4B41, 0x01000000, 0x00000001}, + {0x4A4E4B43, 0x08000000, 0x00000002}, + {0x4A4E4B54, 0x04000000, 0x00000002}, + {0x4A4E4B56, 0x02000000, 0x00000003}, + {0x4A4E4B59, 0x01000000, 0x00000002}, + {0x4A4E4D41, 0x01000000, 0x00000005}, + {0x4A4E4E41, 0x04000000, 0x00000003}, + {0x4A4E4E42, 0x04000000, 0x00000002}, + {0x4A4E4E59, 0x08000000, 0x00000003}, + {0x4A4E4F41, 0x02000000, 0x00000005}, + {0x4A4E4F42, 0x08000000, 0x00000003}, + {0x4A4E4F43, 0x01000000, 0x00000005}, + {0x4A4E4F59, 0x01000000, 0x00000003}, + {0x4A4E5041, 0x02000000, 0x00000001}, + {0x4A4E5141, 0x01000000, 0x00000002}, + {0x4A4E5143, 0x02000000, 0x00000002}, + {0x4A4E5154, 0x04000000, 0x00000000}, + {0x4A4E5159, 0x04000000, 0x00000002}, + {0x4A4E5241, 0x01000000, 0x00000001}, + {0x4A4E5341, 0x00800000, 0x00000002}, + {0x4A4E5459, 0x08000000, 0x00000003}, + {0x4A4E5541, 0x00800000, 0x00000002}, + {0x4A4E5543, 0x10000000, 0x00000003}, + {0x4A4E5559, 0x04000000, 0x00000003}, + {0x4A4E5641, 0x08000000, 0x00000002}, + {0x4A4E5741, 0x08000000, 0x00000002}, + {0x4A4E5742, 0x02000000, 0x00000002}, + {0x4A4E5743, 0x04000000, 0x00000002}, + {0x4A4E5841, 0x00800000, 0x00000002}, + {0x4A4E5859, 0x02000000, 0x00000003}, + {0x4A4E5941, 0x04000000, 0x00000003}, + {0x4A4E5942, 0x04000000, 0x00000003}, + {0x4A4E5959, 0x02000000, 0x00000001}, + {0x4A4E5A59, 0x04000000, 0x00000002}, + {0x4A4F3241, 0x04000000, 0x00000003}, + {0x4A4F3242, 0x02000000, 0x00000005}, + {0x4A4F3341, 0x00800000, 0x00000001}, + {0x4A4F3343, 0x08000000, 0x00000002}, + {0x4A4F3441, 0x02000000, 0x00000005}, + {0x4A4F3641, 0x02000000, 0x00000002}, + {0x4A4F3643, 0x08000000, 0x00000003}, + {0x4A4F4242, 0x00800000, 0x00000001}, + {0x4A4F4243, 0x02000000, 0x00000005}, + {0x4A4F4341, 0x04000000, 0x00000005}, + {0x4A4F4359, 0x04000000, 0x00000001}, + {0x4A4F4459, 0x02000000, 0x00000002}, + {0x4A4F4541, 0x02000000, 0x00000001}, + {0x4A4F4559, 0x04000000, 0x00000003}, + {0x4A4F4641, 0x04000000, 0x00000003}, + {0x4A4F4741, 0x04000000, 0x00000005}, + {0x4A4F4841, 0x01000000, 0x00000002}, + {0x4A4F4859, 0x01000000, 0x00000002}, + {0x4A4F4941, 0x08000000, 0x00000005}, + {0x4A4F4B41, 0x08000000, 0x00000003}, + {0x4A4F4B59, 0x02000000, 0x00000006}, + {0x4A4F4C43, 0x01000000, 0x00000001}, + {0x4A4F4D41, 0x04000000, 0x00000002}, + {0x4A4F4D42, 0x08000000, 0x00000005}, + {0x4A4F4D43, 0x02000000, 0x00000003}, + {0x4A4F4E41, 0x02000000, 0x00000002}, + {0x4A4F4E43, 0x04000000, 0x00000002}, + {0x4A4F4F41, 0x01000000, 0x00000002}, + {0x4A4F4F42, 0x08000000, 0x00000002}, + {0x4A4F4F59, 0x04000000, 0x00000003}, + {0x4A4F5041, 0x04000000, 0x00000001}, + {0x4A4F5042, 0x04000000, 0x00000003}, + {0x4A4F5059, 0x04000000, 0x00000003}, + {0x4A4F5141, 0x04000000, 0x00000003}, + {0x4A4F5241, 0x08000000, 0x00000003}, + {0x4A4F5242, 0x04000000, 0x00000003}, + {0x4A4F5259, 0x04000000, 0x00000002}, + {0x4A4F5441, 0x04000000, 0x00000002}, + {0x4A4F5442, 0x04000000, 0x00000002}, + {0x4A4F5443, 0x04000000, 0x00000001}, + {0x4A4F5459, 0x04000000, 0x00000002}, + {0x4A4F5559, 0x10000000, 0x00000003}, + {0x4A4F5641, 0x01000000, 0x00000003}, + {0x4A4F5659, 0x02000000, 0x00000002}, + {0x4A4F5842, 0x04000000, 0x00000003}, + {0x4A4F5859, 0x04000000, 0x00000005}, + {0x4A4F5941, 0x04000000, 0x00000003}, + {0x4A4F5942, 0x04000000, 0x00000003}, + {0x4A4F5A59, 0x08000000, 0x00000002}, + {0x4A503242, 0x04000000, 0x00000005}, + {0x4A503243, 0x04000000, 0x00000003}, + {0x4A503341, 0x02000000, 0x00000001}, + {0x4A503443, 0x01000000, 0x00000002}, + {0x4A503541, 0x04000000, 0x00000001}, + {0x4A503542, 0x10000000, 0x00000001}, + {0x4A503543, 0x02000000, 0x00000002}, + {0x4A503641, 0x00800000, 0x00000003}, + {0x4A503643, 0x02000000, 0x00000007}, + {0x4A503742, 0x08000000, 0x00000003}, + {0x4A503841, 0x02000000, 0x00000002}, + {0x4A503842, 0x02000000, 0x00000003}, + {0x4A504142, 0x04000000, 0x00000001}, + {0x4A504341, 0x00800000, 0x00000002}, + {0x4A504356, 0x04000000, 0x00000003}, + {0x4A504359, 0x04000000, 0x00000001}, + {0x4A504441, 0x00800000, 0x00000002}, + {0x4A504459, 0x02000000, 0x00000001}, + {0x4A504541, 0x01000000, 0x00000003}, + {0x4A504641, 0x04000000, 0x00000001}, + {0x4A504642, 0x04000000, 0x00000002}, + {0x4A504654, 0x04000000, 0x00000005}, + {0x4A504741, 0x04000000, 0x00000002}, + {0x4A504759, 0x02000000, 0x00000003}, + {0x4A504841, 0x04000000, 0x00000001}, + {0x4A504843, 0x01000000, 0x00000001}, + {0x4A504859, 0x01000000, 0x00000002}, + {0x4A504942, 0x04000000, 0x00000002}, + {0x4A504943, 0x02000000, 0x00000002}, + {0x4A504959, 0x04000000, 0x00000001}, + {0x4A504A42, 0x02000000, 0x00000002}, + {0x4A504B42, 0x04000000, 0x00000002}, + {0x4A504B56, 0x02000000, 0x00000005}, + {0x4A504C59, 0x00800000, 0x00000002}, + {0x4A504D54, 0x08000000, 0x00000003}, + {0x4A504D59, 0x08000000, 0x00000005}, + {0x4A505042, 0x04000000, 0x00000005}, + {0x4A505054, 0x04000000, 0x00000007}, + {0x4A505059, 0x01000000, 0x00000001}, + {0x4A505142, 0x04000000, 0x00000002}, + {0x4A505159, 0x02000000, 0x00000002}, + {0x4A505242, 0x08000000, 0x00000003}, + {0x4A505341, 0x02000000, 0x00000003}, + {0x4A505343, 0x02000000, 0x00000003}, + {0x4A505359, 0x02000000, 0x00000005}, + {0x4A505441, 0x04000000, 0x00000005}, + {0x4A505541, 0x00800000, 0x00000001}, + {0x4A505559, 0x04000000, 0x00000002}, + {0x4A505641, 0x04000000, 0x00000002}, + {0x4A505643, 0x10000000, 0x00000002}, + {0x4A505659, 0x08000000, 0x00000003}, + {0x4A505759, 0x04000000, 0x00000002}, + {0x4A505841, 0x02000000, 0x00000005}, + {0x4A505842, 0x04000000, 0x00000002}, + {0x4A505859, 0x02000000, 0x00000003}, + {0x4A505A41, 0x01000000, 0x00000002}, + {0x4A505A55, 0x08000000, 0x00000003}, + {0x4A505A59, 0x02000000, 0x00000002}, + {0x4A513242, 0x04000000, 0x00000001}, + {0x4A513341, 0x04000000, 0x00000003}, + {0x4A513441, 0x01000000, 0x00000001}, + {0x4A513442, 0x02000000, 0x00000002}, + {0x4A513541, 0x01000000, 0x00000001}, + {0x4A513641, 0x01000000, 0x00000001}, + {0x4A513742, 0x04000000, 0x00000005}, + {0x4A513841, 0x02000000, 0x00000005}, + {0x4A514154, 0x04000000, 0x00000004}, + {0x4A514159, 0x04000000, 0x00000003}, + {0x4A514254, 0x04000000, 0x00000002}, + {0x4A514341, 0x02000000, 0x00000001}, + {0x4A514359, 0x04000000, 0x00000002}, + {0x4A514441, 0x04000000, 0x00000002}, + {0x4A514443, 0x08000000, 0x00000001}, + {0x4A514459, 0x10000000, 0x00000003}, + {0x4A514541, 0x00800000, 0x00000002}, + {0x4A514542, 0x04000000, 0x00000002}, + {0x4A514641, 0x02000000, 0x00000002}, + {0x4A514654, 0x04000000, 0x00000007}, + {0x4A514659, 0x04000000, 0x00000002}, + {0x4A514842, 0x04000000, 0x00000002}, + {0x4A514859, 0x04000000, 0x00000003}, + {0x4A514941, 0x00800000, 0x00000002}, + {0x4A514959, 0x08000000, 0x00000002}, + {0x4A514A41, 0x02000000, 0x00000002}, + {0x4A514B41, 0x02000000, 0x00000001}, + {0x4A514B59, 0x04000000, 0x00000003}, + {0x4A514D41, 0x04000000, 0x00000005}, + {0x4A514E41, 0x00800000, 0x00000002}, + {0x4A514E43, 0x02000000, 0x00000003}, + {0x4A514E59, 0x00800000, 0x00000002}, + {0x4A514F41, 0x04000000, 0x00000001}, + {0x4A514F42, 0x02000000, 0x00000005}, + {0x4A514F59, 0x08000000, 0x00000002}, + {0x4A515054, 0x04000000, 0x00000002}, + {0x4A515059, 0x01000000, 0x00000001}, + {0x4A515141, 0x02000000, 0x00000002}, + {0x4A515241, 0x04000000, 0x00000003}, + {0x4A515242, 0x04000000, 0x00000005}, + {0x4A515341, 0x00800000, 0x00000002}, + {0x4A515541, 0x01000000, 0x00000002}, + {0x4A515542, 0x08000000, 0x00000001}, + {0x4A515559, 0x01000000, 0x00000002}, + {0x4A515741, 0x01000000, 0x00000001}, + {0x4A515859, 0x02000000, 0x00000003}, + {0x4A515942, 0x02000000, 0x00000002}, + {0x4A515959, 0x01000000, 0x00000002}, + {0x4A515A42, 0x08000000, 0x00000003}, + {0x4A515A59, 0x01000000, 0x00000005}, + {0x4A523241, 0x01000000, 0x00000003}, + {0x4A523342, 0x08000000, 0x00000005}, + {0x4A523343, 0x04000000, 0x00000002}, + {0x4A523356, 0x02000000, 0x00000003}, + {0x4A523441, 0x02000000, 0x00000002}, + {0x4A523541, 0x01000000, 0x00000002}, + {0x4A523543, 0x08000000, 0x00000003}, + {0x4A523641, 0x04000000, 0x00000003}, + {0x4A523643, 0x04000000, 0x00000003}, + {0x4A523841, 0x04000000, 0x00000005}, + {0x4A523842, 0x04000000, 0x00000002}, + {0x4A524142, 0x02000000, 0x00000005}, + {0x4A524255, 0x00800000, 0x00000005}, + {0x4A524259, 0x04000000, 0x00000001}, + {0x4A524441, 0x01000000, 0x00000002}, + {0x4A524541, 0x01000000, 0x00000002}, + {0x4A524559, 0x04000000, 0x00000003}, + {0x4A524643, 0x08000000, 0x00000002}, + {0x4A524741, 0x04000000, 0x00000005}, + {0x4A524742, 0x02000000, 0x00000002}, + {0x4A524743, 0x04000000, 0x00000001}, + {0x4A524759, 0x08000000, 0x00000002}, + {0x4A524841, 0x02000000, 0x00000002}, + {0x4A524854, 0x20000000, 0x00000003}, + {0x4A524856, 0x04000000, 0x00000002}, + {0x4A524941, 0x01000000, 0x00000001}, + {0x4A524A41, 0x08000000, 0x00000005}, + {0x4A524A43, 0x08000000, 0x00000003}, + {0x4A524A59, 0x08000000, 0x00000002}, + {0x4A524B41, 0x04000000, 0x00000002}, + {0x4A524B43, 0x04000000, 0x00000003}, + {0x4A524B59, 0x04000000, 0x00000005}, + {0x4A524C41, 0x00800000, 0x00000002}, + {0x4A524D41, 0x01000000, 0x00000003}, + {0x4A524E41, 0x04000000, 0x00000001}, + {0x4A524E43, 0x04000000, 0x00000002}, + {0x4A524E54, 0x10000000, 0x00000003}, + {0x4A524E59, 0x04000000, 0x00000002}, + {0x4A524F42, 0x01000000, 0x00000003}, + {0x4A524F55, 0x02000000, 0x00000008}, + {0x4A525041, 0x02000000, 0x00000002}, + {0x4A525142, 0x02000000, 0x00000002}, + {0x4A525143, 0x04000000, 0x00000002}, + {0x4A525242, 0x10000000, 0x00000003}, + {0x4A525243, 0x02000000, 0x00000005}, + {0x4A525341, 0x04000000, 0x00000003}, + {0x4A525343, 0x10000000, 0x00000002}, + {0x4A525359, 0x01000000, 0x00000005}, + {0x4A525441, 0x01000000, 0x00000002}, + {0x4A52544E, 0x00180AC8, 0x00000000}, + {0x4A525541, 0x04000000, 0x00000002}, + {0x4A525543, 0x04000000, 0x00000001}, + {0x4A525559, 0x04000000, 0x00000003}, + {0x4A525641, 0x04000000, 0x00000002}, + {0x4A525659, 0x08000000, 0x00000002}, + {0x4A525741, 0x02000000, 0x00000005}, + {0x4A525742, 0x02000000, 0x00000003}, + {0x4A525841, 0x01000000, 0x00000002}, + {0x4A525959, 0x04000000, 0x00000001}, + {0x4A525A41, 0x08000000, 0x00000002}, + {0x4A525A59, 0x01000000, 0x00000002}, + {0x4A533243, 0x08000000, 0x00000004}, + {0x4A533342, 0x20000000, 0x00000003}, + {0x4A534159, 0x10000000, 0x00000005}, + {0x4A534241, 0x01000000, 0x00000005}, + {0x4A534254, 0x02000000, 0x00000002}, + {0x4A534259, 0x08000000, 0x00000003}, + {0x4A534342, 0x04000000, 0x00000002}, + {0x4A534459, 0x04000000, 0x00000002}, + {0x4A534559, 0x04000000, 0x00000003}, + {0x4A534654, 0x02000000, 0x00000003}, + {0x4A534659, 0x04000000, 0x00000002}, + {0x4A534841, 0x02000000, 0x00000002}, + {0x4A534A41, 0x001998C8, 0x00000002}, + {0x4A534A59, 0x02000000, 0x00000002}, + {0x4A534B41, 0x02000000, 0x00000002}, + {0x4A534B42, 0x02000000, 0x00000002}, + {0x4A534C41, 0x04000000, 0x00000002}, + {0x4A534C59, 0x04000000, 0x00000001}, + {0x4A534D41, 0x04000000, 0x00000003}, + {0x4A534D43, 0x02000000, 0x00000003}, + {0x4A534D59, 0x04000000, 0x00000005}, + {0x4A534E41, 0x01000000, 0x00000001}, + {0x4A534E43, 0x04000000, 0x00000002}, + {0x4A534E55, 0x00800000, 0x00000006}, + {0x4A534F41, 0x04000000, 0x00000002}, + {0x4A534F42, 0x01000000, 0x00000003}, + {0x4A534F56, 0x02000000, 0x00000007}, + {0x4A534F59, 0x00800000, 0x00000002}, + {0x4A535041, 0x04000000, 0x00000005}, + {0x4A535054, 0x04000000, 0x00000005}, + {0x4A535059, 0x01000000, 0x00000002}, + {0x4A535141, 0x02000000, 0x00000002}, + {0x4A535142, 0x01000000, 0x00000003}, + {0x4A535241, 0x08000000, 0x00000002}, + {0x4A535359, 0x04000000, 0x00000003}, + {0x4A535443, 0x04000000, 0x00000001}, + {0x4A535641, 0x02000000, 0x00000002}, + {0x4A535659, 0x02000000, 0x00000003}, + {0x4A535841, 0x04000000, 0x00000002}, + {0x4A535842, 0x04000000, 0x00000003}, + {0x4A535859, 0x02000000, 0x00000003}, + {0x4A535941, 0x04000000, 0x00000005}, + {0x4A535942, 0x04000000, 0x00000003}, + {0x4A535959, 0x01000000, 0x00000002}, + {0x4A535A41, 0x01000000, 0x00000003}, + {0x4A535A43, 0x04000000, 0x00000001}, + {0x4A535A59, 0x01000000, 0x00000002}, + {0x4A543243, 0x04000000, 0x00000003}, + {0x4A543342, 0x02000000, 0x00000001}, + {0x4A543442, 0x02000000, 0x00000002}, + {0x4A543443, 0x08000000, 0x00000002}, + {0x4A543541, 0x02000000, 0x00000005}, + {0x4A543841, 0x02000000, 0x00000002}, + {0x4A543842, 0x01000000, 0x00000001}, + {0x4A544143, 0x02000000, 0x00000002}, + {0x4A544259, 0x08000000, 0x00000003}, + {0x4A544341, 0x02000000, 0x00000001}, + {0x4A544343, 0x08000000, 0x00000003}, + {0x4A544354, 0x02000000, 0x00000005}, + {0x4A544356, 0x04000000, 0x00000003}, + {0x4A544359, 0x02000000, 0x00000001}, + {0x4A544459, 0x04000000, 0x00000003}, + {0x4A544541, 0x04000000, 0x00000001}, + {0x4A544542, 0x04000000, 0x00000005}, + {0x4A544543, 0x08000000, 0x00000002}, + {0x4A544654, 0x04000000, 0x00000002}, + {0x4A544659, 0x04000000, 0x00000005}, + {0x4A544741, 0x02000000, 0x00000002}, + {0x4A544742, 0x08000000, 0x00000002}, + {0x4A544843, 0x04000000, 0x00000002}, + {0x4A544854, 0x20000000, 0x00000003}, + {0x4A544859, 0x01000000, 0x00000001}, + {0x4A544942, 0x08000000, 0x00000005}, + {0x4A544A59, 0x08000000, 0x00000002}, + {0x4A544B41, 0x01000000, 0x00000001}, + {0x4A544B42, 0x04000000, 0x00000002}, + {0x4A544B54, 0x04000000, 0x00000002}, + {0x4A544B59, 0x02000000, 0x00000002}, + {0x4A544C54, 0x04000000, 0x00000003}, + {0x4A544C59, 0x08000000, 0x00000002}, + {0x4A544D41, 0x04000000, 0x00000002}, + {0x4A544D42, 0x08000000, 0x00000003}, + {0x4A544D56, 0x10000000, 0x00000002}, + {0x4A544E41, 0x04000000, 0x00000002}, + {0x4A544E43, 0x10000000, 0x00000003}, + {0x4A544E59, 0x10000000, 0x00000001}, + {0x4A544F41, 0x01000000, 0x00000002}, + {0x4A544F42, 0x01000000, 0x00000005}, + {0x4A544F43, 0x01000000, 0x00000005}, + {0x4A544F59, 0x04000000, 0x00000003}, + {0x4A545041, 0x01000000, 0x00000002}, + {0x4A545043, 0x04000000, 0x00000005}, + {0x4A545056, 0x08000000, 0x00000006}, + {0x4A545059, 0x02000000, 0x00000005}, + {0x4A545143, 0x04000000, 0x00000003}, + {0x4A545241, 0x08000000, 0x00000002}, + {0x4A545341, 0x02000000, 0x00000001}, + {0x4A545359, 0x04000000, 0x00000001}, + {0x4A545442, 0x04000000, 0x00000002}, + {0x4A545443, 0x08000000, 0x00000003}, + {0x4A545459, 0x08000000, 0x00000003}, + {0x4A545641, 0x04000000, 0x00000002}, + {0x4A545741, 0x00800000, 0x00000001}, + {0x4A545843, 0x10000000, 0x00000003}, + {0x4A545859, 0x02000000, 0x00000003}, + {0x4A545941, 0x08000000, 0x00000003}, + {0x4A545943, 0x04000000, 0x00000003}, + {0x4A545A41, 0x01000000, 0x00000005}, + {0x4A545A43, 0x02000000, 0x00000002}, + {0x4A545A59, 0x01000000, 0x00000005}, + {0x4A553241, 0x04000000, 0x00000002}, + {0x4A553341, 0x02000000, 0x00000001}, + {0x4A553343, 0x08000000, 0x00000002}, + {0x4A553441, 0x02000000, 0x00000002}, + {0x4A553442, 0x02000000, 0x00000003}, + {0x4A553443, 0x04000000, 0x00000001}, + {0x4A553641, 0x02000000, 0x00000001}, + {0x4A553841, 0x02000000, 0x00000002}, + {0x4A554241, 0x04000000, 0x00000005}, + {0x4A554242, 0x04000000, 0x00000003}, + {0x4A554259, 0x08000000, 0x00000003}, + {0x4A554341, 0x04000000, 0x00000005}, + {0x4A554343, 0x04000000, 0x00000006}, + {0x4A554441, 0x02000000, 0x00000003}, + {0x4A554459, 0x04000000, 0x00000003}, + {0x4A554541, 0x04000000, 0x00000003}, + {0x4A554542, 0x10000000, 0x00000003}, + {0x4A554641, 0x01000000, 0x00000003}, + {0x4A554656, 0x10000000, 0x00000005}, + {0x4A554659, 0x04000000, 0x00000002}, + {0x4A554741, 0x02000000, 0x00000002}, + {0x4A554742, 0x08000000, 0x00000003}, + {0x4A554759, 0x01000000, 0x00000002}, + {0x4A554843, 0x10000000, 0x00000003}, + {0x4A554A41, 0x04000000, 0x00000003}, + {0x4A554A42, 0x02000000, 0x00000003}, + {0x4A554A43, 0x04000000, 0x00000003}, + {0x4A554A59, 0x04000000, 0x00000002}, + {0x4A554B42, 0x08000000, 0x00000005}, + {0x4A554B43, 0x04000000, 0x00000003}, + {0x4A554B59, 0x04000000, 0x00000003}, + {0x4A554C41, 0x02000000, 0x00000002}, + {0x4A554C42, 0x08000000, 0x00000003}, + {0x4A554C59, 0x08000000, 0x00000005}, + {0x4A554E43, 0x02000000, 0x00000002}, + {0x4A554E59, 0x04000000, 0x00000003}, + {0x4A554F41, 0x01000000, 0x00000003}, + {0x4A555041, 0x02000000, 0x00000003}, + {0x4A555042, 0x04000000, 0x00000005}, + {0x4A555043, 0x08000000, 0x00000006}, + {0x4A555141, 0x08000000, 0x00000002}, + {0x4A555142, 0x04000000, 0x00000002}, + {0x4A555143, 0x02000000, 0x00000002}, + {0x4A555159, 0x08000000, 0x00000003}, + {0x4A555241, 0x02000000, 0x00000003}, + {0x4A555259, 0x00800000, 0x00000001}, + {0x4A555341, 0x04000000, 0x00000003}, + {0x4A555359, 0x00800000, 0x00000003}, + {0x4A555441, 0x04000000, 0x00000002}, + {0x4A555442, 0x04000000, 0x00000002}, + {0x4A555443, 0x10000000, 0x00000003}, + {0x4A555459, 0x04000000, 0x00000003}, + {0x4A555541, 0x00800000, 0x00000003}, + {0x4A555543, 0x00800000, 0x00000002}, + {0x4A555559, 0x02000000, 0x00000002}, + {0x4A555641, 0x08000000, 0x00000003}, + {0x4A555643, 0x04000000, 0x00000002}, + {0x4A555659, 0x04000000, 0x00000005}, + {0x4A555759, 0x02000000, 0x00000001}, + {0x4A555859, 0x02000000, 0x00000003}, + {0x4A555941, 0x02000000, 0x00000002}, + {0x4A555A41, 0x01000000, 0x00000002}, + {0x4A555A59, 0x04000000, 0x00000001}, + {0x4A563243, 0x10000000, 0x00000003}, + {0x4A563341, 0x04000000, 0x00000003}, + {0x4A563441, 0x08000000, 0x00000005}, + {0x4A563841, 0x04000000, 0x00000002}, + {0x4A563842, 0x02000000, 0x00000003}, + {0x4A564156, 0x04000000, 0x00000001}, + {0x4A564241, 0x02000000, 0x00000002}, + {0x4A564341, 0x04000000, 0x00000002}, + {0x4A564441, 0x01000000, 0x00000001}, + {0x4A564454, 0x08000000, 0x00000003}, + {0x4A564541, 0x04000000, 0x00000002}, + {0x4A564542, 0x10000000, 0x00000003}, + {0x4A564742, 0x04000000, 0x00000002}, + {0x4A564759, 0x04000000, 0x00000002}, + {0x4A564843, 0x01000000, 0x00000003}, + {0x4A564941, 0x02000000, 0x00000002}, + {0x4A564942, 0x00800000, 0x00000001}, + {0x4A564943, 0x08000000, 0x00000003}, + {0x4A564959, 0x08000000, 0x00000003}, + {0x4A564A41, 0x01000000, 0x00000001}, + {0x4A564B41, 0x04000000, 0x00000001}, + {0x4A564B59, 0x08000000, 0x00000003}, + {0x4A564C41, 0x02000000, 0x00000002}, + {0x4A564C59, 0x04000000, 0x00000002}, + {0x4A564D59, 0x00800000, 0x00000001}, + {0x4A564E43, 0x08000000, 0x00000005}, + {0x4A564E59, 0x02000000, 0x00000002}, + {0x4A564F41, 0x04000000, 0x00000002}, + {0x4A564F43, 0x02000000, 0x00000005}, + {0x4A565041, 0x00800000, 0x00000002}, + {0x4A565142, 0x04000000, 0x00000003}, + {0x4A565259, 0x02000000, 0x00000005}, + {0x4A565359, 0x04000000, 0x00000003}, + {0x4A565541, 0x08000000, 0x00000002}, + {0x4A565559, 0x02000000, 0x00000003}, + {0x4A565641, 0x00800000, 0x00000003}, + {0x4A565643, 0x01000000, 0x00000001}, + {0x4A565659, 0x00800000, 0x00000001}, + {0x4A565741, 0x01000000, 0x00000001}, + {0x4A565743, 0x04000000, 0x00000002}, + {0x4A565759, 0x04000000, 0x00000002}, + {0x4A565841, 0x04000000, 0x00000003}, + {0x4A565843, 0x02000000, 0x00000003}, + {0x4A565942, 0x08000000, 0x00000003}, + {0x4A565943, 0x04000000, 0x00000002}, + {0x4A565A41, 0x00800000, 0x00000001}, + {0x4A565A59, 0x02000000, 0x00000002}, + {0x4A573241, 0x04000000, 0x00000001}, + {0x4A573242, 0x08000000, 0x00000003}, + {0x4A573243, 0x02000000, 0x00000002}, + {0x4A573343, 0x02000000, 0x00000003}, + {0x4A573443, 0x02000000, 0x00000002}, + {0x4A573643, 0x02000000, 0x00000002}, + {0x4A573841, 0x00800000, 0x00000001}, + {0x4A574159, 0x04000000, 0x00000002}, + {0x4A574254, 0x02000000, 0x00000001}, + {0x4A574341, 0x00800000, 0x00000002}, + {0x4A574359, 0x00800000, 0x00000002}, + {0x4A574459, 0x02000000, 0x00000005}, + {0x4A574541, 0x04000000, 0x00000002}, + {0x4A574543, 0x08000000, 0x00000002}, + {0x4A574559, 0x04000000, 0x00000008}, + {0x4A574741, 0x01000000, 0x00000002}, + {0x4A574742, 0x02000000, 0x00000002}, + {0x4A574743, 0x00800000, 0x00000001}, + {0x4A574941, 0x01000000, 0x00000002}, + {0x4A574A41, 0x01000000, 0x00000001}, + {0x4A574B41, 0x04000000, 0x00000002}, + {0x4A574B43, 0x10000000, 0x00000001}, + {0x4A574B59, 0x08000000, 0x00000003}, + {0x4A574C41, 0x02000000, 0x00000001}, + {0x4A574D49, 0x04000000, 0x00000007}, + {0x4A574F43, 0x10000000, 0x00000002}, + {0x4A574F59, 0x02000000, 0x00000002}, + {0x4A575141, 0x02000000, 0x00000002}, + {0x4A575142, 0x08000000, 0x00000003}, + {0x4A575241, 0x01000000, 0x00000002}, + {0x4A575242, 0x08000000, 0x00000005}, + {0x4A575259, 0x02000000, 0x00000005}, + {0x4A575342, 0x08000000, 0x00000006}, + {0x4A575441, 0x02000000, 0x00000002}, + {0x4A575443, 0x01000000, 0x00000003}, + {0x4A575459, 0x08000000, 0x00000003}, + {0x4A575541, 0x04000000, 0x00000003}, + {0x4A575543, 0x04000000, 0x00000003}, + {0x4A575659, 0x10000000, 0x00000003}, + {0x4A575742, 0x08000000, 0x00000003}, + {0x4A575759, 0x02000000, 0x00000002}, + {0x4A575841, 0x00800000, 0x00000002}, + {0x4A575843, 0x02000000, 0x00000003}, + {0x4A575859, 0x01000000, 0x00000003}, + {0x4A575941, 0x02000000, 0x00000002}, + {0x4A575943, 0x01000000, 0x00000001}, + {0x4A575A41, 0x02000000, 0x00000002}, + {0x4A575A43, 0x04000000, 0x00000002}, + {0x4A575A59, 0x02000000, 0x00000002}, + {0x4A583241, 0x01000000, 0x00000002}, + {0x4A583243, 0x02000000, 0x00000003}, + {0x4A583342, 0x01000000, 0x00000001}, + {0x4A583343, 0x08000000, 0x00000002}, + {0x4A583442, 0x04000000, 0x00000002}, + {0x4A583641, 0x02000000, 0x00000002}, + {0x4A583642, 0x01000000, 0x00000003}, + {0x4A583643, 0x00800000, 0x00000002}, + {0x4A583742, 0x08000000, 0x00000003}, + {0x4A583841, 0x04000000, 0x00000002}, + {0x4A584241, 0x02000000, 0x00000002}, + {0x4A584342, 0x04000000, 0x00000005}, + {0x4A584359, 0x02000000, 0x00000002}, + {0x4A584441, 0x02000000, 0x00000002}, + {0x4A584442, 0x01000000, 0x00000001}, + {0x4A584541, 0x08000000, 0x00000002}, + {0x4A584559, 0x02000000, 0x00000002}, + {0x4A584641, 0x08000000, 0x00000003}, + {0x4A584642, 0x04000000, 0x00000002}, + {0x4A584743, 0x10000000, 0x00000001}, + {0x4A584759, 0x08000000, 0x00000002}, + {0x4A584842, 0x04000000, 0x00000002}, + {0x4A584941, 0x04000000, 0x00000002}, + {0x4A584959, 0x08000000, 0x00000003}, + {0x4A584A41, 0x02000000, 0x00000001}, + {0x4A584B41, 0x08000000, 0x00000002}, + {0x4A584B42, 0x04000000, 0x00000003}, + {0x4A584B59, 0x00800000, 0x00000002}, + {0x4A584C54, 0x01000000, 0x00000002}, + {0x4A584D54, 0x04000000, 0x00000003}, + {0x4A584E42, 0x04000000, 0x00000002}, + {0x4A584F42, 0x20000000, 0x00000005}, + {0x4A584F59, 0x04000000, 0x00000003}, + {0x4A585041, 0x04000000, 0x00000005}, + {0x4A585141, 0x08000000, 0x00000003}, + {0x4A585241, 0x04000000, 0x00000001}, + {0x4A585259, 0x04000000, 0x00000002}, + {0x4A585341, 0x01000000, 0x00000002}, + {0x4A585459, 0x04000000, 0x00000002}, + {0x4A585541, 0x01000000, 0x00000001}, + {0x4A585559, 0x04000000, 0x00000003}, + {0x4A585659, 0x04000000, 0x00000002}, + {0x4A585841, 0x04000000, 0x00000002}, + {0x4A585843, 0x02000000, 0x00000003}, + {0x4A585859, 0x04000000, 0x00000002}, + {0x4A585941, 0x08000000, 0x00000005}, + {0x4A585942, 0x10000000, 0x00000003}, + {0x4A585A41, 0x04000000, 0x00000002}, + {0x4A585A59, 0x04000000, 0x00000002}, + {0x4A593241, 0x01000000, 0x00000007}, + {0x4A593243, 0x08000000, 0x00000003}, + {0x4A593341, 0x04000000, 0x00000003}, + {0x4A593343, 0x08000000, 0x00000002}, + {0x4A593441, 0x00800000, 0x00000003}, + {0x4A593442, 0x00800000, 0x00000001}, + {0x4A593543, 0x08000000, 0x00000002}, + {0x4A593643, 0x04000000, 0x00000002}, + {0x4A593841, 0x00800000, 0x00000001}, + {0x4A594159, 0x02000000, 0x00000001}, + {0x4A594341, 0x01000000, 0x00000005}, + {0x4A594541, 0x04000000, 0x00000002}, + {0x4A594659, 0x04000000, 0x00000005}, + {0x4A594741, 0x04000000, 0x00000005}, + {0x4A594743, 0x04000000, 0x00000002}, + {0x4A594759, 0x00800000, 0x00000002}, + {0x4A594942, 0x04000000, 0x00000005}, + {0x4A594A41, 0x04000000, 0x00000006}, + {0x4A594B41, 0x01000000, 0x00000003}, + {0x4A594B43, 0x02000000, 0x00000003}, + {0x4A594B59, 0x02000000, 0x00000002}, + {0x4A594D41, 0x04000000, 0x00000003}, + {0x4A594D43, 0x01000000, 0x00000003}, + {0x4A594E41, 0x04000000, 0x00000003}, + {0x4A594F42, 0x04000000, 0x00000002}, + {0x4A594F59, 0x01000000, 0x00000002}, + {0x4A595041, 0x02000000, 0x00000002}, + {0x4A595056, 0x10000000, 0x00000005}, + {0x4A595141, 0x04000000, 0x00000002}, + {0x4A595159, 0x01000000, 0x00000002}, + {0x4A595242, 0x10000000, 0x00000002}, + {0x4A595259, 0x02000000, 0x00000001}, + {0x4A595341, 0x00800000, 0x00000001}, + {0x4A595541, 0x02000000, 0x00000002}, + {0x4A595542, 0x04000000, 0x00000002}, + {0x4A595543, 0x02000000, 0x00000001}, + {0x4A595641, 0x04000000, 0x00000002}, + {0x4A595659, 0x08000000, 0x00000001}, + {0x4A595741, 0x02000000, 0x00000003}, + {0x4A595742, 0x04000000, 0x00000003}, + {0x4A595841, 0x08000000, 0x00000001}, + {0x4A595843, 0x02000000, 0x00000003}, + {0x4A595942, 0x08000000, 0x00000003}, + {0x4A595959, 0x04000000, 0x00000003}, + {0x4A595A43, 0x02000000, 0x00000002}, + {0x4A5A3241, 0x02000000, 0x00000001}, + {0x4A5A3341, 0x04000000, 0x00000002}, + {0x4A5A3342, 0x02000000, 0x00000001}, + {0x4A5A3641, 0x08000000, 0x00000002}, + {0x4A5A3642, 0x04000000, 0x00000003}, + {0x4A5A3841, 0x02000000, 0x00000002}, + {0x4A5A4143, 0x04000000, 0x00000002}, + {0x4A5A4241, 0x08000000, 0x00000003}, + {0x4A5A4341, 0x01000000, 0x00000001}, + {0x4A5A4441, 0x02000000, 0x00000002}, + {0x4A5A4459, 0x01000000, 0x00000002}, + {0x4A5A4541, 0x04000000, 0x00000002}, + {0x4A5A4542, 0x20000000, 0x00000003}, + {0x4A5A4543, 0x08000000, 0x00000002}, + {0x4A5A4559, 0x04000000, 0x00000002}, + {0x4A5A4741, 0x04000000, 0x00000001}, + {0x4A5A4843, 0x04000000, 0x00000002}, + {0x4A5A4854, 0x20000000, 0x00000002}, + {0x4A5A4941, 0x00800000, 0x00000002}, + {0x4A5A4959, 0x04000000, 0x00000002}, + {0x4A5A4A41, 0x00800000, 0x00000002}, + {0x4A5A4A59, 0x02000000, 0x00000005}, + {0x4A5A4B41, 0x01000000, 0x00000002}, + {0x4A5A4B54, 0x02000000, 0x00000002}, + {0x4A5A4B59, 0x01000000, 0x00000002}, + {0x4A5A4C41, 0x02000000, 0x00000002}, + {0x4A5A4C59, 0x08000000, 0x00000002}, + {0x4A5A4D41, 0x00800000, 0x00000002}, + {0x4A5A4D43, 0x04000000, 0x00000003}, + {0x4A5A4E41, 0x01000000, 0x00000001}, + {0x4A5A4E43, 0x02000000, 0x00000002}, + {0x4A5A4E59, 0x04000000, 0x00000002}, + {0x4A5A4F41, 0x01000000, 0x00000002}, + {0x4A5A4F43, 0x08000000, 0x00000002}, + {0x4A5A5041, 0x01000000, 0x00000002}, + {0x4A5A5141, 0x02000000, 0x00000002}, + {0x4A5A5159, 0x00800000, 0x00000001}, + {0x4A5A5241, 0x04000000, 0x00000002}, + {0x4A5A5242, 0x04000000, 0x00000003}, + {0x4A5A5641, 0x01000000, 0x00000001}, + {0x4A5A5643, 0x10000000, 0x00000003}, + {0x4A5A5659, 0x00800000, 0x00000001}, + {0x4A5A5741, 0x02000000, 0x00000002}, + {0x4A5A5742, 0x04000000, 0x00000003}, + {0x4A5A5759, 0x04000000, 0x00000001}, + {0x4A5A5841, 0x08000000, 0x00000001}, + {0x4A5A5843, 0x02000000, 0x00000003}, + {0x4A5A5941, 0x02000000, 0x00000003}, + {0x4A5A5A41, 0x04000000, 0x00000005}, + {0x4A5A5A59, 0x02000000, 0x00000001}, + {0x4B324359, 0x04000000, 0x00000006}, + {0x4B324441, 0x02000000, 0x00000005}, + {0x4B325043, 0x04000000, 0x00000003}, + {0x4B325359, 0x04000000, 0x00000005}, + {0x4B325859, 0x00800000, 0x00000002}, + {0x4B334341, 0x02000000, 0x00000005}, + {0x4B334359, 0x04000000, 0x00000006}, + {0x4B334441, 0x02000000, 0x00000005}, + {0x4B334741, 0x02000000, 0x00000005}, + {0x4B334C41, 0x02000000, 0x00000001}, + {0x4B334D43, 0x08000000, 0x00000003}, + {0x4B344241, 0x04000000, 0x00000005}, + {0x4B344759, 0x10000000, 0x00000003}, + {0x4B344C43, 0x08000000, 0x00000002}, + {0x4B345043, 0x08000000, 0x00000002}, + {0x4B345759, 0x04000000, 0x00000003}, + {0x4B354459, 0x00800000, 0x00000002}, + {0x4B354759, 0x04000000, 0x00000003}, + {0x4B354B43, 0x04000000, 0x00000005}, + {0x4B355443, 0x08000000, 0x00000002}, + {0x4B363643, 0x04000000, 0x00000002}, + {0x4B364843, 0x04000000, 0x00000001}, + {0x4B364C59, 0x04000000, 0x00000001}, + {0x4B374743, 0x04000000, 0x00000002}, + {0x4B374D41, 0x02000000, 0x00000002}, + {0x4B374D59, 0x04000000, 0x00000002}, + {0x4B375241, 0x04000000, 0x00000002}, + {0x4B383443, 0x04000000, 0x00000006}, + {0x4B384659, 0x02000000, 0x00000003}, + {0x4B384759, 0x08000000, 0x00000005}, + {0x4B385741, 0x04000000, 0x00000001}, + {0x4B385943, 0x10000000, 0x00000003}, + {0x4B394559, 0x04000000, 0x00000003}, + {0x4B394643, 0x02000000, 0x00000003}, + {0x4B395259, 0x04000000, 0x00000002}, + {0x4B395343, 0x02000000, 0x00000001}, + {0x4B395759, 0x08000000, 0x00000001}, + {0x4B395941, 0x08000000, 0x00000003}, + {0x4B413242, 0x04000000, 0x00000003}, + {0x4B414156, 0x02000000, 0x00000008}, + {0x4B414441, 0x04000000, 0x00000006}, + {0x4B414641, 0x04000000, 0x00000003}, + {0x4B414642, 0x02000000, 0x00000003}, + {0x4B415041, 0x04000000, 0x00000006}, + {0x4B415249, 0x10000000, 0x00000006}, + {0x4B415941, 0x00800000, 0x00000002}, + {0x4B424B59, 0x04000000, 0x00000003}, + {0x4B425249, 0x10000000, 0x00000006}, + {0x4B425259, 0x08000000, 0x00000003}, + {0x4B433841, 0x02000000, 0x00000002}, + {0x4B434241, 0x02000000, 0x00000005}, + {0x4B434341, 0x02000000, 0x00000001}, + {0x4B434D41, 0x02000000, 0x00000005}, + {0x4B435041, 0x01000000, 0x00000001}, + {0x4B435141, 0x04000000, 0x00000002}, + {0x4B435259, 0x08000000, 0x00000002}, + {0x4B443241, 0x02000000, 0x00000002}, + {0x4B444154, 0x04000000, 0x00000005}, + {0x4B444342, 0x02000000, 0x00000002}, + {0x4B444E41, 0x01000000, 0x00000005}, + {0x4B444E43, 0x04000000, 0x00000002}, + {0x4B445041, 0x01000000, 0x00000002}, + {0x4B445059, 0x02000000, 0x00000003}, + {0x4B445249, 0x20000000, 0x00000006}, + {0x4B454641, 0x04000000, 0x00000003}, + {0x4B455249, 0x20000000, 0x00000006}, + {0x4B455741, 0x04000000, 0x00000005}, + {0x4B455A41, 0x04000000, 0x00000006}, + {0x4B463341, 0x04000000, 0x00000005}, + {0x4B463541, 0x04000000, 0x00000002}, + {0x4B464B59, 0x02000000, 0x00000001}, + {0x4B465241, 0x08000000, 0x00000003}, + {0x4B473341, 0x04000000, 0x00000005}, + {0x4B473641, 0x04000000, 0x00000002}, + {0x4B474441, 0x02000000, 0x00000005}, + {0x4B474E41, 0x08000000, 0x00000005}, + {0x4B474E59, 0x08000000, 0x00000003}, + {0x4B475049, 0x08000000, 0x00000006}, + {0x4B475059, 0x04000000, 0x00000002}, + {0x4B483643, 0x01000000, 0x00000001}, + {0x4B484759, 0x08000000, 0x00000001}, + {0x4B484D41, 0x04000000, 0x00000005}, + {0x4B484E41, 0x08000000, 0x00000006}, + {0x4B485041, 0x02000000, 0x00000005}, + {0x4B494459, 0x04000000, 0x00000002}, + {0x4B495041, 0x00800000, 0x00000002}, + {0x4B495141, 0x02000000, 0x00000005}, + {0x4B495243, 0x02000000, 0x00000002}, + {0x4B495741, 0x08000000, 0x00000005}, + {0x4B4A4241, 0x04000000, 0x00000005}, + {0x4B4A4342, 0x10000000, 0x00000003}, + {0x4B4A4C43, 0x08000000, 0x00000002}, + {0x4B4A5159, 0x08000000, 0x00000005}, + {0x4B4B4343, 0x02000000, 0x00000001}, + {0x4B4B4841, 0x04000000, 0x00000003}, + {0x4B4B5049, 0x08000000, 0x00000006}, + {0x4B4B5659, 0x08000000, 0x00000002}, + {0x4B4C4143, 0x04000000, 0x00000001}, + {0x4B4C4443, 0x02000000, 0x00000005}, + {0x4B4C4542, 0x02000000, 0x00000002}, + {0x4B4C4F43, 0x08000000, 0x00000003}, + {0x4B4C5759, 0x02000000, 0x00000001}, + {0x4B4C5A41, 0x08000000, 0x00000007}, + {0x4B4D3341, 0x08000000, 0x00000002}, + {0x4B4D4441, 0x02000000, 0x00000005}, + {0x4B4D4641, 0x04000000, 0x00000002}, + {0x4B4D4E41, 0x02000000, 0x00000005}, + {0x4B4D5241, 0x04000000, 0x00000002}, + {0x4B4D5341, 0x01000000, 0x00000001}, + {0x4B4E3442, 0x00800000, 0x00000002}, + {0x4B4E5041, 0x02000000, 0x00000001}, + {0x4B4E5943, 0x01000000, 0x00000002}, + {0x4B4F3242, 0x02000000, 0x00000005}, + {0x4B4F4359, 0x04000000, 0x00000001}, + {0x4B4F4443, 0x04000000, 0x00000005}, + {0x4B4F4559, 0x04000000, 0x00000003}, + {0x4B4F4E59, 0x08000000, 0x00000003}, + {0x4B4F5259, 0x02000000, 0x00000002}, + {0x4B504441, 0x00800000, 0x00000002}, + {0x4B504D59, 0x08000000, 0x00000005}, + {0x4B504E59, 0x04000000, 0x00000002}, + {0x4B505142, 0x04000000, 0x00000002}, + {0x4B505359, 0x02000000, 0x00000005}, + {0x4B505759, 0x04000000, 0x00000002}, + {0x4B505841, 0x02000000, 0x00000005}, + {0x4B514641, 0x04000000, 0x00000003}, + {0x4B514B42, 0x04000000, 0x00000001}, + {0x4B524559, 0x04000000, 0x00000003}, + {0x4B524E41, 0x04000000, 0x00000001}, + {0x4B524E59, 0x04000000, 0x00000002}, + {0x4B525441, 0x01000000, 0x00000002}, + {0x4B534743, 0x08000000, 0x00000001}, + {0x4B534E43, 0x04000000, 0x00000002}, + {0x4B534F41, 0x08000000, 0x00000005}, + {0x4B535043, 0x04000000, 0x00000002}, + {0x4B535143, 0x02000000, 0x00000001}, + {0x4B535659, 0x02000000, 0x00000003}, + {0x4B543841, 0x02000000, 0x00000002}, + {0x4B544659, 0x04000000, 0x00000005}, + {0x4B544C59, 0x08000000, 0x00000002}, + {0x4B545041, 0x01000000, 0x00000002}, + {0x4B545359, 0x04000000, 0x00000001}, + {0x4B545A59, 0x01000000, 0x00000005}, + {0x4B554242, 0x04000000, 0x00000003}, + {0x4B554D42, 0x02000000, 0x00000001}, + {0x4B555043, 0x08000000, 0x00000006}, + {0x4B564143, 0x02000000, 0x00000002}, + {0x4B564C59, 0x04000000, 0x00000002}, + {0x4B573443, 0x02000000, 0x00000002}, + {0x4B574441, 0x04000000, 0x00000002}, + {0x4B574459, 0x02000000, 0x00000005}, + {0x4B574B41, 0x04000000, 0x00000002}, + {0x4B574B59, 0x08000000, 0x00000003}, + {0x4B574F42, 0x04000000, 0x00000002}, + {0x4B575241, 0x01000000, 0x00000002}, + {0x4B575941, 0x02000000, 0x00000002}, + {0x4B575A41, 0x02000000, 0x00000002}, + {0x4B583241, 0x01000000, 0x00000002}, + {0x4B584241, 0x02000000, 0x00000002}, + {0x4B584559, 0x02000000, 0x00000002}, + {0x4B585541, 0x01000000, 0x00000001}, + {0x4B585942, 0x10000000, 0x00000003}, + {0x4B585A43, 0x08000000, 0x00000002}, + {0x4B593242, 0x02000000, 0x00000002}, + {0x4B593341, 0x04000000, 0x00000003}, + {0x4B593441, 0x00800000, 0x00000003}, + {0x4B594541, 0x04000000, 0x00000002}, + {0x4B594659, 0x04000000, 0x00000005}, + {0x4B595543, 0x02000000, 0x00000001}, + {0x4B595942, 0x08000000, 0x00000003}, + {0x4B5A4459, 0x00800000, 0x00000002}, + {0x4B5A4C59, 0x08000000, 0x00000002}, + {0x4B5A5242, 0x04000000, 0x00000003}, + {0x4B5A5A43, 0x10000000, 0x00000005}, + {0x4C464B59, 0x04000000, 0x00000001}, + {0x4C474D43, 0x04000000, 0x00000001}, + {0x4D374C42, 0x04000000, 0x00000001}, + {0x4D375042, 0x02000000, 0x00000001}, + {0x4D385042, 0x04000000, 0x00000001}, + {0x4D435143, 0x02000000, 0x00000001}, + {0x4D474D43, 0x04000000, 0x00000001}, + {0x4D503642, 0x02000000, 0x00000001}, + {0x4E374C42, 0x04000000, 0x00000001}, + {0x4E374E42, 0x02000000, 0x00000001}, + {0x4E375042, 0x02000000, 0x00000001}, + {0x4E385042, 0x04000000, 0x00000001}, + {0x4E435143, 0x02000000, 0x00000001}, + {0x4E454642, 0x04000000, 0x00000001}, + {0x4E503642, 0x02000000, 0x00000001}, + {0x4E573542, 0x02000000, 0x00000001}, + {0x4E584C42, 0x04000000, 0x00000008}, + {0x4E594C42, 0x04000000, 0x00000008}, + {0x4F415249, 0x10000000, 0x00000006}, + {0x4F425249, 0x10000000, 0x00000006}, + {0x4F445249, 0x20000000, 0x00000006}, + {0x4F455249, 0x20000000, 0x00000006}, + {0x50323241, 0x01000000, 0x00000002}, + {0x50323343, 0x04000000, 0x00000003}, + {0x50323542, 0x01000000, 0x00000001}, + {0x50323641, 0x04000000, 0x00000008}, + {0x50323643, 0x04000000, 0x00000001}, + {0x50323743, 0x00800000, 0x00000002}, + {0x50323842, 0x01000000, 0x00000001}, + {0x50324241, 0x02000000, 0x00000002}, + {0x50324242, 0x04000000, 0x00000002}, + {0x50324259, 0x04000000, 0x00000002}, + {0x50324341, 0x04000000, 0x00000001}, + {0x50324343, 0x01000000, 0x00000001}, + {0x50324354, 0x00800000, 0x00000001}, + {0x50324359, 0x00000000, 0x00000006}, + {0x50324441, 0x04000000, 0x00000005}, + {0x50324442, 0x01000000, 0x00000002}, + {0x50324459, 0x01000000, 0x00000003}, + {0x50324643, 0x01000000, 0x00000001}, + {0x50324741, 0x08000000, 0x00000001}, + {0x50324743, 0x02000000, 0x00000002}, + {0x50324759, 0x01000000, 0x00000001}, + {0x50324842, 0x02000000, 0x00000003}, + {0x50324854, 0x01000000, 0x00000001}, + {0x50324859, 0x02000000, 0x00000003}, + {0x50324941, 0x04000000, 0x00000002}, + {0x50324943, 0x00800000, 0x00000001}, + {0x50324959, 0x00800000, 0x00000001}, + {0x50324A41, 0x00800000, 0x00000008}, + {0x50324A42, 0x04000000, 0x00000001}, + {0x50324A43, 0x01000000, 0x00000002}, + {0x50324A56, 0x02000000, 0x00000001}, + {0x50324A59, 0x02000000, 0x00000002}, + {0x50324B43, 0x02000000, 0x00000001}, + {0x50324C41, 0x04000000, 0x00000002}, + {0x50324C59, 0x08000000, 0x00000003}, + {0x50325041, 0x02000000, 0x00000001}, + {0x50325042, 0x02000000, 0x00000001}, + {0x50325059, 0x04000000, 0x00000005}, + {0x50325141, 0x02000000, 0x00000002}, + {0x50325254, 0x02000000, 0x00000002}, + {0x50325259, 0x08000000, 0x00000003}, + {0x50325341, 0x01000000, 0x00000001}, + {0x50325359, 0x04000000, 0x00000005}, + {0x50325442, 0x04000000, 0x00000003}, + {0x50325459, 0x00800000, 0x00000001}, + {0x50325559, 0x01000000, 0x00000003}, + {0x50325642, 0x02000000, 0x00000001}, + {0x50325741, 0x02000000, 0x00000003}, + {0x50325759, 0x04000000, 0x00000005}, + {0x50325841, 0x00800000, 0x00000001}, + {0x50325842, 0x00800000, 0x00000001}, + {0x50325A43, 0x01000000, 0x00000003}, + {0x50333441, 0x01000000, 0x00000008}, + {0x50333543, 0x00800000, 0x00000001}, + {0x50333743, 0x00800000, 0x00000002}, + {0x50333842, 0x08000000, 0x00000001}, + {0x50334142, 0x04000000, 0x00000001}, + {0x50334159, 0x00800000, 0x00000001}, + {0x50334241, 0x04000000, 0x00000003}, + {0x50334242, 0x08000000, 0x00000001}, + {0x50334243, 0x02000000, 0x00000002}, + {0x50334259, 0x04000000, 0x00000005}, + {0x50334341, 0x04000000, 0x00000005}, + {0x50334342, 0x00800000, 0x00000001}, + {0x50334354, 0x04000000, 0x00000002}, + {0x50334441, 0x04000000, 0x00000005}, + {0x50334442, 0x04000000, 0x00000001}, + {0x50334444, 0x02000000, 0x00000001}, + {0x50334542, 0x04000000, 0x00000001}, + {0x50334641, 0x00800000, 0x00000001}, + {0x50334643, 0x01000000, 0x00000001}, + {0x50334659, 0x02000000, 0x00000002}, + {0x50334741, 0x04000000, 0x00000005}, + {0x50334743, 0x02000000, 0x00000002}, + {0x50334759, 0x02000000, 0x00000003}, + {0x50334841, 0x02000000, 0x00000003}, + {0x50334842, 0x02000000, 0x00000002}, + {0x50334941, 0x01000000, 0x00000002}, + {0x50334943, 0x04000000, 0x00000001}, + {0x50334959, 0x04000000, 0x00000002}, + {0x50334A43, 0x00800000, 0x00000001}, + {0x50334A54, 0x01000000, 0x00000001}, + {0x50334A56, 0x02000000, 0x00000001}, + {0x50334B41, 0x02000000, 0x00000002}, + {0x50334B59, 0x02000000, 0x00000003}, + {0x50334C41, 0x02000000, 0x00000001}, + {0x50334C43, 0x01000000, 0x00000001}, + {0x50334C59, 0x04000000, 0x00000002}, + {0x50334D43, 0x08000000, 0x00000003}, + {0x50334D54, 0x04000000, 0x00000001}, + {0x50334F41, 0x02000000, 0x00000001}, + {0x50335043, 0x08000000, 0x00000005}, + {0x50335059, 0x02000000, 0x00000008}, + {0x50335141, 0x04000000, 0x00000002}, + {0x50335154, 0x04000000, 0x00000001}, + {0x50335159, 0x04000000, 0x00000002}, + {0x50335341, 0x02000000, 0x00000001}, + {0x50335343, 0x04000000, 0x00000003}, + {0x50335359, 0x00800000, 0x00000001}, + {0x50335459, 0x04000000, 0x00000003}, + {0x50335543, 0x02000000, 0x00000001}, + {0x50335559, 0x02000000, 0x00000001}, + {0x50335741, 0x04000000, 0x00000001}, + {0x50335742, 0x08000000, 0x00000002}, + {0x50335759, 0x01000000, 0x00000001}, + {0x50335842, 0x00800000, 0x00000001}, + {0x50335941, 0x04000000, 0x00000002}, + {0x50343242, 0x00800000, 0x00000001}, + {0x50343243, 0x08000000, 0x00000003}, + {0x50343543, 0x02000000, 0x00000003}, + {0x50343559, 0x02000000, 0x00000008}, + {0x50343741, 0x04000000, 0x00000008}, + {0x50343743, 0x00800000, 0x00000002}, + {0x50344259, 0x02000000, 0x00000001}, + {0x50344341, 0x04000000, 0x00000001}, + {0x50344441, 0x02000000, 0x00000005}, + {0x50344443, 0x00800000, 0x00000001}, + {0x50344456, 0x04000000, 0x00000001}, + {0x50344643, 0x00800000, 0x00000001}, + {0x50344659, 0x08000000, 0x00000003}, + {0x50344759, 0x10000000, 0x00000003}, + {0x50344843, 0x04000000, 0x00000002}, + {0x50344943, 0x04000000, 0x00000002}, + {0x50344A42, 0x00800000, 0x00000001}, + {0x50344A43, 0x01000000, 0x00000001}, + {0x50344A56, 0x02000000, 0x00000001}, + {0x50344C41, 0x00800000, 0x00000001}, + {0x50344D41, 0x00800000, 0x00000002}, + {0x50344D42, 0x00000000, 0x00000002}, + {0x50344D43, 0x01000000, 0x00000003}, + {0x50344D56, 0x02000000, 0x00000002}, + {0x50344E41, 0x04000000, 0x00000001}, + {0x50345059, 0x04000000, 0x00000002}, + {0x50345141, 0x02000000, 0x00000001}, + {0x50345159, 0x00800000, 0x00000002}, + {0x50345242, 0x08000000, 0x00000003}, + {0x50345243, 0x04000000, 0x00000002}, + {0x50345341, 0x04000000, 0x00000003}, + {0x50345442, 0x01000000, 0x00000008}, + {0x50345443, 0x01000000, 0x00000001}, + {0x50345543, 0x02000000, 0x00000002}, + {0x50345659, 0x08000000, 0x00000003}, + {0x50345742, 0x02000000, 0x00000002}, + {0x50345759, 0x04000000, 0x00000003}, + {0x50345842, 0x00800000, 0x00000001}, + {0x50345A43, 0x04000000, 0x00000001}, + {0x50353441, 0x01000000, 0x00000008}, + {0x50353542, 0x00800000, 0x00000001}, + {0x50353643, 0x02000000, 0x00000001}, + {0x50353743, 0x00800000, 0x00000002}, + {0x50353841, 0x02000000, 0x00000008}, + {0x50353859, 0x00800000, 0x00000000}, + {0x50354142, 0x01000000, 0x00000001}, + {0x50354242, 0x00800000, 0x00000002}, + {0x50354259, 0x02000000, 0x00000002}, + {0x50354342, 0x04000000, 0x00000002}, + {0x50354359, 0x00800000, 0x00000008}, + {0x50354443, 0x02000000, 0x00000001}, + {0x50354642, 0x00800000, 0x00000002}, + {0x50354643, 0x00800000, 0x00000002}, + {0x50354741, 0x01000000, 0x00000001}, + {0x50354743, 0x04000000, 0x00000001}, + {0x50354841, 0x02000000, 0x00000002}, + {0x50354943, 0x01000000, 0x00000001}, + {0x50354A42, 0x02000000, 0x00000001}, + {0x50354A54, 0x01000000, 0x00000002}, + {0x50354A59, 0x08000000, 0x00000002}, + {0x50354B43, 0x04000000, 0x00000005}, + {0x50354C41, 0x04000000, 0x00000001}, + {0x50354D43, 0x04000000, 0x00000001}, + {0x50354F41, 0x02000000, 0x00000005}, + {0x50354F42, 0x10000000, 0x00000005}, + {0x50354F43, 0x04000000, 0x00000001}, + {0x50355043, 0x02000000, 0x00000001}, + {0x50355059, 0x01000000, 0x00000001}, + {0x50355141, 0x04000000, 0x00000001}, + {0x50355241, 0x02000000, 0x00000001}, + {0x50355242, 0x01000000, 0x00000002}, + {0x50355259, 0x02000000, 0x00000002}, + {0x50355341, 0x01000000, 0x00000001}, + {0x50355343, 0x04000000, 0x00000001}, + {0x50355359, 0x02000000, 0x00000001}, + {0x50355459, 0x00800000, 0x00000002}, + {0x50355541, 0x00800000, 0x00000001}, + {0x50355643, 0x02000000, 0x00000001}, + {0x50355659, 0x08000000, 0x00000003}, + {0x50355743, 0x00000000, 0x00000001}, + {0x50355759, 0x01000000, 0x00000001}, + {0x50355842, 0x00800000, 0x00000001}, + {0x50355941, 0x08000000, 0x00000003}, + {0x50363241, 0x01000000, 0x00000008}, + {0x50363242, 0x00800000, 0x00000002}, + {0x50363341, 0x04000000, 0x00000008}, + {0x50363442, 0x01000000, 0x00000001}, + {0x50363642, 0x01000000, 0x00000001}, + {0x50363742, 0x02000000, 0x00000001}, + {0x50363743, 0x02000000, 0x00000002}, + {0x50363842, 0x00800000, 0x00000001}, + {0x50363859, 0x00800000, 0x00000000}, + {0x50364241, 0x02000000, 0x00000001}, + {0x50364243, 0x02000000, 0x00000002}, + {0x50364254, 0x02000000, 0x00000001}, + {0x50364341, 0x01000000, 0x00000002}, + {0x50364542, 0x02000000, 0x00000002}, + {0x50364641, 0x02000000, 0x00000002}, + {0x50364642, 0x00800000, 0x00000001}, + {0x50364743, 0x08000000, 0x00000002}, + {0x50364759, 0x04000000, 0x00000002}, + {0x50364841, 0x02000000, 0x00000001}, + {0x50364843, 0x04000000, 0x00000001}, + {0x50364A56, 0x02000000, 0x00000001}, + {0x50364B41, 0x01000000, 0x00000001}, + {0x50364B59, 0x00800000, 0x00000008}, + {0x50364D41, 0x02000000, 0x00000005}, + {0x50364D43, 0x08000000, 0x00000002}, + {0x50364D54, 0x01000000, 0x00000001}, + {0x50364D59, 0x00800000, 0x00000001}, + {0x50364E41, 0x02000000, 0x00000001}, + {0x50365043, 0x00000000, 0x00000002}, + {0x50365059, 0x01000000, 0x00000001}, + {0x50365241, 0x01000000, 0x00000002}, + {0x50365242, 0x02000000, 0x00000002}, + {0x50365259, 0x02000000, 0x00000002}, + {0x50365342, 0x02000000, 0x00000001}, + {0x50365343, 0x04000000, 0x00000002}, + {0x50365359, 0x04000000, 0x00000005}, + {0x50365541, 0x00800000, 0x00000002}, + {0x50365559, 0x04000000, 0x00000002}, + {0x50365642, 0x01000000, 0x00000001}, + {0x50365643, 0x01000000, 0x00000001}, + {0x50365741, 0x00800000, 0x00000001}, + {0x50365743, 0x04000000, 0x00000002}, + {0x50365842, 0x00800000, 0x00000001}, + {0x50365941, 0x00800000, 0x00000005}, + {0x50365942, 0x01000000, 0x00000001}, + {0x50365A41, 0x01000000, 0x00000005}, + {0x50365A42, 0x04000000, 0x00000002}, + {0x50373241, 0x01000000, 0x00000008}, + {0x50373242, 0x00800000, 0x00000001}, + {0x50373243, 0x08000000, 0x00000003}, + {0x50373442, 0x01000000, 0x00000001}, + {0x50373541, 0x01000000, 0x00000008}, + {0x50373743, 0x02000000, 0x00000003}, + {0x50374143, 0x02000000, 0x00000002}, + {0x50374159, 0x02000000, 0x00000002}, + {0x50374241, 0x00800000, 0x00000001}, + {0x50374242, 0x04000000, 0x00000002}, + {0x50374243, 0x02000000, 0x00000002}, + {0x50374259, 0x04000000, 0x00000002}, + {0x50374341, 0x00800000, 0x00000002}, + {0x50374441, 0x04000000, 0x00000005}, + {0x50374443, 0x01000000, 0x00000001}, + {0x50374542, 0x04000000, 0x00000002}, + {0x50374641, 0x02000000, 0x00000002}, + {0x50374642, 0x00800000, 0x00000001}, + {0x50374659, 0x01000000, 0x00000002}, + {0x50374741, 0x04000000, 0x00000002}, + {0x50374943, 0x04000000, 0x00000002}, + {0x50374A42, 0x00800000, 0x00000001}, + {0x50374C41, 0x02000000, 0x00000001}, + {0x50374C43, 0x01000000, 0x00000002}, + {0x50374D54, 0x04000000, 0x00000002}, + {0x50374D59, 0x04000000, 0x00000002}, + {0x50374E41, 0x02000000, 0x00000002}, + {0x50374E43, 0x01000000, 0x00000002}, + {0x50375141, 0x00800000, 0x00000002}, + {0x50375143, 0x04000000, 0x00000001}, + {0x50375241, 0x08000000, 0x00000002}, + {0x50375259, 0x04000000, 0x00000002}, + {0x50375359, 0x02000000, 0x00000001}, + {0x50375443, 0x00800000, 0x00000002}, + {0x50375459, 0x04000000, 0x00000002}, + {0x50375541, 0x02000000, 0x00000002}, + {0x50375542, 0x08000000, 0x00000001}, + {0x50375643, 0x00800000, 0x00000001}, + {0x50375941, 0x08000000, 0x00000005}, + {0x50375942, 0x00800000, 0x00000001}, + {0x50375943, 0x04000000, 0x00000002}, + {0x50383242, 0x04000000, 0x00000001}, + {0x50383259, 0x02000000, 0x00000008}, + {0x50383342, 0x01000000, 0x00000001}, + {0x50383343, 0x04000000, 0x00000005}, + {0x50383541, 0x02000000, 0x00000008}, + {0x50383542, 0x01000000, 0x00000001}, + {0x50383543, 0x04000000, 0x00000001}, + {0x50383642, 0x00800000, 0x00000001}, + {0x50384149, 0x04000000, 0x00000005}, + {0x50384159, 0x01000000, 0x00000002}, + {0x50384241, 0x02000000, 0x00000001}, + {0x50384243, 0x02000000, 0x00000001}, + {0x50384359, 0x01000000, 0x00000002}, + {0x50384443, 0x02000000, 0x00000002}, + {0x50384642, 0x00800000, 0x00000001}, + {0x50384643, 0x04000000, 0x00000002}, + {0x50384659, 0x02000000, 0x00000003}, + {0x50384741, 0x04000000, 0x00000003}, + {0x50384759, 0x08000000, 0x00000005}, + {0x50384841, 0x02000000, 0x00000001}, + {0x50384843, 0x02000000, 0x00000001}, + {0x50384941, 0x02000000, 0x00000002}, + {0x50384A42, 0x04000000, 0x00000002}, + {0x50384C41, 0x04000000, 0x00000001}, + {0x50384C43, 0x04000000, 0x00000002}, + {0x50384D41, 0x01000000, 0x00000001}, + {0x50384D42, 0x04000000, 0x00000001}, + {0x50384D43, 0x02000000, 0x00000002}, + {0x50384E41, 0x00800000, 0x00000001}, + {0x50384F41, 0x04000000, 0x00000003}, + {0x50384F59, 0x08000000, 0x00000003}, + {0x50385043, 0x02000000, 0x00000002}, + {0x50385059, 0x01000000, 0x00000001}, + {0x50385141, 0x00800000, 0x00000002}, + {0x50385143, 0x01000000, 0x00000001}, + {0x50385243, 0x04000000, 0x00000002}, + {0x50385259, 0x02000000, 0x00000002}, + {0x50385342, 0x04000000, 0x00000002}, + {0x50385343, 0x04000000, 0x00000003}, + {0x50385359, 0x04000000, 0x00000001}, + {0x50385442, 0x08000000, 0x00000001}, + {0x50385459, 0x02000000, 0x00000002}, + {0x50385542, 0x04000000, 0x00000001}, + {0x50385543, 0x00800000, 0x00000001}, + {0x50385642, 0x01000000, 0x00000002}, + {0x50385643, 0x04000000, 0x00000002}, + {0x50385741, 0x04000000, 0x00000001}, + {0x50385742, 0x01000000, 0x00000001}, + {0x50385759, 0x08000000, 0x00000005}, + {0x50385859, 0x08000000, 0x00000001}, + {0x50385942, 0x00800000, 0x00000001}, + {0x50385943, 0x10000000, 0x00000003}, + {0x50385A42, 0x01000000, 0x00000001}, + {0x50393241, 0x00800000, 0x00000008}, + {0x50393343, 0x02000000, 0x00000002}, + {0x50393442, 0x04000000, 0x00000001}, + {0x50393443, 0x04000000, 0x00000005}, + {0x50393459, 0x04000000, 0x00000008}, + {0x50393642, 0x01000000, 0x00000001}, + {0x50393643, 0x04000000, 0x00000002}, + {0x50393741, 0x02000000, 0x00000008}, + {0x50393742, 0x02000000, 0x00000001}, + {0x50394159, 0x00800000, 0x00000001}, + {0x50394241, 0x01000000, 0x00000001}, + {0x50394242, 0x02000000, 0x00000001}, + {0x50394243, 0x08000000, 0x00000005}, + {0x50394259, 0x02000000, 0x00000003}, + {0x50394341, 0x04000000, 0x00000001}, + {0x50394441, 0x04000000, 0x00000003}, + {0x50394442, 0x00800000, 0x00000002}, + {0x50394542, 0x04000000, 0x00000002}, + {0x50394543, 0x01000000, 0x00000003}, + {0x50394641, 0x00800000, 0x00000001}, + {0x50394642, 0x00800000, 0x00000001}, + {0x50394643, 0x02000000, 0x00000003}, + {0x50394659, 0x02000000, 0x00000001}, + {0x50394841, 0x04000000, 0x00000005}, + {0x50394943, 0x01000000, 0x00000002}, + {0x50394A59, 0x00800000, 0x00000005}, + {0x50394B42, 0x10000000, 0x00000003}, + {0x50394C42, 0x08000000, 0x00000001}, + {0x50394D41, 0x01000000, 0x00000002}, + {0x50394D43, 0x01000000, 0x00000001}, + {0x50394D59, 0x01000000, 0x00000001}, + {0x50394E41, 0x01000000, 0x00000001}, + {0x50395042, 0x04000000, 0x00000002}, + {0x50395141, 0x04000000, 0x00000001}, + {0x50395242, 0x01000000, 0x00000001}, + {0x50395259, 0x04000000, 0x00000002}, + {0x50395341, 0x02000000, 0x00000001}, + {0x50395343, 0x00000000, 0x00000001}, + {0x50395442, 0x00800000, 0x00000001}, + {0x50395459, 0x04000000, 0x00000003}, + {0x50395542, 0x04000000, 0x00000001}, + {0x50395642, 0x01000000, 0x00000001}, + {0x50395643, 0x01000000, 0x00000001}, + {0x50395742, 0x08000000, 0x00000002}, + {0x50395759, 0x08000000, 0x00000001}, + {0x50395941, 0x08000000, 0x00000003}, + {0x50395943, 0x04000000, 0x00000001}, + {0x50413342, 0x02000000, 0x00000001}, + {0x50413459, 0x04000000, 0x00000008}, + {0x50413541, 0x04000000, 0x00000001}, + {0x50413542, 0x00800000, 0x00000001}, + {0x50413543, 0x02000000, 0x00000002}, + {0x50413641, 0x02000000, 0x00000005}, + {0x50413741, 0x02000000, 0x00000001}, + {0x50413742, 0x00800000, 0x00000001}, + {0x50413842, 0x02000000, 0x00000001}, + {0x50413859, 0x04000000, 0x00000000}, + {0x50414159, 0x04000000, 0x00000002}, + {0x50414241, 0x02000000, 0x00000001}, + {0x50414254, 0x01000000, 0x00000001}, + {0x50414259, 0x02000000, 0x00000002}, + {0x50414341, 0x00800000, 0x00000001}, + {0x50414342, 0x01000000, 0x00000002}, + {0x50414443, 0x04000000, 0x00000002}, + {0x50414541, 0x08000000, 0x00000001}, + {0x50414642, 0x00000000, 0x00000003}, + {0x50414643, 0x08000000, 0x00000002}, + {0x50414754, 0x01000000, 0x00000001}, + {0x50414759, 0x01000000, 0x00000001}, + {0x50414941, 0x04000000, 0x00000001}, + {0x50414A54, 0x00800000, 0x00000001}, + {0x50414B41, 0x08000000, 0x00000005}, + {0x50414B43, 0x04000000, 0x00000002}, + {0x50414C54, 0x00800000, 0x00000001}, + {0x50414C59, 0x00800000, 0x00000002}, + {0x50414D54, 0x00800000, 0x00000001}, + {0x50414E42, 0x02000000, 0x00000001}, + {0x50414E43, 0x02000000, 0x00000001}, + {0x50414F42, 0x04000000, 0x00000001}, + {0x50415042, 0x02000000, 0x00000002}, + {0x50415043, 0x02000000, 0x00000001}, + {0x50415054, 0x02000000, 0x00000001}, + {0x50415141, 0x02000000, 0x00000001}, + {0x50415241, 0x02000000, 0x00000001}, + {0x50415243, 0x00800000, 0x00000001}, + {0x50415254, 0x00800000, 0x00000001}, + {0x50415343, 0x01000000, 0x00000001}, + {0x50415443, 0x04000000, 0x00000001}, + {0x50415543, 0x04000000, 0x00000001}, + {0x50415641, 0x04000000, 0x00000002}, + {0x50415642, 0x00800000, 0x00000001}, + {0x50415741, 0x04000000, 0x00000002}, + {0x50415742, 0x02000000, 0x00000002}, + {0x50415743, 0x00800000, 0x00000001}, + {0x50415941, 0x02000000, 0x00000002}, + {0x50415A42, 0x08000000, 0x00000001}, + {0x50415A43, 0x02000000, 0x00000002}, + {0x50423342, 0x04000000, 0x00000001}, + {0x50423343, 0x00800000, 0x00000001}, + {0x50423442, 0x04000000, 0x00000002}, + {0x50423443, 0x02000000, 0x00000003}, + {0x50423542, 0x04000000, 0x00000002}, + {0x50423543, 0x01000000, 0x00000003}, + {0x50423641, 0x02000000, 0x00000005}, + {0x50423642, 0x04000000, 0x00000001}, + {0x50423643, 0x02000000, 0x00000002}, + {0x50423741, 0x01000000, 0x00000001}, + {0x50423841, 0x00800000, 0x00000002}, + {0x50423842, 0x01000000, 0x00000002}, + {0x50423959, 0x08000000, 0x00000000}, + {0x50424142, 0x01000000, 0x00000002}, + {0x50424243, 0x01000000, 0x00000002}, + {0x50424259, 0x02000000, 0x00000001}, + {0x50424341, 0x04000000, 0x00000003}, + {0x50424354, 0x08000000, 0x00000001}, + {0x50424441, 0x04000000, 0x00000002}, + {0x50424442, 0x04000000, 0x00000002}, + {0x50424443, 0x04000000, 0x00000001}, + {0x50424542, 0x10000000, 0x00000003}, + {0x50424641, 0x00800000, 0x00000001}, + {0x50424642, 0x01000000, 0x00000002}, + {0x50424654, 0x01000000, 0x00000001}, + {0x50424742, 0x00800000, 0x00000002}, + {0x50424841, 0x02000000, 0x00000002}, + {0x50424842, 0x00800000, 0x00000001}, + {0x50424942, 0x01000000, 0x00000003}, + {0x50424959, 0x02000000, 0x00000001}, + {0x50424A42, 0x04000000, 0x00000001}, + {0x50424A59, 0x04000000, 0x00000001}, + {0x50424B41, 0x04000000, 0x00000003}, + {0x50424C42, 0x04000000, 0x00000002}, + {0x50424C43, 0x08000000, 0x00000003}, + {0x50424E43, 0x04000000, 0x00000003}, + {0x50425054, 0x00800000, 0x00000002}, + {0x50425141, 0x02000000, 0x00000001}, + {0x50425159, 0x00800000, 0x00000001}, + {0x50425241, 0x02000000, 0x00000001}, + {0x50425341, 0x04000000, 0x00000002}, + {0x50425343, 0x01000000, 0x00000002}, + {0x50425359, 0x02000000, 0x00000002}, + {0x50425442, 0x04000000, 0x00000002}, + {0x50425543, 0x04000000, 0x00000003}, + {0x50425559, 0x04000000, 0x00000002}, + {0x50425741, 0x00800000, 0x00000001}, + {0x50425742, 0x04000000, 0x00000002}, + {0x50425743, 0x00800000, 0x00000001}, + {0x50425759, 0x02000000, 0x00000002}, + {0x50425855, 0x08000000, 0x00000008}, + {0x50425942, 0x01000000, 0x00000001}, + {0x50425943, 0x04000000, 0x00000001}, + {0x50425959, 0x08000000, 0x00000005}, + {0x50425A41, 0x00800000, 0x00000001}, + {0x50433342, 0x04000000, 0x00000002}, + {0x50433441, 0x02000000, 0x00000003}, + {0x50433459, 0x08000000, 0x00000008}, + {0x50433543, 0x01000000, 0x00000003}, + {0x50433641, 0x02000000, 0x00000005}, + {0x50433643, 0x10000000, 0x00000005}, + {0x50433741, 0x01000000, 0x00000001}, + {0x50433742, 0x00800000, 0x00000002}, + {0x50433841, 0x02000000, 0x00000002}, + {0x50433859, 0x00800000, 0x00000008}, + {0x50434241, 0x04000000, 0x00000005}, + {0x50434259, 0x02000000, 0x00000002}, + {0x50434341, 0x02000000, 0x00000001}, + {0x50434342, 0x04000000, 0x00000002}, + {0x50434354, 0x00800000, 0x00000001}, + {0x50434441, 0x02000000, 0x00000001}, + {0x50434443, 0x04000000, 0x00000003}, + {0x50434541, 0x04000000, 0x00000001}, + {0x50434543, 0x04000000, 0x00000002}, + {0x50434559, 0x02000000, 0x00000001}, + {0x50434641, 0x00800000, 0x00000001}, + {0x50434659, 0x08000000, 0x00000002}, + {0x50434741, 0x04000000, 0x00000003}, + {0x50434742, 0x00800000, 0x00000001}, + {0x50434759, 0x02000000, 0x00000002}, + {0x50434859, 0x00800000, 0x00000001}, + {0x50434941, 0x01000000, 0x00000001}, + {0x50434943, 0x04000000, 0x00000003}, + {0x50434956, 0x08000000, 0x00000002}, + {0x50434A42, 0x04000000, 0x00000002}, + {0x50434A43, 0x04000000, 0x00000002}, + {0x50434A59, 0x04000000, 0x00000002}, + {0x50434C41, 0x01000000, 0x00000008}, + {0x50434C42, 0x04000000, 0x00000002}, + {0x50434C43, 0x02000000, 0x00000001}, + {0x50434D41, 0x02000000, 0x00000005}, + {0x50434D42, 0x01000000, 0x00000001}, + {0x50434D54, 0x04000000, 0x00000003}, + {0x50435041, 0x01000000, 0x00000001}, + {0x50435043, 0x00800000, 0x00000002}, + {0x50435159, 0x01000000, 0x00000001}, + {0x50435242, 0x04000000, 0x00000003}, + {0x50435243, 0x02000000, 0x00000001}, + {0x50435254, 0x04000000, 0x00000001}, + {0x50435341, 0x04000000, 0x00000002}, + {0x50435343, 0x08000000, 0x00000001}, + {0x50435441, 0x04000000, 0x00000005}, + {0x50435442, 0x01000000, 0x00000001}, + {0x50435641, 0x04000000, 0x00000005}, + {0x50435642, 0x00800000, 0x00000001}, + {0x50435759, 0x02000000, 0x00000002}, + {0x50435842, 0x01000000, 0x00000001}, + {0x50435943, 0x02000000, 0x00000002}, + {0x50435959, 0x04000000, 0x00000001}, + {0x50443241, 0x02000000, 0x00000002}, + {0x50443242, 0x02000000, 0x00000002}, + {0x50443343, 0x01000000, 0x00000001}, + {0x50443442, 0x01000000, 0x00000001}, + {0x50443741, 0x01000000, 0x00000001}, + {0x50443841, 0x04000000, 0x00000002}, + {0x50444154, 0x08000000, 0x00000005}, + {0x50444156, 0x02000000, 0x00000001}, + {0x50444159, 0x01000000, 0x00000001}, + {0x50444343, 0x00000000, 0x00000003}, + {0x50444354, 0x02000000, 0x00000001}, + {0x50444441, 0x01000000, 0x00000001}, + {0x50444442, 0x01000000, 0x00000001}, + {0x50444454, 0x00800000, 0x00000001}, + {0x50444459, 0x01000000, 0x00000001}, + {0x50444541, 0x00800000, 0x00000001}, + {0x50444559, 0x00800000, 0x00000001}, + {0x50444641, 0x04000000, 0x00000002}, + {0x50444643, 0x08000000, 0x00000002}, + {0x50444743, 0x01000000, 0x00000001}, + {0x50444759, 0x00800000, 0x00000002}, + {0x50444841, 0x04000000, 0x00000002}, + {0x50444842, 0x04000000, 0x00000001}, + {0x50444859, 0x04000000, 0x00000001}, + {0x50444943, 0x02000000, 0x00000003}, + {0x50444A54, 0x01000000, 0x00000001}, + {0x50444A59, 0x02000000, 0x00000002}, + {0x50444B41, 0x02000000, 0x00000002}, + {0x50444C41, 0x04000000, 0x00000003}, + {0x50444C42, 0x04000000, 0x00000002}, + {0x50444C54, 0x02000000, 0x00000001}, + {0x50444C59, 0x04000000, 0x00000005}, + {0x50444D42, 0x00000000, 0x00000001}, + {0x50444D43, 0x02000000, 0x00000005}, + {0x50444D54, 0x04000000, 0x00000002}, + {0x50444E41, 0x01000000, 0x00000005}, + {0x50444E42, 0x02000000, 0x00000001}, + {0x50444E43, 0x04000000, 0x00000002}, + {0x50445041, 0x02000000, 0x00000002}, + {0x50445042, 0x04000000, 0x00000002}, + {0x50445043, 0x02000000, 0x00000001}, + {0x50445054, 0x08000000, 0x00000001}, + {0x50445059, 0x04000000, 0x00000003}, + {0x50445241, 0x02000000, 0x00000001}, + {0x50445243, 0x01000000, 0x00000001}, + {0x50445259, 0x02000000, 0x00000001}, + {0x50445341, 0x01000000, 0x00000001}, + {0x50445343, 0x02000000, 0x00000001}, + {0x50445441, 0x01000000, 0x00000002}, + {0x50445442, 0x01000000, 0x00000001}, + {0x50445443, 0x04000000, 0x00000002}, + {0x50445641, 0x01000000, 0x00000002}, + {0x50445643, 0x00800000, 0x00000001}, + {0x50445741, 0x02000000, 0x00000005}, + {0x50445743, 0x02000000, 0x00000003}, + {0x50445759, 0x01000000, 0x00000002}, + {0x50445A42, 0x08000000, 0x00000001}, + {0x50453242, 0x00800000, 0x00000001}, + {0x50453341, 0x00800000, 0x00000002}, + {0x50453442, 0x01000000, 0x00000001}, + {0x50453642, 0x02000000, 0x00000001}, + {0x50453643, 0x00800000, 0x00000002}, + {0x50453741, 0x02000000, 0x00000001}, + {0x50454156, 0x02000000, 0x00000001}, + {0x50454254, 0x04000000, 0x00000001}, + {0x50454342, 0x02000000, 0x00000002}, + {0x50454343, 0x00000000, 0x00000005}, + {0x50454359, 0x02000000, 0x00000002}, + {0x50454442, 0x04000000, 0x00000002}, + {0x50454443, 0x00800000, 0x00000001}, + {0x50454542, 0x10000000, 0x00000003}, + {0x50454559, 0x10000000, 0x00000003}, + {0x50454641, 0x04000000, 0x00000003}, + {0x50454659, 0x04000000, 0x00000005}, + {0x50454741, 0x01000000, 0x00000001}, + {0x50454742, 0x04000000, 0x00000001}, + {0x50454841, 0x08000000, 0x00000005}, + {0x50454843, 0x02000000, 0x00000002}, + {0x50454854, 0x01000000, 0x00000001}, + {0x50454A59, 0x01000000, 0x00000001}, + {0x50454B42, 0x04000000, 0x00000002}, + {0x50454C43, 0x02000000, 0x00000001}, + {0x50454C54, 0x02000000, 0x00000001}, + {0x50454C59, 0x02000000, 0x00000001}, + {0x50454D56, 0x02000000, 0x00000001}, + {0x50454F59, 0x01000000, 0x00000005}, + {0x50455141, 0x00800000, 0x00000002}, + {0x50455143, 0x04000000, 0x00000002}, + {0x50455241, 0x04000000, 0x00000001}, + {0x50455341, 0x08000000, 0x00000002}, + {0x50455443, 0x00800000, 0x00000001}, + {0x50455459, 0x02000000, 0x00000003}, + {0x50455542, 0x02000000, 0x00000001}, + {0x50455543, 0x01000000, 0x00000002}, + {0x50455641, 0x01000000, 0x00000001}, + {0x50455642, 0x00800000, 0x00000002}, + {0x50455741, 0x04000000, 0x00000005}, + {0x50455743, 0x01000000, 0x00000002}, + {0x50455842, 0x04000000, 0x00000001}, + {0x50455942, 0x02000000, 0x00000001}, + {0x50455959, 0x00000000, 0x00000002}, + {0x50455A41, 0x08000000, 0x00000006}, + {0x50463259, 0x04000000, 0x00000008}, + {0x50463342, 0x00800000, 0x00000001}, + {0x50463343, 0x00000000, 0x00000002}, + {0x50463541, 0x08000000, 0x00000002}, + {0x50463641, 0x08000000, 0x00000003}, + {0x50463642, 0x08000000, 0x00000001}, + {0x50463741, 0x02000000, 0x00000001}, + {0x50463743, 0x01000000, 0x00000003}, + {0x50464156, 0x02000000, 0x00000001}, + {0x50464159, 0x02000000, 0x00000002}, + {0x50464243, 0x00000000, 0x00000003}, + {0x50464341, 0x04000000, 0x00000002}, + {0x50464342, 0x01000000, 0x00000002}, + {0x50464343, 0x00800000, 0x00000001}, + {0x50464354, 0x04000000, 0x00000002}, + {0x50464441, 0x01000000, 0x00000001}, + {0x50464443, 0x04000000, 0x00000002}, + {0x50464542, 0x00800000, 0x00000001}, + {0x50464543, 0x01000000, 0x00000001}, + {0x50464641, 0x08000000, 0x00000003}, + {0x50464643, 0x00800000, 0x00000005}, + {0x50464741, 0x04000000, 0x00000002}, + {0x50464743, 0x00800000, 0x00000001}, + {0x50464759, 0x01000000, 0x00000001}, + {0x50464841, 0x02000000, 0x00000001}, + {0x50464843, 0x02000000, 0x00000002}, + {0x50464859, 0x00800000, 0x00000002}, + {0x50464943, 0x02000000, 0x00000001}, + {0x50464959, 0x04000000, 0x00000002}, + {0x50464A59, 0x08000000, 0x00000002}, + {0x50464B43, 0x02000000, 0x00000001}, + {0x50464B59, 0x02000000, 0x00000001}, + {0x50464C42, 0x10000000, 0x00000003}, + {0x50464C43, 0x02000000, 0x00000001}, + {0x50464C54, 0x01000000, 0x00000001}, + {0x50464C59, 0x04000000, 0x00000001}, + {0x50464D41, 0x01000000, 0x00000001}, + {0x50464D42, 0x02000000, 0x00000002}, + {0x50464D59, 0x04000000, 0x00000003}, + {0x50464E41, 0x02000000, 0x00000005}, + {0x50464F41, 0x01000000, 0x00000001}, + {0x50465042, 0x04000000, 0x00000002}, + {0x50465054, 0x02000000, 0x00000001}, + {0x50465159, 0x02000000, 0x00000002}, + {0x50465241, 0x08000000, 0x00000003}, + {0x50465242, 0x08000000, 0x00000003}, + {0x50465243, 0x02000000, 0x00000002}, + {0x50465259, 0x02000000, 0x00000002}, + {0x50465341, 0x04000000, 0x00000005}, + {0x50465342, 0x02000000, 0x00000001}, + {0x50465359, 0x04000000, 0x00000001}, + {0x50465441, 0x01000000, 0x00000001}, + {0x50465443, 0x08000000, 0x00000001}, + {0x50465541, 0x04000000, 0x00000002}, + {0x50465543, 0x01000000, 0x00000001}, + {0x50465643, 0x01000000, 0x00000001}, + {0x50465659, 0x02000000, 0x00000001}, + {0x50465743, 0x02000000, 0x00000002}, + {0x50465841, 0x08000000, 0x00000003}, + {0x50465842, 0x04000000, 0x00000001}, + {0x50465943, 0x08000000, 0x00000003}, + {0x50465956, 0x02000000, 0x00000001}, + {0x50465A42, 0x04000000, 0x00000001}, + {0x50473241, 0x02000000, 0x00000003}, + {0x50473459, 0x01000000, 0x00000008}, + {0x50473559, 0x01000000, 0x00000002}, + {0x50473642, 0x01000000, 0x00000001}, + {0x50473742, 0x00800000, 0x00000001}, + {0x50473743, 0x01000000, 0x00000001}, + {0x50473759, 0x08000000, 0x00000008}, + {0x50474142, 0x01000000, 0x00000001}, + {0x50474143, 0x02000000, 0x00000001}, + {0x50474159, 0x04000000, 0x00000001}, + {0x50474243, 0x02000000, 0x00000005}, + {0x50474254, 0x00800000, 0x00000001}, + {0x50474259, 0x00800000, 0x00000001}, + {0x50474354, 0x04000000, 0x00000001}, + {0x50474441, 0x04000000, 0x00000005}, + {0x50474443, 0x04000000, 0x00000006}, + {0x50474541, 0x04000000, 0x00000001}, + {0x50474542, 0x00800000, 0x00000001}, + {0x50474641, 0x04000000, 0x00000001}, + {0x50474659, 0x01000000, 0x00000001}, + {0x50474742, 0x02000000, 0x00000005}, + {0x50474754, 0x00800000, 0x00000001}, + {0x50474842, 0x02000000, 0x00000001}, + {0x50474942, 0x02000000, 0x00000001}, + {0x50474959, 0x02000000, 0x00000001}, + {0x50474B41, 0x02000000, 0x00000002}, + {0x50474B59, 0x10000000, 0x00000003}, + {0x50474C59, 0x04000000, 0x00000001}, + {0x50474D41, 0x01000000, 0x00000001}, + {0x50474D42, 0x02000000, 0x00000001}, + {0x50474D43, 0x04000000, 0x00000001}, + {0x50474D54, 0x04000000, 0x00000002}, + {0x50474E41, 0x08000000, 0x00000005}, + {0x50474E59, 0x08000000, 0x00000003}, + {0x50474F41, 0x00800000, 0x00000001}, + {0x50474F59, 0x08000000, 0x00000003}, + {0x50475041, 0x01000000, 0x00000001}, + {0x50475059, 0x04000000, 0x00000002}, + {0x50475241, 0x02000000, 0x00000005}, + {0x50475243, 0x01000000, 0x00000001}, + {0x50475541, 0x02000000, 0x00000002}, + {0x50475543, 0x02000000, 0x00000002}, + {0x50475842, 0x04000000, 0x00000002}, + {0x50475843, 0x00800000, 0x00000001}, + {0x50475941, 0x04000000, 0x00000002}, + {0x50475956, 0x04000000, 0x00000001}, + {0x50483241, 0x02000000, 0x00000005}, + {0x50483243, 0x02000000, 0x00000002}, + {0x50483341, 0x02000000, 0x00000001}, + {0x50483343, 0x00800000, 0x00000001}, + {0x50483442, 0x02000000, 0x00000001}, + {0x50483741, 0x02000000, 0x00000001}, + {0x50483742, 0x04000000, 0x00000002}, + {0x50483842, 0x04000000, 0x00000002}, + {0x50484159, 0x04000000, 0x00000002}, + {0x50484241, 0x08000000, 0x00000002}, + {0x50484259, 0x02000000, 0x00000002}, + {0x50484341, 0x04000000, 0x00000005}, + {0x50484342, 0x00800000, 0x00000001}, + {0x50484442, 0x02000000, 0x00000002}, + {0x50484459, 0x02000000, 0x00000005}, + {0x50484541, 0x04000000, 0x00000002}, + {0x50484542, 0x01000000, 0x00000002}, + {0x50484559, 0x04000000, 0x00000001}, + {0x50484643, 0x04000000, 0x00000003}, + {0x50484659, 0x04000000, 0x00000002}, + {0x50484742, 0x10000000, 0x00000001}, + {0x50484743, 0x02000000, 0x00000002}, + {0x50484759, 0x08000000, 0x00000001}, + {0x50484841, 0x04000000, 0x00000001}, + {0x50484842, 0x01000000, 0x00000001}, + {0x50484943, 0x04000000, 0x00000002}, + {0x50484959, 0x02000000, 0x00000002}, + {0x50484A42, 0x01000000, 0x00000001}, + {0x50484B43, 0x02000000, 0x00000002}, + {0x50484B56, 0x02000000, 0x00000002}, + {0x50484C41, 0x02000000, 0x00000001}, + {0x50484C42, 0x08000000, 0x00000001}, + {0x50484C54, 0x01000000, 0x00000001}, + {0x50484D41, 0x04000000, 0x00000005}, + {0x50484D42, 0x04000000, 0x00000001}, + {0x50484D54, 0x00800000, 0x00000001}, + {0x50484E41, 0x08000000, 0x00000006}, + {0x50484E43, 0x04000000, 0x00000002}, + {0x50485041, 0x02000000, 0x00000005}, + {0x50485043, 0x04000000, 0x00000001}, + {0x50485243, 0x02000000, 0x00000002}, + {0x50485254, 0x02000000, 0x00000001}, + {0x50485341, 0x02000000, 0x00000002}, + {0x50485441, 0x04000000, 0x00000001}, + {0x50485641, 0x04000000, 0x00000002}, + {0x50485643, 0x04000000, 0x00000002}, + {0x50485741, 0x01000000, 0x00000001}, + {0x50485759, 0x01000000, 0x00000001}, + {0x50485843, 0x02000000, 0x00000001}, + {0x50485959, 0x04000000, 0x00000001}, + {0x50485A42, 0x01000000, 0x00000001}, + {0x50485A59, 0x04000000, 0x00000001}, + {0x50493241, 0x02000000, 0x00000005}, + {0x50493242, 0x04000000, 0x00000001}, + {0x50493341, 0x08000000, 0x00000002}, + {0x50493441, 0x04000000, 0x00000001}, + {0x50493642, 0x04000000, 0x00000002}, + {0x50493741, 0x02000000, 0x00000001}, + {0x50493742, 0x02000000, 0x00000001}, + {0x50493842, 0x04000000, 0x00000001}, + {0x50494159, 0x04000000, 0x00000001}, + {0x50494341, 0x02000000, 0x00000002}, + {0x50494342, 0x02000000, 0x00000002}, + {0x50494359, 0x01000000, 0x00000001}, + {0x50494442, 0x04000000, 0x00000001}, + {0x50494443, 0x02000000, 0x00000001}, + {0x50494542, 0x01000000, 0x00000001}, + {0x50494641, 0x02000000, 0x00000002}, + {0x50494643, 0x08000000, 0x00000003}, + {0x50494659, 0x04000000, 0x00000001}, + {0x50494742, 0x04000000, 0x00000001}, + {0x50494759, 0x00800000, 0x00000002}, + {0x50494842, 0x04000000, 0x00000002}, + {0x50494959, 0x00800000, 0x00000001}, + {0x50494A43, 0x02000000, 0x00000002}, + {0x50494B42, 0x08000000, 0x00000007}, + {0x50494C43, 0x04000000, 0x00000001}, + {0x50494C56, 0x02000000, 0x00000001}, + {0x50494C59, 0x04000000, 0x00000002}, + {0x50494D43, 0x00800000, 0x00000001}, + {0x50494E41, 0x08000000, 0x00000005}, + {0x50494E42, 0x02000000, 0x00000001}, + {0x50494E43, 0x04000000, 0x00000001}, + {0x50494E59, 0x08000000, 0x00000002}, + {0x50494F42, 0x02000000, 0x00000002}, + {0x50495042, 0x00800000, 0x00000001}, + {0x50495043, 0x01000000, 0x00000002}, + {0x50495056, 0x02000000, 0x00000002}, + {0x50495059, 0x02000000, 0x00000003}, + {0x50495141, 0x02000000, 0x00000005}, + {0x50495241, 0x01000000, 0x00000001}, + {0x50495243, 0x02000000, 0x00000002}, + {0x50495259, 0x04000000, 0x00000002}, + {0x50495341, 0x02000000, 0x00000002}, + {0x50495342, 0x04000000, 0x00000001}, + {0x50495441, 0x01000000, 0x00000008}, + {0x50495442, 0x01000000, 0x00000001}, + {0x50495456, 0x02000000, 0x00000001}, + {0x50495541, 0x02000000, 0x00000001}, + {0x50495543, 0x02000000, 0x00000002}, + {0x50495559, 0x04000000, 0x00000002}, + {0x50495641, 0x04000000, 0x00000001}, + {0x50495659, 0x08000000, 0x00000003}, + {0x50495741, 0x08000000, 0x00000005}, + {0x50495742, 0x01000000, 0x00000002}, + {0x50495941, 0x01000000, 0x00000001}, + {0x50495A41, 0x00800000, 0x00000002}, + {0x504A3259, 0x04000000, 0x00000008}, + {0x504A3343, 0x10000000, 0x00000003}, + {0x504A3356, 0x04000000, 0x00000001}, + {0x504A3442, 0x00800000, 0x00000001}, + {0x504A3542, 0x01000000, 0x00000001}, + {0x504A3642, 0x00800000, 0x00000001}, + {0x504A3742, 0x01000000, 0x00000001}, + {0x504A4241, 0x04000000, 0x00000005}, + {0x504A4243, 0x08000000, 0x00000003}, + {0x504A4259, 0x00800000, 0x00000001}, + {0x504A4341, 0x04000000, 0x00000001}, + {0x504A4343, 0x04000000, 0x00000002}, + {0x504A4359, 0x02000000, 0x00000005}, + {0x504A4559, 0x01000000, 0x00000002}, + {0x504A4643, 0x02000000, 0x00000002}, + {0x504A4743, 0x02000000, 0x00000002}, + {0x504A4759, 0x02000000, 0x00000001}, + {0x504A4841, 0x01000000, 0x00000002}, + {0x504A4943, 0x00800000, 0x00000001}, + {0x504A4959, 0x00000000, 0x00000002}, + {0x504A4A43, 0x00800000, 0x00000002}, + {0x504A4B43, 0x02000000, 0x00000001}, + {0x504A4C41, 0x01000000, 0x00000001}, + {0x504A4C42, 0x04000000, 0x00000001}, + {0x504A4C43, 0x08000000, 0x00000002}, + {0x504A4C54, 0x08000000, 0x00000002}, + {0x504A4C59, 0x04000000, 0x00000001}, + {0x504A4D43, 0x01000000, 0x00000002}, + {0x504A4D59, 0x04000000, 0x00000001}, + {0x504A4E41, 0x02000000, 0x00000001}, + {0x504A4E42, 0x01000000, 0x00000001}, + {0x504A4E43, 0x02000000, 0x00000001}, + {0x504A4E59, 0x02000000, 0x00000001}, + {0x504A4F42, 0x04000000, 0x00000002}, + {0x504A5042, 0x00800000, 0x00000001}, + {0x504A5043, 0x04000000, 0x00000002}, + {0x504A5141, 0x08000000, 0x00000001}, + {0x504A5143, 0x00800000, 0x00000001}, + {0x504A5243, 0x02000000, 0x00000001}, + {0x504A5259, 0x08000000, 0x00000002}, + {0x504A5341, 0x04000000, 0x00000005}, + {0x504A5342, 0x01000000, 0x00000001}, + {0x504A5359, 0x00800000, 0x00000001}, + {0x504A5441, 0x01000000, 0x00000002}, + {0x504A5541, 0x04000000, 0x00000001}, + {0x504A5542, 0x08000000, 0x00000001}, + {0x504A5641, 0x04000000, 0x00000002}, + {0x504A5659, 0x01000000, 0x00000001}, + {0x504A5743, 0x00000000, 0x00000001}, + {0x504A5759, 0x00800000, 0x00000002}, + {0x504A5841, 0x08000000, 0x00000003}, + {0x504A5842, 0x00000000, 0x00000001}, + {0x504A5A43, 0x01000000, 0x00000001}, + {0x504B3342, 0x01000000, 0x00000001}, + {0x504B3443, 0x00800000, 0x00000001}, + {0x504B3641, 0x08000000, 0x00000003}, + {0x504B3642, 0x08000000, 0x00000003}, + {0x504B3842, 0x02000000, 0x00000002}, + {0x504B3859, 0x00800000, 0x00000008}, + {0x504B4159, 0x08000000, 0x00000002}, + {0x504B4241, 0x00800000, 0x00000001}, + {0x504B4242, 0x02000000, 0x00000002}, + {0x504B4243, 0x04000000, 0x00000002}, + {0x504B4343, 0x04000000, 0x00000001}, + {0x504B4541, 0x04000000, 0x00000002}, + {0x504B4641, 0x00800000, 0x00000001}, + {0x504B4742, 0x01000000, 0x00000001}, + {0x504B4841, 0x04000000, 0x00000003}, + {0x504B4843, 0x01000000, 0x00000001}, + {0x504B4A59, 0x08000000, 0x00000002}, + {0x504B4B41, 0x01000000, 0x00000003}, + {0x504B4C41, 0x08000000, 0x00000003}, + {0x504B4C43, 0x04000000, 0x00000001}, + {0x504B4C54, 0x10000000, 0x00000002}, + {0x504B4C59, 0x02000000, 0x00000002}, + {0x504B4E41, 0x01000000, 0x00000001}, + {0x504B4E59, 0x04000000, 0x00000002}, + {0x504B5043, 0x02000000, 0x00000008}, + {0x504B5142, 0x01000000, 0x00000001}, + {0x504B5143, 0x04000000, 0x00000001}, + {0x504B5159, 0x02000000, 0x00000001}, + {0x504B5243, 0x00000000, 0x00000001}, + {0x504B5341, 0x04000000, 0x00000002}, + {0x504B5441, 0x04000000, 0x00000002}, + {0x504B5559, 0x04000000, 0x00000001}, + {0x504B5641, 0x01000000, 0x00000001}, + {0x504B5642, 0x04000000, 0x00000002}, + {0x504B5741, 0x04000000, 0x00000003}, + {0x504B5759, 0x04000000, 0x00000002}, + {0x504B5842, 0x02000000, 0x00000001}, + {0x504B5843, 0x04000000, 0x00000001}, + {0x504B5943, 0x02000000, 0x00000002}, + {0x504B5A41, 0x00800000, 0x00000002}, + {0x504C3241, 0x01000000, 0x00000003}, + {0x504C3242, 0x02000000, 0x00000001}, + {0x504C3541, 0x08000000, 0x00000002}, + {0x504C3543, 0x02000000, 0x00000001}, + {0x504C3742, 0x00800000, 0x00000001}, + {0x504C3743, 0x08000000, 0x00000002}, + {0x504C3859, 0x08000000, 0x00000000}, + {0x504C4143, 0x04000000, 0x00000001}, + {0x504C4241, 0x08000000, 0x00000002}, + {0x504C4242, 0x02000000, 0x00000001}, + {0x504C4259, 0x00800000, 0x00000001}, + {0x504C4341, 0x08000000, 0x00000003}, + {0x504C4354, 0x02000000, 0x00000001}, + {0x504C4441, 0x04000000, 0x00000003}, + {0x504C4443, 0x02000000, 0x00000005}, + {0x504C4642, 0x04000000, 0x00000002}, + {0x504C4741, 0x02000000, 0x00000001}, + {0x504C4742, 0x01000000, 0x00000001}, + {0x504C4759, 0x04000000, 0x00000002}, + {0x504C4859, 0x08000000, 0x00000003}, + {0x504C4A41, 0x04000000, 0x00000001}, + {0x504C4A43, 0x02000000, 0x00000002}, + {0x504C4A54, 0x00800000, 0x00000001}, + {0x504C4A59, 0x01000000, 0x00000002}, + {0x504C4D41, 0x02000000, 0x00000002}, + {0x504C4E41, 0x04000000, 0x00000001}, + {0x504C4E59, 0x04000000, 0x00000001}, + {0x504C4F41, 0x00800000, 0x00000001}, + {0x504C4F43, 0x08000000, 0x00000003}, + {0x504C5041, 0x00800000, 0x00000002}, + {0x504C5042, 0x02000000, 0x00000001}, + {0x504C5043, 0x02000000, 0x00000001}, + {0x504C5054, 0x04000000, 0x00000001}, + {0x504C5059, 0x00800000, 0x00000001}, + {0x504C5141, 0x00800000, 0x00000001}, + {0x504C5159, 0x08000000, 0x00000002}, + {0x504C5243, 0x02000000, 0x00000001}, + {0x504C5259, 0x02000000, 0x00000001}, + {0x504C5342, 0x02000000, 0x00000003}, + {0x504C5441, 0x01000000, 0x00000001}, + {0x504C5443, 0x02000000, 0x00000003}, + {0x504C5459, 0x00800000, 0x00000002}, + {0x504C5643, 0x01000000, 0x00000001}, + {0x504C5741, 0x08000000, 0x00000003}, + {0x504C5742, 0x04000000, 0x00000003}, + {0x504C5759, 0x02000000, 0x00000001}, + {0x504C5841, 0x04000000, 0x00000001}, + {0x504C5843, 0x04000000, 0x00000002}, + {0x504C5941, 0x02000000, 0x00000002}, + {0x504C5943, 0x04000000, 0x00000002}, + {0x504C5956, 0x04000000, 0x00000001}, + {0x504C5A41, 0x10000000, 0x00000007}, + {0x504C5A42, 0x00800000, 0x00000002}, + {0x504C5A43, 0x02000000, 0x00000002}, + {0x504D3241, 0x00800000, 0x00000001}, + {0x504D3242, 0x08000000, 0x00000002}, + {0x504D3243, 0x02000000, 0x00000002}, + {0x504D3341, 0x08000000, 0x00000002}, + {0x504D3443, 0x04000000, 0x00000001}, + {0x504D3643, 0x04000000, 0x00000002}, + {0x504D3743, 0x00000000, 0x00000003}, + {0x504D4142, 0x02000000, 0x00000002}, + {0x504D4154, 0x02000000, 0x00000001}, + {0x504D4156, 0x02000000, 0x00000001}, + {0x504D4159, 0x00800000, 0x00000001}, + {0x504D4241, 0x00800000, 0x00000001}, + {0x504D4242, 0x00800000, 0x00000001}, + {0x504D4243, 0x02000000, 0x00000002}, + {0x504D4254, 0x04000000, 0x00000001}, + {0x504D4341, 0x01000000, 0x00000001}, + {0x504D4342, 0x04000000, 0x00000001}, + {0x504D4343, 0x04000000, 0x00000002}, + {0x504D4354, 0x04000000, 0x00000002}, + {0x504D4356, 0x04000000, 0x00000002}, + {0x504D4359, 0x02000000, 0x00000001}, + {0x504D4441, 0x04000000, 0x00000005}, + {0x504D4442, 0x04000000, 0x00000002}, + {0x504D4459, 0x02000000, 0x00000002}, + {0x504D4556, 0x04000000, 0x00000001}, + {0x504D4559, 0x04000000, 0x00000003}, + {0x504D4642, 0x02000000, 0x00000002}, + {0x504D4742, 0x04000000, 0x00000003}, + {0x504D4843, 0x04000000, 0x00000002}, + {0x504D4943, 0x00000000, 0x00000002}, + {0x504D4959, 0x04000000, 0x00000001}, + {0x504D4A54, 0x00800000, 0x00000001}, + {0x504D4C42, 0x02000000, 0x00000001}, + {0x504D4C54, 0x08000000, 0x00000001}, + {0x504D4D59, 0x02000000, 0x00000001}, + {0x504D4E41, 0x04000000, 0x00000005}, + {0x504D4E43, 0x04000000, 0x00000001}, + {0x504D4E59, 0x01000000, 0x00000002}, + {0x504D5042, 0x02000000, 0x00000001}, + {0x504D5043, 0x04000000, 0x00000002}, + {0x504D5141, 0x00800000, 0x00000001}, + {0x504D5143, 0x00000000, 0x00000001}, + {0x504D5241, 0x04000000, 0x00000002}, + {0x504D5242, 0x01000000, 0x00000002}, + {0x504D5259, 0x02000000, 0x00000003}, + {0x504D5341, 0x01000000, 0x00000002}, + {0x504D5342, 0x01000000, 0x00000002}, + {0x504D5343, 0x01000000, 0x00000003}, + {0x504D5442, 0x00800000, 0x00000002}, + {0x504D5459, 0x04000000, 0x00000002}, + {0x504D5642, 0x02000000, 0x00000001}, + {0x504D5643, 0x02000000, 0x00000002}, + {0x504D5742, 0x01000000, 0x00000001}, + {0x504D5842, 0x04000000, 0x00000002}, + {0x504D5A43, 0x02000000, 0x00000001}, + {0x504E3242, 0x02000000, 0x00000001}, + {0x504E3342, 0x02000000, 0x00000001}, + {0x504E3542, 0x01000000, 0x00000001}, + {0x504E3543, 0x01000000, 0x00000001}, + {0x504E3641, 0x08000000, 0x00000003}, + {0x504E3642, 0x00800000, 0x00000001}, + {0x504E3742, 0x08000000, 0x00000003}, + {0x504E3841, 0x02000000, 0x00000005}, + {0x504E3842, 0x01000000, 0x00000001}, + {0x504E4142, 0x01000000, 0x00000002}, + {0x504E4143, 0x02000000, 0x00000005}, + {0x504E4241, 0x08000000, 0x00000002}, + {0x504E4243, 0x02000000, 0x00000001}, + {0x504E4259, 0x04000000, 0x00000007}, + {0x504E4341, 0x01000000, 0x00000002}, + {0x504E4343, 0x00000000, 0x00000001}, + {0x504E4443, 0x08000000, 0x00000001}, + {0x504E4541, 0x04000000, 0x00000002}, + {0x504E4542, 0x00800000, 0x00000001}, + {0x504E4559, 0x00800000, 0x00000001}, + {0x504E4641, 0x02000000, 0x00000002}, + {0x504E4642, 0x00800000, 0x00000001}, + {0x504E4654, 0x04000000, 0x00000002}, + {0x504E4741, 0x02000000, 0x00000001}, + {0x504E4743, 0x04000000, 0x00000002}, + {0x504E4759, 0x04000000, 0x00000002}, + {0x504E4841, 0x02000000, 0x00000001}, + {0x504E4843, 0x02000000, 0x00000002}, + {0x504E4859, 0x00000000, 0x00000003}, + {0x504E4A41, 0x02000000, 0x00000002}, + {0x504E4A42, 0x02000000, 0x00000001}, + {0x504E4C43, 0x02000000, 0x00000002}, + {0x504E4C59, 0x08000000, 0x00000002}, + {0x504E4D54, 0x01000000, 0x00000002}, + {0x504E4D59, 0x01000000, 0x00000002}, + {0x504E4E42, 0x04000000, 0x00000002}, + {0x504E4E59, 0x08000000, 0x00000003}, + {0x504E4F41, 0x02000000, 0x00000005}, + {0x504E4F43, 0x02000000, 0x00000001}, + {0x504E4F59, 0x04000000, 0x00000003}, + {0x504E5041, 0x02000000, 0x00000001}, + {0x504E5042, 0x02000000, 0x00000002}, + {0x504E5043, 0x02000000, 0x00000008}, + {0x504E5142, 0x04000000, 0x00000001}, + {0x504E5159, 0x04000000, 0x00000002}, + {0x504E5241, 0x02000000, 0x00000001}, + {0x504E5243, 0x01000000, 0x00000001}, + {0x504E5341, 0x00800000, 0x00000002}, + {0x504E5342, 0x02000000, 0x00000001}, + {0x504E5343, 0x08000000, 0x00000003}, + {0x504E5359, 0x04000000, 0x00000002}, + {0x504E5442, 0x04000000, 0x00000002}, + {0x504E5443, 0x01000000, 0x00000002}, + {0x504E5642, 0x04000000, 0x00000001}, + {0x504E5656, 0x02000000, 0x00000002}, + {0x504E5A43, 0x04000000, 0x00000002}, + {0x504F3241, 0x04000000, 0x00000003}, + {0x504F3341, 0x01000000, 0x00000001}, + {0x504F3441, 0x02000000, 0x00000005}, + {0x504F3442, 0x00800000, 0x00000001}, + {0x504F3541, 0x01000000, 0x00000001}, + {0x504F3543, 0x01000000, 0x00000001}, + {0x504F3642, 0x02000000, 0x00000001}, + {0x504F3743, 0x04000000, 0x00000002}, + {0x504F3959, 0x00800000, 0x00000000}, + {0x504F4142, 0x04000000, 0x00000001}, + {0x504F4143, 0x02000000, 0x00000001}, + {0x504F4156, 0x04000000, 0x00000001}, + {0x504F4241, 0x02000000, 0x00000001}, + {0x504F4259, 0x08000000, 0x00000003}, + {0x504F4341, 0x04000000, 0x00000005}, + {0x504F4342, 0x01000000, 0x00000001}, + {0x504F4359, 0x04000000, 0x00000001}, + {0x504F4742, 0x00800000, 0x00000002}, + {0x504F4743, 0x01000000, 0x00000001}, + {0x504F4759, 0x02000000, 0x00000001}, + {0x504F4842, 0x04000000, 0x00000001}, + {0x504F4843, 0x02000000, 0x00000001}, + {0x504F4941, 0x08000000, 0x00000005}, + {0x504F4942, 0x02000000, 0x00000001}, + {0x504F4959, 0x00800000, 0x00000001}, + {0x504F4A42, 0x04000000, 0x00000001}, + {0x504F4A43, 0x04000000, 0x00000002}, + {0x504F4C42, 0x00800000, 0x00000001}, + {0x504F4D41, 0x04000000, 0x00000002}, + {0x504F4D59, 0x04000000, 0x00000001}, + {0x504F4E41, 0x02000000, 0x00000002}, + {0x504F4E42, 0x01000000, 0x00000001}, + {0x504F4F42, 0x00400000, 0x00000002}, + {0x504F4F43, 0x04000000, 0x00000002}, + {0x504F5043, 0x01000000, 0x00000002}, + {0x504F5059, 0x04000000, 0x00000003}, + {0x504F5143, 0x02000000, 0x00000001}, + {0x504F5159, 0x00800000, 0x00000001}, + {0x504F5259, 0x04000000, 0x00000002}, + {0x504F5342, 0x02000000, 0x00000001}, + {0x504F5343, 0x00000000, 0x00000002}, + {0x504F5359, 0x01000000, 0x00000002}, + {0x504F5541, 0x00800000, 0x00000001}, + {0x504F5741, 0x02000000, 0x00000002}, + {0x504F5743, 0x00800000, 0x00000001}, + {0x504F5759, 0x00800000, 0x00000001}, + {0x504F5841, 0x01000000, 0x00000002}, + {0x504F5843, 0x04000000, 0x00000001}, + {0x504F5A42, 0x04000000, 0x00000003}, + {0x504F5A43, 0x02000000, 0x00000001}, + {0x50503342, 0x04000000, 0x00000001}, + {0x50503343, 0x04000000, 0x00000002}, + {0x50503441, 0x02000000, 0x00000002}, + {0x50503541, 0x04000000, 0x00000001}, + {0x50503643, 0x04000000, 0x00000007}, + {0x50503659, 0x04000000, 0x00000008}, + {0x50504143, 0x02000000, 0x00000003}, + {0x50504159, 0x01000000, 0x00000001}, + {0x50504243, 0x01000000, 0x00000002}, + {0x50504259, 0x02000000, 0x00000001}, + {0x50504341, 0x01000000, 0x00000002}, + {0x50504441, 0x00800000, 0x00000002}, + {0x50504442, 0x00800000, 0x00000001}, + {0x50504443, 0x00000000, 0x00000002}, + {0x50504459, 0x02000000, 0x00000001}, + {0x50504542, 0x01000000, 0x00000002}, + {0x50504543, 0x08000000, 0x00000002}, + {0x50504741, 0x04000000, 0x00000002}, + {0x50504742, 0x04000000, 0x00000002}, + {0x50504743, 0x02000000, 0x00000001}, + {0x50504754, 0x02000000, 0x00000001}, + {0x50504841, 0x04000000, 0x00000001}, + {0x50504941, 0x00800000, 0x00000008}, + {0x50504A41, 0x00800000, 0x00000001}, + {0x50504A43, 0x04000000, 0x00000002}, + {0x50504B41, 0x01000000, 0x00000001}, + {0x50504C42, 0x04000000, 0x00000002}, + {0x50504C43, 0x04000000, 0x00000003}, + {0x50504C59, 0x00800000, 0x00000002}, + {0x50504D43, 0x04000000, 0x00000001}, + {0x50504D44, 0x10000000, 0xFFFFFFFF}, + {0x50504E41, 0x01000000, 0x00000001}, + {0x50504E42, 0x04000000, 0x00000001}, + {0x50504E43, 0x01000000, 0x00000002}, + {0x50504E59, 0x04000000, 0x00000002}, + {0x50504F43, 0x01000000, 0x00000003}, + {0x50505041, 0x01000000, 0x00000002}, + {0x50505141, 0x02000000, 0x00000002}, + {0x50505143, 0x01000000, 0x00000001}, + {0x50505241, 0x04000000, 0x00000001}, + {0x50505242, 0x08000000, 0x00000002}, + {0x50505341, 0x02000000, 0x00000003}, + {0x50505343, 0x02000000, 0x00000003}, + {0x50505359, 0x02000000, 0x00000005}, + {0x50505543, 0x00800000, 0x00000001}, + {0x50505642, 0x08000000, 0x00000006}, + {0x50505659, 0x08000000, 0x00000003}, + {0x50505741, 0x01000000, 0x00000001}, + {0x50505742, 0x00800000, 0x00000001}, + {0x50505743, 0x02000000, 0x00000002}, + {0x50505841, 0x02000000, 0x00000005}, + {0x50505843, 0x02000000, 0x00000001}, + {0x50505943, 0x04000000, 0x00000002}, + {0x50505A41, 0x01000000, 0x00000002}, + {0x50505A42, 0x01000000, 0x00000001}, + {0x50505A55, 0x08000000, 0x00000003}, + {0x50513243, 0x00800000, 0x00000001}, + {0x50513342, 0x00800000, 0x00000001}, + {0x50513543, 0x01000000, 0x00000002}, + {0x50513642, 0x00800000, 0x00000001}, + {0x50513643, 0x08000000, 0x00000001}, + {0x50513841, 0x02000000, 0x00000005}, + {0x50513842, 0x00800000, 0x00000001}, + {0x50513859, 0x00800000, 0x00000000}, + {0x50514143, 0x02000000, 0x00000002}, + {0x50514242, 0x00800000, 0x00000001}, + {0x50514243, 0x02000000, 0x00000002}, + {0x50514259, 0x02000000, 0x00000002}, + {0x50514359, 0x04000000, 0x00000002}, + {0x50514459, 0x10000000, 0x00000003}, + {0x50514559, 0x00800000, 0x00000001}, + {0x50514641, 0x04000000, 0x00000002}, + {0x50514642, 0x00800000, 0x00000001}, + {0x50514742, 0x02000000, 0x00000002}, + {0x50514743, 0x04000000, 0x00000003}, + {0x50514759, 0x04000000, 0x00000002}, + {0x50514841, 0x02000000, 0x00000001}, + {0x50514943, 0x02000000, 0x00000002}, + {0x50514A41, 0x04000000, 0x00000002}, + {0x50514A43, 0x00800000, 0x00000002}, + {0x50514A59, 0x01000000, 0x00000001}, + {0x50514B41, 0x02000000, 0x00000001}, + {0x50514B43, 0x02000000, 0x00000001}, + {0x50514C41, 0x00800000, 0x00000001}, + {0x50514C43, 0x04000000, 0x00000001}, + {0x50514D41, 0x04000000, 0x00000005}, + {0x50514D42, 0x04000000, 0x00000001}, + {0x50514D54, 0x02000000, 0x00000002}, + {0x50514E41, 0x00800000, 0x00000002}, + {0x50514E42, 0x02000000, 0x00000001}, + {0x50514F41, 0x01000000, 0x00000001}, + {0x50514F43, 0x04000000, 0x00000002}, + {0x50515043, 0x02000000, 0x00000001}, + {0x50515141, 0x02000000, 0x00000002}, + {0x50515143, 0x04000000, 0x00000001}, + {0x50515243, 0x02000000, 0x00000001}, + {0x50515259, 0x02000000, 0x00000001}, + {0x50515341, 0x01000000, 0x00000002}, + {0x50515343, 0x01000000, 0x00000001}, + {0x50515359, 0x02000000, 0x00000002}, + {0x50515442, 0x01000000, 0x00000001}, + {0x50515641, 0x02000000, 0x00000002}, + {0x50515643, 0x02000000, 0x00000002}, + {0x50515741, 0x01000000, 0x00000001}, + {0x50515743, 0x02000000, 0x00000001}, + {0x50515842, 0x04000000, 0x00000001}, + {0x50515941, 0x01000000, 0x00000002}, + {0x50515943, 0x04000000, 0x00000001}, + {0x50515A41, 0x01000000, 0x00000002}, + {0x50523341, 0x01000000, 0x00000002}, + {0x50523342, 0x08000000, 0x00000005}, + {0x50523443, 0x02000000, 0x00000001}, + {0x50523459, 0x04000000, 0x00000008}, + {0x50523542, 0x10000000, 0x00000001}, + {0x50523559, 0x04000000, 0x00000008}, + {0x50523642, 0x08000000, 0x00000002}, + {0x50523743, 0x00800000, 0x00000001}, + {0x50524241, 0x04000000, 0x00000002}, + {0x50524243, 0x01000000, 0x00000002}, + {0x50524254, 0x04000000, 0x00000001}, + {0x50524255, 0x00800000, 0x00000005}, + {0x50524259, 0x04000000, 0x00000001}, + {0x50524341, 0x02000000, 0x00000001}, + {0x50524343, 0x00800000, 0x00000002}, + {0x50524354, 0x00800000, 0x00000001}, + {0x50524441, 0x01000000, 0x00000002}, + {0x50524442, 0x04000000, 0x00000005}, + {0x50524459, 0x00800000, 0x00000001}, + {0x50524541, 0x01000000, 0x00000002}, + {0x50524543, 0x02000000, 0x00000003}, + {0x50524554, 0x00800000, 0x00000001}, + {0x50524559, 0x04000000, 0x00000003}, + {0x50524641, 0x04000000, 0x00000001}, + {0x50524659, 0x01000000, 0x00000001}, + {0x50524741, 0x02000000, 0x00000005}, + {0x50524754, 0x01000000, 0x00000001}, + {0x50524841, 0x02000000, 0x00000002}, + {0x50524942, 0x01000000, 0x00000001}, + {0x50524943, 0x04000000, 0x00000002}, + {0x50524A41, 0x08000000, 0x00000005}, + {0x50524A42, 0x01000000, 0x00000001}, + {0x50524A43, 0x08000000, 0x00000003}, + {0x50524C42, 0x10000000, 0x00000001}, + {0x50524C43, 0x04000000, 0x00000003}, + {0x50524C54, 0x08000000, 0x00000001}, + {0x50524D43, 0x02000000, 0x00000002}, + {0x50524D59, 0x01000000, 0x00000001}, + {0x50524E41, 0x04000000, 0x00000001}, + {0x50524E42, 0x04000000, 0x00000003}, + {0x50524E43, 0x04000000, 0x00000002}, + {0x50524F55, 0x08000000, 0x00000008}, + {0x50525041, 0x02000000, 0x00000002}, + {0x50525042, 0x00800000, 0x00000001}, + {0x50525054, 0x02000000, 0x00000001}, + {0x50525059, 0x02000000, 0x00000002}, + {0x50525141, 0x01000000, 0x00000002}, + {0x50525143, 0x04000000, 0x00000002}, + {0x50525159, 0x02000000, 0x00000001}, + {0x50525254, 0x01000000, 0x00000001}, + {0x50525259, 0x02000000, 0x00000002}, + {0x50525359, 0x01000000, 0x00000005}, + {0x50525441, 0x01000000, 0x00000002}, + {0x50525442, 0x02000000, 0x00000002}, + {0x50525443, 0x02000000, 0x00000003}, + {0x50525459, 0x00000000, 0x00000001}, + {0x50525741, 0x02000000, 0x00000005}, + {0x50525743, 0x02000000, 0x00000001}, + {0x50525759, 0x04000000, 0x00000001}, + {0x50525843, 0x04000000, 0x00000001}, + {0x50525941, 0x00800000, 0x00000001}, + {0x50525943, 0x02000000, 0x00000001}, + {0x50525959, 0x04000000, 0x00000001}, + {0x50525A43, 0x02000000, 0x00000001}, + {0x50533242, 0x08000000, 0x00000002}, + {0x50533243, 0x08000000, 0x00000004}, + {0x50533341, 0x02000000, 0x00000001}, + {0x50533343, 0x01000000, 0x00000002}, + {0x50533543, 0x08000000, 0x00000001}, + {0x50533641, 0x04000000, 0x00000001}, + {0x50533642, 0x04000000, 0x00000001}, + {0x50533659, 0x04000000, 0x00000008}, + {0x50533759, 0x04000000, 0x00000008}, + {0x50533841, 0x00800000, 0x00000002}, + {0x50534143, 0x02000000, 0x00000001}, + {0x50534156, 0x02000000, 0x00000001}, + {0x50534359, 0x00800000, 0x00000001}, + {0x50534443, 0x08000000, 0x00000001}, + {0x50534556, 0x04000000, 0x00000001}, + {0x50534641, 0x02000000, 0x00000002}, + {0x50534643, 0x02000000, 0x00000001}, + {0x50534743, 0x08000000, 0x00000001}, + {0x50534759, 0x04000000, 0x00000003}, + {0x50534841, 0x02000000, 0x00000002}, + {0x50534843, 0x02000000, 0x00000001}, + {0x50534859, 0x02000000, 0x00000003}, + {0x50534941, 0x01000000, 0x00000001}, + {0x50534943, 0x04000000, 0x00000001}, + {0x50534959, 0x04000000, 0x00000002}, + {0x50534A42, 0x04000000, 0x00000003}, + {0x50534A43, 0x01000000, 0x00000002}, + {0x50534A54, 0x00800000, 0x00000001}, + {0x50534C42, 0x04000000, 0x00000001}, + {0x50534C54, 0x02000000, 0x00000001}, + {0x50534D43, 0x02000000, 0x00000003}, + {0x50534D54, 0x01000000, 0x00000001}, + {0x50534E41, 0x01000000, 0x00000001}, + {0x50534F41, 0x08000000, 0x00000005}, + {0x50534F43, 0x02000000, 0x00000001}, + {0x50535042, 0x04000000, 0x00000002}, + {0x50535043, 0x04000000, 0x00000002}, + {0x50535143, 0x02000000, 0x00000001}, + {0x50535154, 0x00800000, 0x00000001}, + {0x50535159, 0x02000000, 0x00000002}, + {0x50535243, 0x00800000, 0x00000001}, + {0x50535341, 0x04000000, 0x00000002}, + {0x50535343, 0x00800000, 0x00000001}, + {0x50535459, 0x01000000, 0x00000001}, + {0x50535541, 0x04000000, 0x00000001}, + {0x50535542, 0x00800000, 0x00000002}, + {0x50535543, 0x02000000, 0x00000001}, + {0x50535559, 0x00800000, 0x00000001}, + {0x50535641, 0x02000000, 0x00000002}, + {0x50535643, 0x02000000, 0x00000001}, + {0x50535659, 0x02000000, 0x00000003}, + {0x50535741, 0x01000000, 0x00000002}, + {0x50535743, 0x00000000, 0x00000002}, + {0x50535842, 0x04000000, 0x00000003}, + {0x50535843, 0x00000000, 0x00000001}, + {0x50535941, 0x04000000, 0x00000001}, + {0x50543241, 0x02000000, 0x00000001}, + {0x50543341, 0x02000000, 0x00000002}, + {0x50543343, 0x08000000, 0x00000003}, + {0x50543442, 0x01000000, 0x00000002}, + {0x50543541, 0x04000000, 0x00000005}, + {0x50543641, 0x04000000, 0x00000001}, + {0x50543642, 0x04000000, 0x00000001}, + {0x50543643, 0x01000000, 0x00000002}, + {0x50543743, 0x01000000, 0x00000002}, + {0x50543841, 0x02000000, 0x00000002}, + {0x50544142, 0x04000000, 0x00000002}, + {0x50544143, 0x02000000, 0x00000002}, + {0x50544159, 0x01000000, 0x00000002}, + {0x50544241, 0x02000000, 0x00000001}, + {0x50544243, 0x02000000, 0x00000001}, + {0x50544254, 0x01000000, 0x00000001}, + {0x50544256, 0x02000000, 0x00000002}, + {0x50544259, 0x08000000, 0x00000003}, + {0x50544341, 0x02000000, 0x00000001}, + {0x50544459, 0x04000000, 0x00000003}, + {0x50544556, 0x08000000, 0x00000007}, + {0x50544559, 0x01000000, 0x00000001}, + {0x50544641, 0x00800000, 0x00000001}, + {0x50544642, 0x01000000, 0x00000001}, + {0x50544659, 0x08000000, 0x00000005}, + {0x50544742, 0x08000000, 0x00000002}, + {0x50544754, 0x04000000, 0x00000002}, + {0x50544759, 0x02000000, 0x00000001}, + {0x50544841, 0x01000000, 0x00000001}, + {0x50544941, 0x00800000, 0x00000001}, + {0x50544943, 0x01000000, 0x00000001}, + {0x50544A41, 0x02000000, 0x00000001}, + {0x50544A56, 0x04000000, 0x00000001}, + {0x50544B43, 0x04000000, 0x00000002}, + {0x50544C41, 0x00800000, 0x00000001}, + {0x50544C59, 0x08000000, 0x00000002}, + {0x50544D41, 0x04000000, 0x00000002}, + {0x50544D43, 0x02000000, 0x00000001}, + {0x50544D54, 0x04000000, 0x00000003}, + {0x50544D59, 0x02000000, 0x00000002}, + {0x50544F43, 0x02000000, 0x00000001}, + {0x50545041, 0x01000000, 0x00000002}, + {0x50545054, 0x08000000, 0x00000001}, + {0x50545059, 0x02000000, 0x00000005}, + {0x50545154, 0x02000000, 0x00000002}, + {0x50545259, 0x02000000, 0x00000002}, + {0x50545341, 0x02000000, 0x00000001}, + {0x50545359, 0x04000000, 0x00000001}, + {0x50545456, 0x04000000, 0x00000001}, + {0x50545541, 0x02000000, 0x00000001}, + {0x50545542, 0x02000000, 0x00000001}, + {0x50545559, 0x04000000, 0x00000002}, + {0x50545642, 0x01000000, 0x00000001}, + {0x50545643, 0x02000000, 0x00000001}, + {0x50545659, 0x02000000, 0x00000001}, + {0x50545841, 0x00800000, 0x00000001}, + {0x50545942, 0x08000000, 0x00000002}, + {0x50545959, 0x02000000, 0x00000002}, + {0x50545A41, 0x01000000, 0x00000005}, + {0x50545A59, 0x01000000, 0x00000005}, + {0x50553242, 0x02000000, 0x00000001}, + {0x50553342, 0x02000000, 0x00000002}, + {0x50553459, 0x02000000, 0x00000008}, + {0x50553541, 0x02000000, 0x00000005}, + {0x50553659, 0x01000000, 0x00000008}, + {0x50553743, 0x02000000, 0x00000001}, + {0x50553842, 0x01000000, 0x00000001}, + {0x50554159, 0x04000000, 0x00000003}, + {0x50554241, 0x04000000, 0x00000005}, + {0x50554242, 0x08000000, 0x00000003}, + {0x50554259, 0x08000000, 0x00000003}, + {0x50554359, 0x00000000, 0x00000003}, + {0x50554442, 0x02000000, 0x00000001}, + {0x50554443, 0x01000000, 0x00000003}, + {0x50554454, 0x00800000, 0x00000001}, + {0x50554641, 0x01000000, 0x00000003}, + {0x50554643, 0x02000000, 0x00000002}, + {0x50554842, 0x04000000, 0x00000001}, + {0x50554854, 0x02000000, 0x00000001}, + {0x50554859, 0x00800000, 0x00000008}, + {0x50554943, 0x04000000, 0x00000002}, + {0x50554B41, 0x04000000, 0x00000001}, + {0x50554B42, 0x08000000, 0x00000005}, + {0x50554C41, 0x02000000, 0x00000002}, + {0x50554C54, 0x04000000, 0x00000001}, + {0x50554C59, 0x08000000, 0x00000005}, + {0x50554D41, 0x00800000, 0x00000001}, + {0x50554D42, 0x04000000, 0x00000001}, + {0x50554D43, 0x01000000, 0x00000003}, + {0x50554D54, 0x04000000, 0x00000003}, + {0x50554D59, 0x04000000, 0x00000002}, + {0x50554E41, 0x01000000, 0x00000001}, + {0x50554E42, 0x01000000, 0x00000001}, + {0x50554F42, 0x02000000, 0x00000001}, + {0x50555054, 0x01000000, 0x00000001}, + {0x50555059, 0x02000000, 0x00000008}, + {0x50555154, 0x00800000, 0x00000001}, + {0x50555159, 0x08000000, 0x00000003}, + {0x50555341, 0x04000000, 0x00000003}, + {0x50555342, 0x02000000, 0x00000001}, + {0x50555343, 0x02000000, 0x00000001}, + {0x50555442, 0x04000000, 0x00000002}, + {0x50555542, 0x04000000, 0x00000001}, + {0x50555741, 0x02000000, 0x00000001}, + {0x50555743, 0x04000000, 0x00000001}, + {0x50555841, 0x02000000, 0x00000001}, + {0x50555842, 0x04000000, 0x00000001}, + {0x50555843, 0x08000000, 0x00000002}, + {0x50555942, 0x00800000, 0x00000001}, + {0x50555943, 0x01000000, 0x00000002}, + {0x50555959, 0x04000000, 0x00000001}, + {0x50555A42, 0x02000000, 0x00000002}, + {0x50563241, 0x00800000, 0x00000001}, + {0x50563342, 0x02000000, 0x00000001}, + {0x50563343, 0x01000000, 0x00000001}, + {0x50563443, 0x01000000, 0x00000001}, + {0x50563643, 0x02000000, 0x00000001}, + {0x50563743, 0x00800000, 0x00000001}, + {0x50564143, 0x02000000, 0x00000002}, + {0x50564159, 0x04000000, 0x00000002}, + {0x50564242, 0x00800000, 0x00000001}, + {0x50564243, 0x04000000, 0x00000002}, + {0x50564341, 0x04000000, 0x00000002}, + {0x50564359, 0x01000000, 0x00000003}, + {0x50564441, 0x01000000, 0x00000001}, + {0x50564442, 0x00000000, 0x00000001}, + {0x50564443, 0x01000000, 0x00000001}, + {0x50564454, 0x07FFEC70, 0x00000003}, + {0x50564641, 0x04000000, 0x00000001}, + {0x50564642, 0x00800000, 0x00000001}, + {0x50564741, 0x02000000, 0x00000002}, + {0x50564841, 0x01000000, 0x00000001}, + {0x50564842, 0x02000000, 0x00000001}, + {0x50564843, 0x02000000, 0x00000003}, + {0x50564854, 0x04000000, 0x00000001}, + {0x50564942, 0x00800000, 0x00000001}, + {0x50564959, 0x08000000, 0x00000003}, + {0x50564A56, 0x04000000, 0x00000001}, + {0x50564C41, 0x01000000, 0x00000002}, + {0x50564C43, 0x04000000, 0x00000001}, + {0x50564C54, 0x02000000, 0x00000002}, + {0x50564D41, 0x04000000, 0x00000001}, + {0x50564D42, 0x00800000, 0x00000001}, + {0x50564D43, 0x00800000, 0x00000001}, + {0x50564D54, 0x04000000, 0x00000002}, + {0x50564E42, 0x02000000, 0x00000001}, + {0x50564E43, 0x10000000, 0x00000005}, + {0x50565042, 0x00800000, 0x00000002}, + {0x50565043, 0x04000000, 0x00000002}, + {0x50565059, 0x04000000, 0x00000001}, + {0x50565141, 0x01000000, 0x00000002}, + {0x50565143, 0x04000000, 0x00000001}, + {0x50565159, 0x01000000, 0x00000001}, + {0x50565243, 0x02000000, 0x00000001}, + {0x50565259, 0x02000000, 0x00000005}, + {0x50565341, 0x00800000, 0x00000001}, + {0x50565342, 0x02000000, 0x00000001}, + {0x50565343, 0x02000000, 0x00000005}, + {0x50565441, 0x02000000, 0x00000001}, + {0x50565442, 0x02000000, 0x00000002}, + {0x50565443, 0x04000000, 0x00000003}, + {0x50565459, 0x08000000, 0x00000003}, + {0x50565542, 0x02000000, 0x00000002}, + {0x50565642, 0x01000000, 0x00000002}, + {0x50565741, 0x01000000, 0x00000001}, + {0x50565742, 0x02000000, 0x00000001}, + {0x50565756, 0x04000000, 0x00000001}, + {0x50565841, 0x04000000, 0x00000003}, + {0x50565842, 0x02000000, 0x00000001}, + {0x50565859, 0x00800000, 0x00000001}, + {0x50565A41, 0x00800000, 0x00000001}, + {0x50565A43, 0x02000000, 0x00000001}, + {0x50573259, 0x04000000, 0x00000008}, + {0x50573341, 0x04000000, 0x00000002}, + {0x50573641, 0x02000000, 0x00000002}, + {0x50573643, 0x02000000, 0x00000002}, + {0x50573742, 0x01000000, 0x00000002}, + {0x50573759, 0x01000000, 0x00000001}, + {0x50574142, 0x02000000, 0x00000001}, + {0x50574159, 0x04000000, 0x00000002}, + {0x50574259, 0x01000000, 0x00000002}, + {0x50574343, 0x02000000, 0x00000001}, + {0x50574354, 0x02000000, 0x00000001}, + {0x50574442, 0x02000000, 0x00000001}, + {0x50574443, 0x00800000, 0x00000001}, + {0x50574459, 0x02000000, 0x00000005}, + {0x50574542, 0x04000000, 0x00000002}, + {0x50574641, 0x01000000, 0x00000001}, + {0x50574741, 0x01000000, 0x00000002}, + {0x50574759, 0x00800000, 0x00000001}, + {0x50574843, 0x02000000, 0x00000002}, + {0x50574859, 0x02000000, 0x00000001}, + {0x50574942, 0x04000000, 0x00000002}, + {0x50574A43, 0x00800000, 0x00000001}, + {0x50574A59, 0x00800000, 0x00000001}, + {0x50574B41, 0x04000000, 0x00000002}, + {0x50574B42, 0x00800000, 0x00000002}, + {0x50574B59, 0x08000000, 0x00000003}, + {0x50574C41, 0x02000000, 0x00000001}, + {0x50574C43, 0x10000000, 0x00000002}, + {0x50574C54, 0x02000000, 0x00000002}, + {0x50574C59, 0x02000000, 0x00000001}, + {0x50574D41, 0x04000000, 0x00000002}, + {0x50574D43, 0x02000000, 0x00000002}, + {0x50574D49, 0x04000000, 0x00000007}, + {0x50574D54, 0x01000000, 0x00000001}, + {0x50574D59, 0x01000000, 0x00000002}, + {0x50574E41, 0x02000000, 0x00000002}, + {0x50574E42, 0x02000000, 0x00000001}, + {0x50574E59, 0x02000000, 0x00000001}, + {0x50574F41, 0x00800000, 0x00000001}, + {0x50575041, 0x02000000, 0x00000001}, + {0x50575042, 0x01000000, 0x00000001}, + {0x50575043, 0x04000000, 0x00000002}, + {0x50575054, 0x00800000, 0x00000002}, + {0x50575141, 0x01000000, 0x00000001}, + {0x50575159, 0x00800000, 0x00000001}, + {0x50575243, 0x02000000, 0x00000002}, + {0x50575254, 0x04000000, 0x00000002}, + {0x50575259, 0x02000000, 0x00000005}, + {0x50575343, 0x04000000, 0x00000001}, + {0x50575442, 0x02000000, 0x00000001}, + {0x50575443, 0x08000000, 0x00000001}, + {0x50575542, 0x02000000, 0x00000001}, + {0x50575559, 0x02000000, 0x00000002}, + {0x50575641, 0x02000000, 0x00000002}, + {0x50575643, 0x01000000, 0x00000002}, + {0x50575941, 0x02000000, 0x00000002}, + {0x50575942, 0x00800000, 0x00000001}, + {0x50575A41, 0x02000000, 0x00000002}, + {0x50583242, 0x02000000, 0x00000002}, + {0x50583341, 0x04000000, 0x00000001}, + {0x50583542, 0x02000000, 0x00000003}, + {0x50583559, 0x00800000, 0x00000008}, + {0x50583659, 0x00800000, 0x00000008}, + {0x50584142, 0x04000000, 0x00000001}, + {0x50584143, 0x02000000, 0x00000003}, + {0x50584154, 0x00800000, 0x00000001}, + {0x50584159, 0x02000000, 0x00000002}, + {0x50584241, 0x04000000, 0x00000002}, + {0x50584242, 0x00800000, 0x00000001}, + {0x50584259, 0x00800000, 0x00000001}, + {0x50584341, 0x01000000, 0x00000003}, + {0x50584343, 0x01000000, 0x00000003}, + {0x50584354, 0x00800000, 0x00000001}, + {0x50584443, 0x02000000, 0x00000001}, + {0x50584459, 0x04000000, 0x00000001}, + {0x50584559, 0x02000000, 0x00000002}, + {0x50584641, 0x08000000, 0x00000003}, + {0x50584642, 0x04000000, 0x00000002}, + {0x50584741, 0x08000000, 0x00000003}, + {0x50584742, 0x02000000, 0x00000002}, + {0x50584759, 0x08000000, 0x00000002}, + {0x50584841, 0x00800000, 0x00000001}, + {0x50584843, 0x02000000, 0x00000003}, + {0x50584859, 0x01000000, 0x00000001}, + {0x50584943, 0x00800000, 0x00000001}, + {0x50584A43, 0x01000000, 0x00000001}, + {0x50584A59, 0x00800000, 0x00000001}, + {0x50584C41, 0x02000000, 0x00000001}, + {0x50584C43, 0x02000000, 0x00000002}, + {0x50584C59, 0x00800000, 0x00000001}, + {0x50584D41, 0x02000000, 0x00000001}, + {0x50584D42, 0x02000000, 0x00000001}, + {0x50584D59, 0x00800000, 0x00000001}, + {0x50584E41, 0x02000000, 0x00000001}, + {0x50584F41, 0x02000000, 0x00000001}, + {0x50585043, 0x01000000, 0x00000005}, + {0x50585054, 0x00800000, 0x00000002}, + {0x50585059, 0x00800000, 0x00000003}, + {0x50585143, 0x04000000, 0x00000001}, + {0x50585159, 0x01000000, 0x00000001}, + {0x50585342, 0x02000000, 0x00000001}, + {0x50585359, 0x01000000, 0x00000001}, + {0x50585441, 0x01000000, 0x00000002}, + {0x50585543, 0x04000000, 0x00000001}, + {0x50585559, 0x04000000, 0x00000003}, + {0x50585641, 0x01000000, 0x00000001}, + {0x50585741, 0x01000000, 0x00000002}, + {0x50585742, 0x02000000, 0x00000001}, + {0x50585759, 0x01000000, 0x00000002}, + {0x50585859, 0x04000000, 0x00000002}, + {0x50585941, 0x08000000, 0x00000005}, + {0x50585942, 0x10000000, 0x00000003}, + {0x50585A42, 0x02000000, 0x00000001}, + {0x50585A59, 0x04000000, 0x00000002}, + {0x50593259, 0x00800000, 0x00000008}, + {0x50593341, 0x04000000, 0x00000003}, + {0x50593342, 0x02000000, 0x00000001}, + {0x50593443, 0x02000000, 0x00000001}, + {0x50593542, 0x01000000, 0x00000001}, + {0x50593641, 0x01000000, 0x00000002}, + {0x50593842, 0x02000000, 0x00000001}, + {0x50594143, 0x02000000, 0x00000001}, + {0x50594159, 0x02000000, 0x00000001}, + {0x50594242, 0x00800000, 0x00000001}, + {0x50594243, 0x02000000, 0x00000001}, + {0x50594259, 0x02000000, 0x00000001}, + {0x50594343, 0x01000000, 0x00000001}, + {0x50594359, 0x00800000, 0x00000001}, + {0x50594442, 0x04000000, 0x00000002}, + {0x50594443, 0x02000000, 0x00000002}, + {0x50594459, 0x00800000, 0x00000001}, + {0x50594542, 0x00800000, 0x00000001}, + {0x50594641, 0x04000000, 0x00000001}, + {0x50594659, 0x08000000, 0x00000005}, + {0x50594741, 0x04000000, 0x00000005}, + {0x50594742, 0x01000000, 0x00000001}, + {0x50594842, 0x02000000, 0x00000001}, + {0x50594843, 0x00000000, 0x00000001}, + {0x50594859, 0x01000000, 0x00000001}, + {0x50594943, 0x04000000, 0x00000002}, + {0x50594959, 0x01000000, 0x00000001}, + {0x50594A42, 0x04000000, 0x00000001}, + {0x50594A59, 0x00800000, 0x00000001}, + {0x50594B41, 0x02000000, 0x00000003}, + {0x50594B42, 0x02000000, 0x00000002}, + {0x50594C41, 0x04000000, 0x00000001}, + {0x50594C43, 0x02000000, 0x00000002}, + {0x50594C59, 0x02000000, 0x00000002}, + {0x50594D54, 0x00800000, 0x00000001}, + {0x50594D59, 0x08000000, 0x00000005}, + {0x50594E41, 0x04000000, 0x00000003}, + {0x50594E42, 0x04000000, 0x00000001}, + {0x50594E43, 0x08000000, 0x00000002}, + {0x50594E59, 0x00800000, 0x00000001}, + {0x50594F41, 0x02000000, 0x00000002}, + {0x50594F43, 0x00000000, 0x00000002}, + {0x50595041, 0x02000000, 0x00000002}, + {0x50595042, 0x00800000, 0x00000001}, + {0x50595056, 0x10000000, 0x00000005}, + {0x50595241, 0x02000000, 0x00000002}, + {0x50595243, 0x01000000, 0x00000001}, + {0x50595254, 0x02000000, 0x00000001}, + {0x50595342, 0x02000000, 0x00000002}, + {0x50595344, 0x02000000, 0x00000001}, + {0x50595359, 0x01000000, 0x00000001}, + {0x50595442, 0x01000000, 0x00000002}, + {0x50595443, 0x01000000, 0x00000002}, + {0x50595543, 0x02000000, 0x00000001}, + {0x50595642, 0x08000000, 0x00000001}, + {0x50595743, 0x02000000, 0x00000003}, + {0x50595842, 0x04000000, 0x00000002}, + {0x50595941, 0x01000000, 0x00000002}, + {0x50595942, 0x08000000, 0x00000003}, + {0x50595943, 0x00800000, 0x00000001}, + {0x50595A41, 0x04000000, 0x00000002}, + {0x505A3243, 0x00800000, 0x00000002}, + {0x505A3441, 0x00800000, 0x00000001}, + {0x505A3442, 0x08000000, 0x00000002}, + {0x505A3443, 0x04000000, 0x00000002}, + {0x505A3542, 0x01000000, 0x00000001}, + {0x505A3642, 0x04000000, 0x00000003}, + {0x505A3659, 0x08000000, 0x00000000}, + {0x505A3742, 0x04000000, 0x00000001}, + {0x505A3842, 0x01000000, 0x00000001}, + {0x505A4159, 0x01000000, 0x00000001}, + {0x505A4241, 0x08000000, 0x00000003}, + {0x505A4243, 0x01000000, 0x00000003}, + {0x505A4259, 0x01000000, 0x00000001}, + {0x505A4341, 0x01000000, 0x00000001}, + {0x505A4342, 0x01000000, 0x00000002}, + {0x505A4343, 0x00800000, 0x00000001}, + {0x505A4359, 0x00800000, 0x00000001}, + {0x505A4441, 0x02000000, 0x00000002}, + {0x505A4442, 0x04000000, 0x00000003}, + {0x505A4443, 0x04000000, 0x00000002}, + {0x505A4459, 0x01000000, 0x00000002}, + {0x505A4641, 0x04000000, 0x00000001}, + {0x505A4642, 0x00800000, 0x00000001}, + {0x505A4742, 0x01000000, 0x00000002}, + {0x505A4743, 0x00000000, 0x00000001}, + {0x505A4759, 0x04000000, 0x00000001}, + {0x505A4841, 0x04000000, 0x00000001}, + {0x505A4842, 0x02000000, 0x00000003}, + {0x505A4859, 0x04000000, 0x00000002}, + {0x505A4941, 0x02000000, 0x00000002}, + {0x505A4943, 0x02000000, 0x00000001}, + {0x505A4A59, 0x04000000, 0x00000005}, + {0x505A4C42, 0x02000000, 0x00000001}, + {0x505A4C43, 0x04000000, 0x00000001}, + {0x505A4C59, 0x10000000, 0x00000002}, + {0x505A4D42, 0x00800000, 0x00000002}, + {0x505A4D54, 0x01000000, 0x00000002}, + {0x505A4D56, 0x04000000, 0x00000001}, + {0x505A4E41, 0x01000000, 0x00000001}, + {0x505A4E42, 0x01000000, 0x00000001}, + {0x505A4E59, 0x04000000, 0x00000002}, + {0x505A4F41, 0x01000000, 0x00000002}, + {0x505A4F42, 0x02000000, 0x00000001}, + {0x505A4F59, 0x00000000, 0x00000002}, + {0x505A5042, 0x00000000, 0x00000001}, + {0x505A5059, 0x01000000, 0x00000001}, + {0x505A5143, 0x02000000, 0x00000001}, + {0x505A5241, 0x04000000, 0x00000002}, + {0x505A5242, 0x04000000, 0x00000003}, + {0x505A5243, 0x00800000, 0x00000002}, + {0x505A5259, 0x01000000, 0x00000002}, + {0x505A5359, 0x08000000, 0x00000001}, + {0x505A5442, 0x02000000, 0x00000001}, + {0x505A5459, 0x04000000, 0x00000001}, + {0x505A5541, 0x04000000, 0x00000005}, + {0x505A5542, 0x00800000, 0x00000002}, + {0x505A5543, 0x04000000, 0x00000001}, + {0x505A5759, 0x04000000, 0x00000001}, + {0x505A5A42, 0x01000000, 0x00000001}, + {0x51374C42, 0x04000000, 0x00000001}, + {0x51375042, 0x02000000, 0x00000001}, + {0x51375142, 0x02000000, 0x00000001}, + {0x51385042, 0x04000000, 0x00000001}, + {0x51435143, 0x02000000, 0x00000001}, + {0x51454642, 0x04000000, 0x00000001}, + {0x514C5542, 0x02000000, 0x00000001}, + {0x514F5542, 0x01000000, 0x00000001}, + {0x51503642, 0x02000000, 0x00000001}, + {0x51573542, 0x02000000, 0x00000001}, + {0x51584C42, 0x04000000, 0x00000008}, + {0x51585042, 0x04000000, 0x00000003}, + {0x51594C42, 0x04000000, 0x00000008}, + {0x52335741, 0x04000000, 0x00000001}, + {0x52464443, 0x04000000, 0x00000002}, + {0x53323643, 0x04000000, 0x00000001}, + {0x53335141, 0x04000000, 0x00000002}, + {0x53335159, 0x04000000, 0x00000002}, + {0x53344259, 0x02000000, 0x00000001}, + {0x53344C43, 0x04000000, 0x00000002}, + {0x53354841, 0x02000000, 0x00000002}, + {0x53394341, 0x04000000, 0x00000001}, + {0x53414441, 0x04000000, 0x00000006}, + {0x53415041, 0x04000000, 0x00000006}, + {0x53415249, 0x10000000, 0x00000006}, + {0x53424542, 0x10000000, 0x00000003}, + {0x53425249, 0x10000000, 0x00000006}, + {0x53434A42, 0x04000000, 0x00000002}, + {0x53434D43, 0x02000000, 0x00000002}, + {0x53435141, 0x04000000, 0x00000002}, + {0x53435259, 0x08000000, 0x00000002}, + {0x53435943, 0x02000000, 0x00000002}, + {0x53445249, 0x20000000, 0x00000006}, + {0x53445641, 0x01000000, 0x00000002}, + {0x53453231, 0x02000000, 0x00000003}, + {0x53453443, 0x04000000, 0x00000001}, + {0x53454343, 0x01000000, 0x00000005}, + {0x53454542, 0x10000000, 0x00000003}, + {0x53454559, 0x10000000, 0x00000003}, + {0x53454959, 0x02000000, 0x00000002}, + {0x53454C43, 0x04000000, 0x00000001}, + {0x53455249, 0x20000000, 0x00000006}, + {0x53464959, 0x02000000, 0x00000002}, + {0x53464B59, 0x02000000, 0x00000001}, + {0x53464C42, 0x10000000, 0x00000003}, + {0x53465359, 0x04000000, 0x00000001}, + {0x53474D41, 0x01000000, 0x00000001}, + {0x53474D43, 0x04000000, 0x00000001}, + {0x53475049, 0x08000000, 0x00000006}, + {0x534A3343, 0x10000000, 0x00000003}, + {0x534A5641, 0x04000000, 0x00000002}, + {0x534B4356, 0x08000000, 0x00000002}, + {0x534B5049, 0x08000000, 0x00000006}, + {0x534C4443, 0x02000000, 0x00000004}, + {0x534C4C43, 0x01000000, 0x00000002}, + {0x534D4359, 0x02000000, 0x00000001}, + {0x534F4359, 0x04000000, 0x00000001}, + {0x534F5342, 0x02000000, 0x00000001}, + {0x53504A59, 0x01000000, 0x00000001}, + {0x53505A55, 0x08000000, 0xFFFFFFFF}, + {0x53514142, 0x08000000, 0x00000002}, + {0x53525359, 0x01000000, 0x00000005}, + {0x53533341, 0x02000000, 0x00000001}, + {0x53534F41, 0x08000000, 0x00000005}, + {0x53535541, 0x04000000, 0x00000001}, + {0x53544C59, 0x08000000, 0x00000002}, + {0x53554259, 0x08000000, 0x00000003}, + {0x53555043, 0x08000000, 0x00000006}, + {0x53563543, 0x01000000, 0x00000001}, + {0x53564256, 0x02000000, 0x00000001}, + {0x53564E43, 0x10000000, 0x00000005}, + {0x53565841, 0x04000000, 0x00000003}, + {0x53574143, 0x04000000, 0x00000001}, + {0x53594641, 0x04000000, 0x00000001}, + {0x53594C41, 0x04000000, 0x00000001}, + {0x53595543, 0x02000000, 0x00000001}, + {0x53595A41, 0x04000000, 0x00000002}, + {0x535A4641, 0x04000000, 0x00000001}, + {0x535A5359, 0x08000000, 0x00000001}, + {0x54595056, 0x10000000, 0x00000005}, + {0x55414C59, 0x00800000, 0x00000002}, + {0x55425742, 0x04000000, 0x00000002}, + {0x55434956, 0x04000000, 0x00000002}, + {0x55435243, 0x02000000, 0x00000001}, + {0x55444E41, 0x00800000, 0x00000008}, + {0x55454342, 0x02000000, 0x00000002}, + {0x55463343, 0x02000000, 0x00000002}, + {0x554A5243, 0x02000000, 0x00000001}, + {0x55504A59, 0x01000000, 0x00000001}, + {0x55515243, 0x02000000, 0x00000001}, + {0x55524542, 0x02000000, 0x00000001}, + {0x55525342, 0x01000000, 0x00000001}, + {0x55544256, 0x02000000, 0x00000002}, + {0x55545942, 0x04000000, 0x00000002}, + {0x55573341, 0x04000000, 0x00000002}, + {0x55574C41, 0x02000000, 0x00000001}, + {0x56324356, 0x02000000, 0x00000001}, + {0x56324456, 0x04000000, 0x00000001}, + {0x56324D56, 0x04000000, 0x00000002}, + {0x56335356, 0x08000000, 0x00000005}, + {0x56335456, 0x04000000, 0x00000001}, + {0x56345456, 0x04000000, 0x00000003}, + {0x56364356, 0x02000000, 0x00000002}, + {0x56394856, 0x04000000, 0x00000002}, + {0x56395056, 0x04000000, 0x00000001}, + {0x56413956, 0x02000000, 0x00000000}, + {0x56414156, 0x02000000, 0x00000008}, + {0x56414256, 0x02000000, 0x00000001}, + {0x56414356, 0x04000000, 0x00000001}, + {0x56414C56, 0x04000000, 0x00000002}, + {0x56434156, 0x04000000, 0x00000002}, + {0x56434D56, 0x02000000, 0x00000001}, + {0x56444356, 0x04000000, 0x00000002}, + {0x56444956, 0x02000000, 0x00000002}, + {0x56455056, 0x04000000, 0x00000001}, + {0x56455456, 0x04000000, 0x00000002}, + {0x56464956, 0x02000000, 0x00000002}, + {0x56465056, 0x04000000, 0x00000001}, + {0x56473256, 0x02000000, 0x00000006}, + {0x56475256, 0x02000000, 0x00000002}, + {0x56494C56, 0x02000000, 0x00000001}, + {0x56495256, 0x02000000, 0x00000001}, + {0x564A4956, 0x08000000, 0x00000003}, + {0x564B4356, 0x08000000, 0x00000002}, + {0x564B4D56, 0x02000000, 0x00000003}, + {0x564B5355, 0x08000000, 0xFFFFFFFF}, + {0x564B5356, 0x04000000, 0x00000001}, + {0x564C4156, 0x04000000, 0x00000002}, + {0x564C4256, 0x02000000, 0x00000002}, + {0x564C4556, 0x02000000, 0x00000003}, + {0x564D4356, 0x04000000, 0x00000002}, + {0x564E5356, 0x04000000, 0x00000002}, + {0x564F4156, 0x04000000, 0x00000001}, + {0x564F5356, 0x04000000, 0x00000003}, + {0x56505056, 0x02000000, 0x00000001}, + {0x56505256, 0x02000000, 0x00000001}, + {0x56505456, 0x08000000, 0x00000002}, + {0x56524756, 0x04000000, 0x00000001}, + {0x56534256, 0x02000000, 0x00000001}, + {0x56534556, 0x04000000, 0x00000001}, + {0x56534656, 0x08000000, 0x00000003}, + {0x56534844, 0x02000000, 0xFFFFFFFF}, + {0x56544156, 0x02000000, 0x00000001}, + {0x56554B56, 0x04000000, 0x00000001}, + {0x56555A56, 0x02000000, 0x00000002}, + {0x56564156, 0x04000000, 0x00000001}, + {0x56564256, 0x02000000, 0x00000001}, + {0x56564A56, 0x04000000, 0x00000001}, + {0x56565056, 0x04000000, 0x00000002}, + {0x56565756, 0x04000000, 0x00000001}, + {0x56574356, 0x02000000, 0x00000002}, + {0x56574856, 0x04000000, 0x00000002}, + {0x56574A56, 0x02000000, 0x00000003}, + {0x56594D56, 0x04000000, 0x00000001}, + {0x565A4656, 0x02000000, 0x00000001}, + {0x565A4D56, 0x04000000, 0x00000001}, + {0x57325141, 0x02000000, 0x00000002}, + {0x57334941, 0x01000000, 0x00000002}, + {0x57414356, 0x04000000, 0x00000001}, + {0x57414E43, 0x04000000, 0x00000001}, + {0x57445759, 0x01000000, 0x00000002}, + {0x57474C43, 0x04000000, 0x00000001}, + {0x574C5759, 0x02000000, 0x00000001}, + {0x57565141, 0x01000000, 0x00000002}, + {0x575A5242, 0x04000000, 0x00000003}, + {0x58324354, 0x00800000, 0x00000001}, + {0x58324842, 0x02000000, 0x00000003}, + {0x58324859, 0x02000000, 0x00000003}, + {0x58324B41, 0x04000000, 0x00000001}, + {0x58324D56, 0x04000000, 0x00000002}, + {0x58325141, 0x02000000, 0x00000002}, + {0x58325241, 0x02000000, 0x00000003}, + {0x58325341, 0x01000000, 0x00000001}, + {0x58334242, 0x00000000, 0x00000001}, + {0x58334542, 0x04000000, 0x00000001}, + {0x58334759, 0x02000000, 0x00000003}, + {0x58334841, 0x04000000, 0x00000003}, + {0x58334941, 0x01000000, 0x00000002}, + {0x58334943, 0x04000000, 0x00000001}, + {0x58334C41, 0x02000000, 0x00000001}, + {0x58335456, 0x04000000, 0x00000001}, + {0x58343242, 0x00800000, 0x00000001}, + {0x58344A43, 0x01000000, 0x00000001}, + {0x58345442, 0x01000000, 0x00000008}, + {0x58345741, 0x02000000, 0x00000002}, + {0x58354259, 0x02000000, 0x00000002}, + {0x58354A42, 0x02000000, 0x00000001}, + {0x58354D54, 0x04000000, 0x00000003}, + {0x58355059, 0x10000000, 0x00000001}, + {0x58355142, 0x04000000, 0x00000001}, + {0x58355243, 0x10000000, 0x00000001}, + {0x58355259, 0x02000000, 0x00000002}, + {0x58355343, 0x04000000, 0x00000001}, + {0x58363559, 0x04000000, 0x00000008}, + {0x58364254, 0x02000000, 0x00000001}, + {0x58364341, 0x01000000, 0x00000002}, + {0x58365259, 0x00000000, 0x00000002}, + {0x58374943, 0x04000000, 0x00000002}, + {0x58374A42, 0x00800000, 0x00000001}, + {0x58374C42, 0x04000000, 0x00000001}, + {0x58375042, 0x02000000, 0x00000001}, + {0x58384442, 0x04000000, 0x00000001}, + {0x58384843, 0x02000000, 0x00000001}, + {0x58384D41, 0x01000000, 0x00000001}, + {0x58385741, 0x04000000, 0x00000001}, + {0x58385742, 0x01000000, 0x00000001}, + {0x58385859, 0x08000000, 0x00000001}, + {0x58394259, 0x02000000, 0x00000003}, + {0x58394943, 0x01000000, 0x00000002}, + {0x58394D59, 0x01000000, 0x00000001}, + {0x58395056, 0x04000000, 0x00000001}, + {0x58395141, 0x04000000, 0x00000001}, + {0x58395341, 0x02000000, 0x00000001}, + {0x58395759, 0x08000000, 0x00000001}, + {0x58413541, 0x04000000, 0x00000001}, + {0x58414243, 0x02000000, 0x00000001}, + {0x58414356, 0x04000000, 0x00000001}, + {0x58414643, 0x08000000, 0x00000002}, + {0x58414E43, 0x04000000, 0x00000001}, + {0x58415141, 0x02000000, 0x00000001}, + {0x58415243, 0x00800000, 0x00000001}, + {0x58415359, 0x01000000, 0x00000002}, + {0x58415459, 0x04000000, 0x00000001}, + {0x58415A43, 0x02000000, 0x00000002}, + {0x58423242, 0x08000000, 0x00000002}, + {0x58423542, 0x08000000, 0x00000002}, + {0x58424254, 0x02000000, 0x00000001}, + {0x58424654, 0x01000000, 0x00000001}, + {0x58424743, 0x02000000, 0x00000001}, + {0x58424A43, 0x01000000, 0x00000001}, + {0x58424B43, 0x02000000, 0x00000002}, + {0x58425342, 0x04000000, 0x00000003}, + {0x58425442, 0x04000000, 0x00000002}, + {0x58425742, 0x04000000, 0x00000002}, + {0x58433342, 0x04000000, 0x00000002}, + {0x58433441, 0x02000000, 0x00000003}, + {0x58434341, 0x02000000, 0x00000001}, + {0x58434542, 0x01000000, 0x00000003}, + {0x58434642, 0x02000000, 0x00000001}, + {0x58434741, 0x04000000, 0x00000003}, + {0x58434941, 0x01000000, 0x00000001}, + {0x58435043, 0x01000000, 0x00000002}, + {0x58435143, 0x02000000, 0x00000001}, + {0x58435359, 0x02000000, 0x00000001}, + {0x58435842, 0x01000000, 0x00000001}, + {0x58443743, 0x04000000, 0x00000001}, + {0x58444359, 0x01000000, 0x00000001}, + {0x58444642, 0x00000000, 0x00000001}, + {0x58444842, 0x04000000, 0x00000001}, + {0x58444A54, 0x01000000, 0x00000001}, + {0x58444B42, 0x00800000, 0x00000001}, + {0x58445054, 0x08000000, 0x00000001}, + {0x58445759, 0x01000000, 0x00000002}, + {0x58453242, 0x00800000, 0x00000001}, + {0x58453442, 0x01000000, 0x00000001}, + {0x58454543, 0x00800000, 0x00000001}, + {0x58454C43, 0x04000000, 0x00000001}, + {0x58455056, 0x04000000, 0x00000001}, + {0x58455141, 0x00800000, 0x00000002}, + {0x58455143, 0x04000000, 0x00000002}, + {0x58455456, 0x04000000, 0x00000002}, + {0x58455542, 0x02000000, 0x00000001}, + {0x58463642, 0x08000000, 0x00000001}, + {0x58464143, 0x01000000, 0x00000001}, + {0x58464243, 0x08000000, 0x00000003}, + {0x58464541, 0x00800000, 0x00000001}, + {0x58464A42, 0x08000000, 0x00000003}, + {0x58465956, 0x02000000, 0x00000001}, + {0x58465A42, 0x04000000, 0x00000001}, + {0x58473241, 0x02000000, 0x00000003}, + {0x58474142, 0x01000000, 0x00000001}, + {0x58474143, 0x02000000, 0x00000001}, + {0x58474342, 0x04000000, 0x00000002}, + {0x58474354, 0x04000000, 0x00000001}, + {0x58474542, 0x00800000, 0x00000001}, + {0x58475742, 0x04000000, 0x00000001}, + {0x58475956, 0x04000000, 0x00000001}, + {0x58483343, 0x00800000, 0x00000001}, + {0x58483842, 0x04000000, 0x00000002}, + {0x58484759, 0x08000000, 0x00000001}, + {0x58484A42, 0x01000000, 0x00000001}, + {0x58484C41, 0x02000000, 0x00000001}, + {0x58485243, 0x00000000, 0x00000002}, + {0x58485254, 0x02000000, 0x00000001}, + {0x58485641, 0x04000000, 0x00000002}, + {0x58485A59, 0x04000000, 0x00000001}, + {0x58493642, 0x04000000, 0x00000002}, + {0x58494442, 0x04000000, 0x00000001}, + {0x58494641, 0x02000000, 0x00000002}, + {0x58494942, 0x00800000, 0x00000001}, + {0x58494C43, 0x04000000, 0x00000001}, + {0x58495259, 0x04000000, 0x00000002}, + {0x58495442, 0x01000000, 0x00000001}, + {0x584A4841, 0x01000000, 0x00000002}, + {0x584A4D54, 0x02000000, 0x00000001}, + {0x584A5143, 0x00800000, 0x00000001}, + {0x584B3443, 0x00800000, 0x00000001}, + {0x584B3842, 0x02000000, 0x00000002}, + {0x584B4143, 0x04000000, 0x00000002}, + {0x584B4243, 0x04000000, 0x00000002}, + {0x584B4541, 0x04000000, 0x00000002}, + {0x584B4642, 0x04000000, 0x00000001}, + {0x584B4B41, 0x02000000, 0x00000003}, + {0x584B4C42, 0x04000000, 0x00000001}, + {0x584B5356, 0x04000000, 0x00000001}, + {0x584B5559, 0x04000000, 0x00000001}, + {0x584C4643, 0x02000000, 0x00000002}, + {0x584C4A59, 0x01000000, 0x00000002}, + {0x584C4E59, 0x04000000, 0x00000001}, + {0x584C5059, 0x00800000, 0x00000001}, + {0x584C5242, 0x02000000, 0x00000001}, + {0x584C5342, 0x02000000, 0x00000003}, + {0x584C5543, 0x04000000, 0x00000001}, + {0x584C5759, 0x02000000, 0x00000001}, + {0x584C5941, 0x02000000, 0x00000002}, + {0x584C5959, 0x04000000, 0x00000002}, + {0x584D3243, 0x02000000, 0x00000002}, + {0x584D3442, 0x02000000, 0x00000001}, + {0x584D4359, 0x02000000, 0x00000001}, + {0x584D4842, 0x02000000, 0x00000001}, + {0x584D4A54, 0x00800000, 0x00000001}, + {0x584D4C42, 0x01000000, 0x00000001}, + {0x584D4E42, 0x04000000, 0x00000001}, + {0x584D5642, 0x02000000, 0x00000001}, + {0x584D5842, 0x04000000, 0x00000002}, + {0x584E3743, 0x04000000, 0x00000001}, + {0x584E4354, 0x01000000, 0x00000001}, + {0x584E4559, 0x00800000, 0x00000001}, + {0x584E4641, 0x02000000, 0x00000002}, + {0x584E5159, 0x04000000, 0x00000002}, + {0x584F3543, 0x01000000, 0x00000001}, + {0x584F3642, 0x02000000, 0x00000001}, + {0x584F3743, 0x04000000, 0x00000002}, + {0x584F4142, 0x04000000, 0x00000001}, + {0x584F4156, 0x04000000, 0x00000001}, + {0x584F4442, 0x01000000, 0x00000001}, + {0x584F4D59, 0x04000000, 0x00000001}, + {0x584F5542, 0x02000000, 0x00000001}, + {0x584F5741, 0x02000000, 0x00000002}, + {0x584F5841, 0x01000000, 0x00000002}, + {0x584F5843, 0x04000000, 0x00000001}, + {0x58503541, 0x04000000, 0x00000001}, + {0x58504259, 0x02000000, 0x00000001}, + {0x58504342, 0x04000000, 0x00000002}, + {0x58504442, 0x02000000, 0x00000001}, + {0x58504B59, 0x01000000, 0x00000001}, + {0x58504F43, 0x01000000, 0x00000003}, + {0x58505343, 0x02000000, 0x00000003}, + {0x58513543, 0x01000000, 0x00000002}, + {0x58513643, 0x08000000, 0x00000001}, + {0x58514559, 0x01000000, 0x00000001}, + {0x58514A59, 0x01000000, 0x00000001}, + {0x58514C42, 0x02000000, 0x00000001}, + {0x58514D43, 0x02000000, 0x00000001}, + {0x58514D59, 0x02000000, 0x00000001}, + {0x58515459, 0x01000000, 0x00000001}, + {0x58523559, 0x04000000, 0x00000008}, + {0x58523743, 0x00800000, 0x00000001}, + {0x58524354, 0x00800000, 0x00000001}, + {0x58524459, 0x01000000, 0x00000001}, + {0x58524842, 0x02000000, 0x00000001}, + {0x58524943, 0x04000000, 0x00000002}, + {0x58524A42, 0x01000000, 0x00000001}, + {0x58524C54, 0x08000000, 0x00000001}, + {0x58524D42, 0x02000000, 0x00000001}, + {0x58525042, 0x00800000, 0x00000001}, + {0x58525141, 0x01000000, 0x00000002}, + {0x58525642, 0x04000000, 0x00000001}, + {0x58525843, 0x04000000, 0x00000001}, + {0x58533841, 0x00800000, 0x00000002}, + {0x58534342, 0x04000000, 0x00000002}, + {0x58534556, 0x04000000, 0x00000001}, + {0x58534642, 0x04000000, 0x00000001}, + {0x58534643, 0x02000000, 0x00000001}, + {0x58534743, 0x08000000, 0x00000001}, + {0x58534A54, 0x00800000, 0x00000001}, + {0x58534E43, 0x04000000, 0x00000002}, + {0x58535143, 0x02000000, 0x00000001}, + {0x58543341, 0x02000000, 0x00000002}, + {0x58543642, 0x04000000, 0x00000001}, + {0x58543743, 0x01000000, 0x00000002}, + {0x58544256, 0x02000000, 0x00000002}, + {0x58544D59, 0x02000000, 0x00000002}, + {0x58545054, 0x08000000, 0x00000001}, + {0x58545259, 0x02000000, 0x00000002}, + {0x58545A41, 0x01000000, 0x00000005}, + {0x58554159, 0x04000000, 0x00000003}, + {0x58554242, 0x04000000, 0x00000003}, + {0x58554341, 0x08000000, 0x00000005}, + {0x58554454, 0x01000000, 0x00000001}, + {0x58554643, 0x00000000, 0x00000002}, + {0x58554E42, 0x01000000, 0x00000001}, + {0x58555442, 0x04000000, 0x00000002}, + {0x58555841, 0x02000000, 0x00000001}, + {0x58564142, 0x04000000, 0x00000001}, + {0x58564159, 0x04000000, 0x00000002}, + {0x58564343, 0x01000000, 0x00000001}, + {0x58564854, 0x04000000, 0x00000001}, + {0x58564B42, 0x00800000, 0x00000001}, + {0x58564D42, 0x00800000, 0x00000001}, + {0x58565141, 0x01000000, 0x00000002}, + {0x58573241, 0x04000000, 0x00000001}, + {0x58573341, 0x04000000, 0x00000002}, + {0x58573742, 0x01000000, 0x00000002}, + {0x58574443, 0x01000000, 0x00000001}, + {0x58574859, 0x02000000, 0x00000001}, + {0x58574942, 0x04000000, 0x00000002}, + {0x58574C41, 0x02000000, 0x00000001}, + {0x58574D42, 0x04000000, 0x00000002}, + {0x58575141, 0x02000000, 0x00000001}, + {0x58575343, 0x04000000, 0x00000001}, + {0x58575942, 0x00800000, 0x00000001}, + {0x58584254, 0x04000000, 0x00000002}, + {0x58584C41, 0x02000000, 0x00000001}, + {0x58584D59, 0x00800000, 0x00000001}, + {0x58585043, 0x01000000, 0x00000005}, + {0x58594159, 0x02000000, 0x00000001}, + {0x58594259, 0x02000000, 0x00000001}, + {0x58594443, 0x02000000, 0x00000002}, + {0x58594741, 0x04000000, 0x00000003}, + {0x58594842, 0x02000000, 0x00000001}, + {0x58594943, 0x04000000, 0x00000002}, + {0x58594A42, 0x04000000, 0x00000001}, + {0x58594E42, 0x04000000, 0x00000001}, + {0x58595543, 0x02000000, 0x00000001}, + {0x585A3242, 0x00800000, 0x00000001}, + {0x585A3742, 0x04000000, 0x00000001}, + {0x585A4341, 0x01000000, 0x00000001}, + {0x585A4A59, 0x04000000, 0x00000005}, + {0x585A4C59, 0x10000000, 0x00000002}, + {0x585A4D56, 0x04000000, 0x00000001}, + {0x585A5059, 0x01000000, 0x00000001}, + {0x585A5242, 0x04000000, 0x00000003}, + {0x585A5243, 0x00800000, 0x00000002}, + {0x585A5442, 0x04000000, 0x00000001}, + {0x59325141, 0x02000000, 0x00000002}, + {0x59334242, 0x08000000, 0x00000001}, + {0x59334759, 0x02000000, 0x00000003}, + {0x59334941, 0x01000000, 0x00000002}, + {0x59334943, 0x04000000, 0x00000001}, + {0x59334C41, 0x02000000, 0x00000001}, + {0x59345741, 0x02000000, 0x00000002}, + {0x59354A42, 0x02000000, 0x00000001}, + {0x59355142, 0x08000000, 0x00000001}, + {0x59364341, 0x01000000, 0x00000002}, + {0x59374943, 0x00000000, 0x00000002}, + {0x59394259, 0x02000000, 0x00000003}, + {0x59395056, 0x04000000, 0x00000001}, + {0x59414356, 0x04000000, 0x00000001}, + {0x59414643, 0x08000000, 0x00000002}, + {0x59414E43, 0x04000000, 0x00000001}, + {0x59415359, 0x01000000, 0x00000002}, + {0x59415459, 0x04000000, 0x00000001}, + {0x59425442, 0x04000000, 0x00000002}, + {0x59425742, 0x04000000, 0x00000002}, + {0x59434741, 0x04000000, 0x00000003}, + {0x59443442, 0x01000000, 0x00000001}, + {0x59444642, 0x00800000, 0x00000001}, + {0x59445054, 0x08000000, 0x00000001}, + {0x59453442, 0x01000000, 0x00000001}, + {0x59454259, 0x08000000, 0x00000003}, + {0x59454543, 0x00800000, 0x00000001}, + {0x59454C43, 0x04000000, 0x00000001}, + {0x59455056, 0x04000000, 0x00000001}, + {0x59455143, 0x04000000, 0x00000002}, + {0x59455542, 0x02000000, 0x00000001}, + {0x59463642, 0x08000000, 0x00000001}, + {0x59465042, 0x04000000, 0x00000002}, + {0x59474354, 0x04000000, 0x00000001}, + {0x59474C43, 0x04000000, 0x00000001}, + {0x59484A42, 0x01000000, 0x00000001}, + {0x59484C41, 0x02000000, 0x00000001}, + {0x59495443, 0x02000000, 0x00000002}, + {0x594A4841, 0x01000000, 0x00000002}, + {0x594A4D54, 0x02000000, 0x00000001}, + {0x594B5356, 0x04000000, 0x00000001}, + {0x594C4A59, 0x01000000, 0x00000002}, + {0x594C4E59, 0x04000000, 0x00000001}, + {0x594C5759, 0x02000000, 0x00000001}, + {0x594E4641, 0x02000000, 0x00000002}, + {0x594E4654, 0x04000000, 0x00000002}, + {0x594E5159, 0x04000000, 0x00000002}, + {0x594F5841, 0x01000000, 0x00000002}, + {0x59504442, 0x02000000, 0x00000001}, + {0x59513642, 0x00800000, 0x00000001}, + {0x59514559, 0x01000000, 0x00000001}, + {0x59514D59, 0x02000000, 0x00000001}, + {0x59524254, 0x04000000, 0x00000001}, + {0x59524459, 0x01000000, 0x00000001}, + {0x59524842, 0x02000000, 0x00000001}, + {0x59524C54, 0x08000000, 0x00000001}, + {0x59533841, 0x00800000, 0x00000002}, + {0x59545054, 0x08000000, 0x00000001}, + {0x59545259, 0x02000000, 0x00000002}, + {0x59545A41, 0x01000000, 0x00000005}, + {0x59554242, 0x04000000, 0x00000003}, + {0x59554341, 0x08000000, 0x00000005}, + {0x59554B56, 0x04000000, 0x00000001}, + {0x59554D42, 0x04000000, 0x00000001}, + {0x59555154, 0x00800000, 0x00000001}, + {0x59555442, 0x04000000, 0x00000002}, + {0x59564854, 0x04000000, 0x00000001}, + {0x59565141, 0x01000000, 0x00000002}, + {0x59573241, 0x04000000, 0x00000001}, + {0x59574443, 0x01000000, 0x00000001}, + {0x59574C41, 0x02000000, 0x00000001}, + {0x59574D42, 0x04000000, 0x00000002}, + {0x59594159, 0x02000000, 0x00000001}, + {0x59594254, 0x04000000, 0x00000002}, + {0x59594442, 0x08000000, 0x00000002}, + {0x59594E42, 0x04000000, 0x00000001}, + {0x595A4341, 0x01000000, 0x00000001}, + {0x595A4A59, 0x04000000, 0x00000005}, + {0x595A5059, 0x01000000, 0x00000001}, + {0x595A5242, 0x04000000, 0x00000003}, + {0x595A5442, 0x04000000, 0x00000001}, + {0x595A5443, 0x02000000, 0x00000003}, + {0x5A325141, 0x02000000, 0x00000002}, + {0x5A334941, 0x01000000, 0x00000002}, + {0x5A335456, 0x04000000, 0x00000001}, + {0x5A345741, 0x02000000, 0x00000002}, + {0x5A353859, 0x00800000, 0x00000008}, + {0x5A374943, 0x04000000, 0x00000002}, + {0x5A414356, 0x04000000, 0x00000001}, + {0x5A424259, 0x02000000, 0x00000001}, + {0x5A445759, 0x01000000, 0x00000002}, + {0x5A454259, 0x08000000, 0x00000003}, + {0x5A475956, 0x04000000, 0x00000001}, + {0x5A4A3642, 0x00800000, 0x00000001}, + {0x5A4A3959, 0x00800000, 0x00000008}, + {0x5A4C4E59, 0x04000000, 0x00000001}, + {0x5A4C5759, 0x02000000, 0x00000001}, + {0x5A4C5959, 0x04000000, 0x00000002}, + {0x5A4D4842, 0x02000000, 0x00000001}, + {0x5A4F3959, 0x00800000, 0x00000000}, + {0x5A513642, 0x00800000, 0x00000001}, + {0x5A523642, 0x08000000, 0x00000002}, + {0x5A544D59, 0x02000000, 0x00000002}, + {0x5A545054, 0x08000000, 0x00000001}, + {0x5A554242, 0x04000000, 0x00000003}, + {0x5A565141, 0x01000000, 0x00000002}, + {0x5A574C41, 0x02000000, 0x00000001}, + {0x5A595543, 0x02000000, 0x00000001}, + {0x5A5A4254, 0x04000000, 0x00000002}, + {0x5A5A4341, 0x01000000, 0x00000001}, + {0x5A5A5242, 0x04000000, 0x00000003}, +}; + +#endif // ROMLIST_H diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 8df6ec87..a3207c74 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1900,39 +1900,6 @@ int main(int argc, char** argv) SANITIZE(Config::ScreenSizing, 0, 3); #undef SANITIZE - // TODO: this should be checked before running anything -#if 0 - { - const char* romlist_missing = "Save memory type detection will not work correctly.\n\n" - "You should use the latest version of romlist.bin (provided in melonDS release packages)."; -#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) - std::string missingstr = std::string(romlist_missing) + - "\n\nThe ROM list should be placed in " + g_get_user_data_dir() + "/melonds/, otherwise " - "melonDS will search for it in the current working directory."; - const char* romlist_missing_text = missingstr.c_str(); -#else - const char* romlist_missing_text = romlist_missing; -#endif - - FILE* f = Platform::OpenDataFile("romlist.bin"); - if (f) - { - u32 data; - fread(&data, 4, 1, f); - fclose(f); - - if ((data >> 24) == 0) // old CRC-based list - { - uiMsgBoxError(NULL, "Your version of romlist.bin is outdated.", romlist_missing_text); - } - } - else - { - uiMsgBoxError(NULL, "romlist.bin not found.", romlist_missing_text); - } - } -#endif - QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); From b27ed541bb992d2e296ab3e9884e9cd2e67f45cc Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 30 May 2020 00:38:31 +0200 Subject: [PATCH 102/105] blarg --- src/frontend/qt_sdl/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 37a8ff1a..62d6e601 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -110,5 +110,4 @@ install(FILES ../../../icon/melon_48x48.png DESTINATION ${CMAKE_INSTALL_PREFIX}/ install(FILES ../../../icon/melon_64x64.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/64x64/apps RENAME net.kuribo64.melonDS.png) install(FILES ../../../icon/melon_128x128.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/128x128/apps RENAME net.kuribo64.melonDS.png) install(FILES ../../../icon/melon_256x256.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/256x256/apps RENAME net.kuribo64.melonDS.png) -install(FILES ../../../romlist.bin DESTINATION ${CMAKE_INSTALL_PREFIX}/share/melonDS) install(TARGETS melonDS RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) From 0a8e14519ea0e3865b833127aeaa2a37bb602b33 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 30 May 2020 00:42:15 +0200 Subject: [PATCH 103/105] now hopefully all references to romlist.bin are removed --- msys-dist.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/msys-dist.sh b/msys-dist.sh index f2e59418..01b2ade6 100755 --- a/msys-dist.sh +++ b/msys-dist.sh @@ -10,5 +10,3 @@ mkdir -p dist for lib in $(ldd melonDS.exe | grep mingw | sed "s/.*=> //" | sed "s/(.*)//"); do cp "${lib}" dist done - -cp melonDS.exe romlist.bin dist From b3fad6f819ab1cc3f0b67194a40d73256850dcdf Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 30 May 2020 00:51:50 +0200 Subject: [PATCH 104/105] asaddazs sneaky bastard --- .github/workflows/build-ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index 6071e33e..e9307e92 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -40,7 +40,7 @@ jobs: run: | make -j$(nproc --all) \ && mkdir dist \ - && cp {melonDS,romlist.bin} dist + && cp {melonDS} dist - uses: actions/upload-artifact@v1 with: name: melonDS From 993048dd241b59747a7b30edfc861eedd4c005c9 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 30 May 2020 00:55:34 +0200 Subject: [PATCH 105/105] ASGHAFGSHASHJKQHD --- .github/workflows/build-ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index e9307e92..efb96048 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -40,7 +40,7 @@ jobs: run: | make -j$(nproc --all) \ && mkdir dist \ - && cp {melonDS} dist + && cp melonDS dist - uses: actions/upload-artifact@v1 with: name: melonDS